SSM-SpringMVC-04:SpringMVC深入浅出理解HandleMapping(源码刨析)

Posted 晨曦Dawn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSM-SpringMVC-04:SpringMVC深入浅出理解HandleMapping(源码刨析)相关的知识,希望对你有一定的参考价值。

 

------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥-------------

 

 

先从概念理解,从中央调度器,携带参数request,调度到HandleMapping处理器映射器,处理器映射器返回处理器执行链给中央调度器

 

我从底层走一遍,印证这个概念:

  1.都说是中央调度器的,所以先找到中央调度器DispatcherServlet

  2.从他里面找到一个方法   ctrl+f 找(doDistch)

 

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            try {
                ModelAndView err = null;
                Exception dispatchException = null;

                try {
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    mappedHandler = this.getHandler(processedRequest);
                    if(mappedHandler == null || mappedHandler.getHandler() == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }

                    HandlerAdapter ex = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if(isGet || "HEAD".equals(method)) {
                        long lastModified = ex.getLastModified(request, mappedHandler.getHandler());
                        if(this.logger.isDebugEnabled()) {
                            this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                        }

                        if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }

                    if(!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }

                    err = ex.handle(processedRequest, response, mappedHandler.getHandler());
                    if(asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, err);
                    mappedHandler.applyPostHandle(processedRequest, response, err);
                } catch (Exception var19) {
                    dispatchException = var19;
                }

                this.processDispatchResult(processedRequest, response, mappedHandler, err, dispatchException);
            } catch (Exception var20) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20);
            } catch (Error var21) {
                this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var21);
            }

        } finally {
            if(asyncManager.isConcurrentHandlingStarted()) {
                if(mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            } else if(multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
    }

 

    这个方法里面很多内容不需要关注,需要关注的的我讲讲

        HttpServletRequest processedRequest = request;
        //接收请求
        HandlerExecutionChain mappedHandler = null;
        //处理器执行链
        boolean multipartRequestParsed = false;
        //多部分请求,文件上传
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        //异部请求

        try {
            try {
               
                ModelAndView err = null;
                 //视图解析

                try {
                    
                    processedRequest = this.checkMultipart(request);
                    //检查是否是多部分请求
                    multipartRequestParsed = processedRequest != request;
                    
                    mappedHandler = this.getHandler(processedRequest);   
                     //这就返回处理器执行链

  3.到这儿,点击getHandler(processedRequest)查看

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        Iterator var2 = this.handlerMappings.iterator();

        HandlerExecutionChain handler;
        do {
            if(!var2.hasNext()) {
                return null;
            }

            HandlerMapping hm = (HandlerMapping)var2.next();
            if(this.logger.isTraceEnabled()) {
                this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name \‘" + this.getServletName() + "\‘");
            }

            handler = hm.getHandler(request);
        } while(handler == null);

        return handler;
    }

    我把关键代码提炼出来解释一波

        //迭代器,没做泛型,handlerMapping是list集合
        Iterator var2 = this.handlerMappings.iterator();
        //处理器执行链
        HandlerExecutionChain handler;
        do {
            if(!var2.hasNext()) {
                return null;
            }
            //处理器映射器
            HandlerMapping hm = (HandlerMapping)var2.next();
           
            //继续追踪
            handler = hm.getHandler(request);
        } while(handler == null);

        return handler;    

  4.追踪hm.getHandler(request)方法,发现他是HandlerMapping接口的,(Ctrl+H)找它的实现类AbstractHandlerMapping,ctrl+F找getHandler

    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        Object handler = this.getHandlerInternal(request);
        if(handler == null) {
            handler = this.getDefaultHandler();
        }

        if(handler == null) {
            return null;
        } else {
            if(handler instanceof String) {
                String executionChain = (String)handler;
                handler = this.getApplicationContext().getBean(executionChain);
            }

            HandlerExecutionChain executionChain1 = this.getHandlerExecutionChain(handler, request);
            if(CorsUtils.isCorsRequest(request)) {
                CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
                CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
                CorsConfiguration config = globalConfig != null?globalConfig.combine(handlerConfig):handlerConfig;
                executionChain1 = this.getCorsHandlerExecutionChain(request, executionChain1, config);
            }

            return executionChain1;
        }
    }

    同样,我把关键代码提出来解释一波

    //获取处理器
        Object handler = this.getHandlerInternal(request);
        //处理器为空就用默认的
        if(handler == null) {
            handler = this.getDefaultHandler();
        }
        //默认的也是空就返回null
        if(handler == null) {
            return null;
        } else {
            //判断是否是String类型
            if(handler instanceof String) {
                //这儿就是我们一般用的处理器的从配置文件bean的id
                String handlerName = (String)handler;  //  /hello
                //这就是Spring啊
                handler = this.getApplicationContext().getBean(handlerName);
            }
        //获取处理程序执行链
        HandlerExecutionChain executionChain1 = this.getHandlerExecutionChain(handler, request);
    //返回的时候变成携带处理器的了 
  
    return this.getHandlerExecutionChain(handler, request); }

  5.追踪获取程序执行链,this.getHandlerExecutionChain(handler,request)

    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        //三元表达式,是处理器执行链就强转,不是就获取根据处理器生成一个
        HandlerExecutionChain chain = handler instanceof HandlerExecutionChain?(HandlerExecutionChain)handler:new HandlerExecutionChain(handler);
        String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
        Iterator var5 = this.adaptedInterceptors.iterator();

        while(var5.hasNext()) {

            //只需要知道这儿添加拦截器即可
            HandlerInterceptor interceptor = (HandlerInterceptor)var5.next();
            if(interceptor instanceof MappedInterceptor) {
                MappedInterceptor mappedInterceptor = (MappedInterceptor)interceptor;
                if(mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                    chain.addInterceptor(mappedInterceptor.getInterceptor());
                }
            } else {
                chain.addInterceptor(interceptor);
            }
        }

        return chain;
    }

 





以上是关于SSM-SpringMVC-04:SpringMVC深入浅出理解HandleMapping(源码刨析)的主要内容,如果未能解决你的问题,请参考以下文章

springmv的文件上传(多种类型)

spring,springmv,springboot解决跨域问题

Springmv 拦截器&异常处理

Spring学习10-SpringMV核心组件2及SpringMVC项目示例

第七次课:ssh的集成(SpringMV+Spring+Hibernate)

springmv日志debug异常,javax.naming.NameNotFoundException