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

2020-04-04  本文已影响0人  JBryan

经过上一篇(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;
    }
上一篇 下一篇

猜你喜欢

热点阅读