美文网首页
SpringMVC源码浅析(二):获取HandlerExecut

SpringMVC源码浅析(二):获取HandlerExecut

作者: JBryan | 来源:发表于2020-04-04 21:20 被阅读0次

    经过上一篇(https://www.jianshu.com/p/117c12f5f334
    )的分析,DispatcherServlet已经初始化完毕,本篇文章将分析获取处理器执行链的过程。

    入口代码AccountController类:

    @Controller
    @RequestMapping("/account")
    public class AccountController {
    
        @Autowired
        AccountService accountService;
    
        @RequestMapping("/findAll")
        public @ResponseBody List<AccountSSM> findAll(){
            List<AccountSSM> list = accountService.findAll();
            return list;
        }
    
        @RequestMapping("/findOne")
        public @ResponseBody AccountSSM findAccount(String name,int id){
            AccountSSM accountSSM = new AccountSSM();
            accountSSM.setId(id);
            accountSSM.setName(name);
            return accountSSM;
        }
    }
    

    配置一个拦截器

    public class MyIntercepter implements HandlerInterceptor {
    
        /**
         *预处理方法
         * @param httpServletRequest
         * @param httpServletResponse
         * @param o
         * @return true 放行;false 不放行
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
            System.out.println("MyIntercepter执行了preHandle()方法");
            return true;
        }
    
        /**
         * 后处理方法,Controller方法执行之后,success.jsp执行之前
         * @param httpServletRequest
         * @param httpServletResponse
         * @param o
         * @param modelAndView
         * @throws Exception
         */
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
            System.out.println("MyIntercepter执行了postHandle()方法");
        }
    
        /**
         * success.jsp执行之后执行,最后执行的方法
         * @param httpServletRequest
         * @param httpServletResponse
         * @param o
         * @param e
         * @throws Exception
         */
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
            System.out.println("MyIntercepter执行了afterCompletion()方法");
        }
    }
    
    

    springmvc.xml配置拦截器

    <mvc:interceptors>
            <mvc:interceptor>
                <!--要拦截的方法-->
                <mvc:mapping path="/account/findOne"/>
                <!--不要拦截的方法
                <mvc:exclude-mapping path=""/>
                -->
                <!--配置拦截器对象-->
                <bean class="com.ljessie.ssm_demo.intercepter.MyIntercepter"></bean>
            </mvc:interceptor>
        </mvc:interceptors>
    

    DispatherServlet处理请求的过程如图所示:


    请求处理流程.png

    断点打到FrameworkServlet#doGet中

    protected final void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            processRequest(request, response);
        }
    

    FrameworkServlet#processRequest

    protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            long startTime = System.currentTimeMillis();
            //省略其他代码
            try {
                doService(request, response);
            }
            //省略其他代码
        }
    

    DispatcherServlet#doService

    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
            //省略其他代码
            try {
                doDispatch(request, response);
            }
            //省略其他代码
        }
    

    DispatcherServlet#doDispatch

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
            HttpServletRequest processedRequest = request;
            HandlerExecutionChain mappedHandler = null;
            boolean multipartRequestParsed = false;
    
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
            try {
                ModelAndView mv = null;
                Exception dispatchException = null;
    
                try {
                    //检查是否上传文件
                    processedRequest = checkMultipart(request);
                    multipartRequestParsed = (processedRequest != request);
    
                    // 获取HandlerExecutionChain
                    mappedHandler = getHandler(processedRequest);
                    if (mappedHandler == null) {
                        noHandlerFound(processedRequest, response);
                        return;
                    }
    
                    // 获取适配器
                    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
                    // Process last-modified header, if supported by the handler.
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if (logger.isDebugEnabled()) {
                            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;
                    }
    
                    // 处理Handler方法
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
    
                    applyDefaultViewName(processedRequest, mv);
                    //应用后置处理器
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                }
                catch (Exception ex) {
                    dispatchException = ex;
                }
                catch (Throwable err) {
                    // As of 4.3, we're processing Errors thrown from handler methods as well,
                    // making them available for @ExceptionHandler methods and other scenarios.
                    dispatchException = new NestedServletException("Handler dispatch failed", err);
                }
                //处理结果
                processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
            }
            catch (Exception ex) {
                triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
            }
            catch (Throwable err) {
                triggerAfterCompletion(processedRequest, response, mappedHandler,
                        new NestedServletException("Handler processing failed", err));
            }
            finally {
                if (asyncManager.isConcurrentHandlingStarted()) {
                    // Instead of postHandle and afterCompletion
                    if (mappedHandler != null) {
                        mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                    }
                }
                else {
                    // Clean up any resources used by a multipart request.
                    if (multipartRequestParsed) {
                        cleanupMultipart(processedRequest);
                    }
                }
            }
        }
    
    

    1、检查是否上传文件

    checkMultipart()不是这里分析的重点,大致看一下就行。

    protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
            if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
                if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
                    logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
                            "this typically results from an additional MultipartFilter in web.xml");
                }
                else if (hasMultipartException(request) ) {
                    logger.debug("Multipart resolution failed for current request before - " +
                            "skipping re-resolution for undisturbed error rendering");
                }
                else {
                    try {
                        return this.multipartResolver.resolveMultipart(request);
                    }
                    catch (MultipartException ex) {
                        if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) {
                            logger.debug("Multipart resolution failed for error dispatch", ex);
                            // Keep processing error dispatch with regular request handle below
                        }
                        else {
                            throw ex;
                        }
                    }
                }
            }
            // If not returned before: return original request.
            return request;
        }
    

    2、获取HandlerExecutionChain

    获取处理器的执行链过程如下图所示:


    获取处理器执行链.jpg

    getHandler()

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            if (this.handlerMappings != null) {
                for (HandlerMapping hm : this.handlerMappings) {
                    if (logger.isTraceEnabled()) {
                        logger.trace(
                                "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
                    }
                    //调用HandlerMapping 的getHandler方法,获取执行链
                    HandlerExecutionChain handler = hm.getHandler(request);
                    if (handler != null) {
                        return handler;
                    }
                }
            }
            return null;
        }
    
    

    AbstractHandlerMapping#getHandler:获取Handler执行链

    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            //1、获取HandlerMethod
            Object handler = getHandlerInternal(request);
            if (handler == null) {
                handler = getDefaultHandler();
            }
            if (handler == null) {
                return null;
            }
            // Bean name or resolved handler?
            if (handler instanceof String) {
                String handlerName = (String) handler;
                handler = obtainApplicationContext().getBean(handlerName);
            }
            //2、获取HandlerMethod的执行链
            HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
            if (CorsUtils.isCorsRequest(request)) {
                CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
                CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
                CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
                executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
            }
            return executionChain;
        }
    
    
    2.1、获取HandlerMethod

    AbstractHandlerMethodMapping#getHandlerInternal:获取HandlerMethod

    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
            //1、获取lookupPath
            String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
            if (logger.isDebugEnabled()) {
                logger.debug("Looking up handler method for path " + lookupPath);
            }
            this.mappingRegistry.acquireReadLock();
            try {
                //2、根据lookupPath获取HandlerMethod 
                HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
                if (logger.isDebugEnabled()) {
                    if (handlerMethod != null) {
                        logger.debug("Returning handler method [" + handlerMethod + "]");
                    }
                    else {
                        logger.debug("Did not find handler method for [" + lookupPath + "]");
                    }
                }
                //3、将HandlerMethod里面的bean,从String类型实例化为它的实际类型
                return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
            }
            finally {
                this.mappingRegistry.releaseReadLock();
            }
        }
    
    
    2.1.1、获取lookupPath
    String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    
    2.1.2、获取HandlerMethod

    AbstractHandlerMethodMapping#lookupHandlerMethod

    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
            List<Match> matches = new ArrayList<>();
            //1、根据lookupPath查找RequestMappingInfo对象
            List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
            if (directPathMatches != null) {
                //2、根据拿到的RequestMappingInfo对象,封装Match集合
                addMatchingMappings(directPathMatches, matches, request);
            }
            if (matches.isEmpty()) {
                // No choice but to go through all mappings...
                addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
            }
    
            if (!matches.isEmpty()) {
                Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
                Collections.sort(matches, comparator);
                if (logger.isTraceEnabled()) {
                    logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
                            lookupPath + "] : " + matches);
                }
                //3、找到最合适的Match对象
                Match bestMatch = matches.get(0);
                if (matches.size() > 1) {
                    if (CorsUtils.isPreFlightRequest(request)) {
                        return PREFLIGHT_AMBIGUOUS_MATCH;
                    }
                    Match secondBestMatch = matches.get(1);
                    if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                        Method m1 = bestMatch.handlerMethod.getMethod();
                        Method m2 = secondBestMatch.handlerMethod.getMethod();
                        throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
                                request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
                    }
                }
                handleMatch(bestMatch.mapping, lookupPath, request);
                //4、返回Match的HandlerMethod对象
                return bestMatch.handlerMethod;
            }
            else {
                return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
            }
        }
    
    

    第一步中,根据lookupPath查找RequestMappingInfo对象,实际上就是去urlLookup属性中找。

    public List<T> getMappingsByUrl(String urlPath) {
                return this.urlLookup.get(urlPath);
            }
    

    上面的Match对象其实只有两个属性,一个是泛型T(RequestMappingInfo类型),另外一个是HandlerMethod对象

    private class Match {
    
            private final T mapping;
    
            private final HandlerMethod handlerMethod;
    
            public Match(T mapping, HandlerMethod handlerMethod) {
                this.mapping = mapping;
                this.handlerMethod = handlerMethod;
            }
    
            @Override
            public String toString() {
                return this.mapping.toString();
            }
        }
    

    addMatchingMappings方法:根据RequestMappingInfo来封装Match集合

    private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
            for (T mapping : mappings) {
                T match = getMatchingMapping(mapping, request);
                if (match != null) {
                    matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
                }
            }
        }
    

    其中this.mappingRegistry.getMappings()返回的是Map<T, HandlerMethod>集合。

    public Map<T, HandlerMethod> getMappings() {
                return this.mappingLookup;
            }
    
    2.1.3、实例化HandlerMethod的bean属性

    HandlerMethod#createWithResolvedBean:先拿到beanFactory,然后调用beanFactory.getBean(beanName)方法。

    public HandlerMethod createWithResolvedBean() {
            Object handler = this.bean;
            if (this.bean instanceof String) {
                Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");
                String beanName = (String)this.bean;
                handler = this.beanFactory.getBean(beanName);
            }
    
            return new HandlerMethod(this, handler);
        }
    
    2.2、获取HandlerMethod的执行链

    AbstractHandlerMapping#getHandlerExecutionChain:根据路径lookupPath找到这个请求的拦截器,并添加到执行链中。

    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
            HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
                    (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
            //1、获取请求的路径
            String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
            //自定义的MyInterceptor拦截器和另外两个Spring的拦截器都在adaptedInterceptors属性中
            //2、遍历this.adaptedInterceptors集合
            for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
                if (interceptor instanceof MappedInterceptor) {
                    MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                    //3、如果拦截器和路径匹配
                    if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                        //4、将拦截器添加到执行链中
                        chain.addInterceptor(mappedInterceptor.getInterceptor());
                    }
                }
                else {
                    chain.addInterceptor(interceptor);
                }
            }
            return chain;
        }
    

    相关文章

      网友评论

          本文标题:SpringMVC源码浅析(二):获取HandlerExecut

          本文链接:https://www.haomeiwen.com/subject/ngkjphtx.html