DispatcherServlet源码分析

请求从DispatcherServlet到达具体的Controller

DispatcherServlet

Servlet的service方法是响应前端请求的入口方法,Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。DispatcherServlet是一个标准的Servlet,肯定具有service方法,并且通过service方法来响应所有的请求。

DispatherServlet继承自FrameWorkServlet,FrameWorkServlet是 springmvc 的基础 Servlet,它的主要工作是对 WebApplicationContext实例进行初始化和管理,并且FrameWorkServlet重写了doGet、doPost、doPut,doDelete 等方法,将所有类型的请求都交给processRequest方法来处理。

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

    long startTime = System.currentTimeMillis();
    Throwable failureCause = null;

    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    LocaleContext localeContext = buildLocaleContext(request);

    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

    initContextHolders(request, localeContext, requestAttributes);

    try {
        //抽象方法由子类实现
        doService(request, response);
    }
    catch (ServletException | IOException ex) {
        failureCause = ex;
        throw ex;
    }
    catch (Throwable ex) {
        failureCause = ex;
        throw new NestedServletException("Request processing failed", ex);
    }

    finally {
        resetContextHolders(request, previousLocaleContext, previousAttributes);
        if (requestAttributes != null) {
            requestAttributes.requestCompleted();
        }
        logResult(request, response, failureCause, asyncManager);
        publishRequestHandledEvent(request, response, startTime, failureCause);
    }
}

processRequest方法主要是作用是初始化request请求的上下文参数,然后将请求交给子类的doService方法处理,该方法由DispatcherServlet实现。

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    logRequest(request);

    //保存request请求参数的快照,使在后续处理中可以恢复原来的数据
    Map<String, Object> attributesSnapshot = null;
    if (WebUtils.isIncludeRequest(request)) {
        attributesSnapshot = new HashMap<>();
        Enumeration<?> attrNames = request.getAttributeNames();
        while (attrNames.hasMoreElements()) {
            String attrName = (String) attrNames.nextElement();
            if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
                attributesSnapshot.put(attrName, request.getAttribute(attrName));
            }
        }
    }

    // 添加框架的内置对象到request域中,使得handler和view对象能够使用
    request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
    request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
    request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
    request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

    //注入通过redirect传递来的(RedirectAttribute)属性
    if (this.flashMapManager != null) {
        FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
        if (inputFlashMap != null) {
            request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
        }
        request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
        request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
    }

    try {
        //进行请求分发
        doDispatch(request, response);
    }
    finally {
        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            // Restore the original attribute snapshot, in case of an include.
            if (attributesSnapshot != null) {
                restoreAttributesAfterInclude(request, attributesSnapshot);
            }
        }
    }
}

可以看出doService方法主要作用是对request请求参数进行备份,并且对request必要域进行赋值操作,最后调用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);

            //找到能够处理当前请求的handler
            //该对象最终会被包装为HandlerExecutionChain类型
            mappedHandler = getHandler(processedRequest);

            ...
        }
    }
}

DispatcherServlet的getHandler方法根据请求获取请求所对应的mappedHandler(即具体处理请求的 method 方法,实际上会最终被包装成一个HandlerExecutionChain 对象),这里是找到响应该请求的Controller方法的关键,该方法的具体实现如下:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        //遍历所有的HandlerMapping对象,调用其getHandler
        //如果该方法返回的handler不为空,则返回第一个获得的handler
        for (HandlerMapping mapping : this.handlerMappings) {
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}

以上的逻辑,只是遍历了DispatcherServlet的handlerMappings集合,然后调用HandlerMapping的getHandler方法获得HandlerExecutionChain对象(主要是包括了一个handler,以及一个拦截器列表),如果该对象不为空则返回该对象。这里问题就出现了,handlerMappings集合是什么,是从哪里获得的?

实际上handlerMappings集合中存放了实现了HandlerMapping接口的对象,其中最重要的对象就是RequestMappingHandlerMapping对象,它会在spring容器初始化以后将Controller中添加了@RequestMapping注解的方法映射信息缓存起来,方便在响应请求时通过反射调用对应的方法,具体实现将在下文进行分析。那么RequestMappingHandlerMapping是在哪配置的,又是怎么初始化的呢?直接提起RequestMappingHandlerMapping对象大家可能不太熟悉,但是spring配置文件中的<mvc:annotation-driven/>配置项大家应该不陌生,该配置项默认添加了以下配置:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />

因此在spring容器初始化时,会将RequestMappingHandlerMapping对象初始化,而该对象的父类AbstractHandlerMethodMapping实现了InitializingBean接口并实现其afterPropertiesSet方法,在Bean依赖注入完成时,spring会去检查这个Bean是否实现了InitializingBean接口,如果实现了InitializingBean接口,就会去调用这个类的afterPropertiesSet方法。AbstractHandlerMethodMapping的afterPropertiesSet方法如下:

public void afterPropertiesSet() {
    initHandlerMethods();
}

protected void initHandlerMethods() {
    //对所有的BeanName调用processCandidateBean方法
    for (String beanName : getCandidateBeanNames()) {
        if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
            processCandidateBean(beanName);
        }
    }
    handlerMethodsInitialized(getHandlerMethods());
}

//从spring上下文中获得所有的Bean的名字,因为这里的BeanType为Object
protected String[] getCandidateBeanNames() {
    return (this.detectHandlerMethodsInAncestorContexts ?
            BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) :
            obtainApplicationContext().getBeanNamesForType(Object.class));
}

afterPropertiesSet调用了initHandlerMethods方法获得当前spring上下文中所有bean的名字,并且对符合条件的beanName调用processCandidateBean方法。

protected void processCandidateBean(String beanName) {
    Class<?> beanType = null;
    try {
        beanType = obtainApplicationContext().getType(beanName);
    }
    catch (Throwable ex) {
        // An unresolvable bean type, probably from a lazy bean - let's ignore it.
        if (logger.isTraceEnabled()) {
            logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
        }
    }
    //beanType不为空并且isHandler方法返回值为true
    if (beanType != null && isHandler(beanType)) {
        detectHandlerMethods(beanName);
    }
}

//isHandler方法在RequestMappingHandlerMapping的实现
protected boolean isHandler(Class<?> beanType) {
    return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
            AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

processCandidateBean方法通过beanName获得bean的类型,当bean的类型不为空且该类同时具有@Controller注解和@RequestMapping注解时,才会继续调用detectHandlerMethods方法。

protected void detectHandlerMethods(Object handler) {
        //根据beanName获得其class类型
        Class<?> handlerType = (handler instanceof String ?
                obtainApplicationContext().getType((String) handler) : handler.getClass());

        if (handlerType != null) {
            Class<?> userType = ClassUtils.getUserClass(handlerType);
             //遍历该类实现的所有方法,获取它的所有方法对应的匹配信息(@RequestMapping注解中的信息)
             //并且将匹配信息保存在mappingRegistry中
            Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
                    (MethodIntrospector.MetadataLookup<T>) method -> {
                        try {
                               //根据方法匹配信息构造RequestMappingInfo
                            return getMappingForMethod(method, userType);
                        }
                        catch (Throwable ex) {
                            throw new IllegalStateException("Invalid mapping on handler class [" +
                                    userType.getName() + "]: " + method, ex);
                        }
                    });
            if (logger.isTraceEnabled()) {
                logger.trace(formatMappings(userType, methods));
            }
            methods.forEach((method, mapping) -> {
                Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
                 //将方法和@RequestMapping中的信息缓存到mappingRegister
                registerHandlerMethod(handler, invocableMethod, mapping);
            });
        }
    }

//getMappingForMethod方法在RequestMappingHandlerMapping的实现
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
    //从方法上@RequestMapping注解中的属性封装到RequestMappingInfo中
    RequestMappingInfo info = createRequestMappingInfo(method);
    if (info != null) {
        //同样的从类中的上@RequestMapping注解中获得信息
        RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
        if (typeInfo != null) {
            //将方法和类上的信息进行一次合并
            info = typeInfo.combine(info);
        }
        String prefix = getPathPrefix(handlerType);
        if (prefix != null) {
            info = RequestMappingInfo.paths(prefix).build().combine(info);
        }
    }
    return info;
}

detectHandlerMethods的作用主要是获得类所有的实现方法,遍历这些方法获得方法上@ReqestMapping中的信息,构造成RequestMappingInfo对象,需要注意的是在构造RequestMappingInfo时会将类上的注解信息和方法上的注解信息进行合并,比如类对应的path为 test,Method对应的path为 test1,那么最后合并的path即为 test/test1。最后,调用registerHandlerMethod将获得的信息缓存在mappingRegister中。

protected void registerHandlerMethod(Object handler, Method method, T mapping) {
    //mappingRegistry是AbstractHandlerMethodMapping的内部类MappingRegistry的实体对象
    //主要缓存了MappingInfo与Method的映射,以及url与MappingInfo的映射
    this.mappingRegistry.register(mapping, handler, method);
}

public void register(T mapping, Object handler, Method method) {
    this.readWriteLock.writeLock().lock();
    try {
        //将handler(类名或类)和方法关联创建HandlerMethod对象
        HandlerMethod handlerMethod = createHandlerMethod(handler, method);
        assertUniqueMethodMapping(handlerMethod, mapping);
        //将MappingInfo与Method的映射存在mappingLookup中
        this.mappingLookup.put(mapping, handlerMethod);

        List<String> directUrls = getDirectUrls(mapping);
        for (String url : directUrls) {
            //将url与MappingInfo的映射存在urlLookup中
            this.urlLookup.add(url, mapping);
        }

        String name = null;
        if (getNamingStrategy() != null) {
            name = getNamingStrategy().getName(handlerMethod, mapping);
            addMappingName(name, handlerMethod);
        }

        CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
        if (corsConfig != null) {
            this.corsLookup.put(handlerMethod, corsConfig);
        }

        this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
    }
    finally {
        this.readWriteLock.writeLock().unlock();
    }
}

到此RequestMappingHandlerMapping对象初始化基本完成,在DispatchServlet初始化时会通过BeanFactory获得所有实现了HandlerMapping的类来初始化handlerMappings成员变量。

现在让我们回到DispatcherServlet的getHandler方法上,该方法调用了HandlerMapping的getHandler方法,具体实现在AbstractHandlerMethodMapping中:

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    //获得handler对象
    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);
    }

    ...
}

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    //从request中获得请求路径
    String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    //加锁
    this.mappingRegistry.acquireReadLock();
    try {
        //获得和请求路径匹配的HandlerMethod对象
        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
        return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
    }
    finally {
        //释放锁
        this.mappingRegistry.releaseReadLock();
    }
}

AbstractHandlerMethodMapping的getHandler方法调用了getHandlerInternal来获得HandlerMethod对象,在getHandlerInternal方法中先mappingRegistry对象添加读锁,接着调用lookupHandlerMethod来获得具体的HandlerMethod,从之前的分析中我们知道了HandlerMethod由MappingRegister中进行了缓存,所以lookupHandlerMethod很可能是在缓存中寻找对应的HandlerMethod,方法如下:

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
    List<Match> matches = new ArrayList<>();
    //根据url在mappingRegistry的urlLookup中找到直接路径匹配的MappingInfo
    List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
    if (directPathMatches != null) { //如果url能够直接匹配
        //再根据具体信息找到最匹配的方法
        addMatchingMappings(directPathMatches, matches, request);
    }
    if (matches.isEmpty()) { //如果url不能直接匹配,这里考虑通配符的问题
        // No choice but to go through all mappings...
        addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
    }

   ...
}

不出所料,在lookupHandlerMethod方法中先根据请求的url信息,在mappingRegistry的urlLookup中初步确定匹配的MappingInfo,然后调用addMatchingMappings方法中进行详细的筛选,找出匹配的MappingInfo;如果在直接路径匹配没有找到任何匹配的信息(由于通配符的原因),只能遍历mappingRegistry的mappingLookup中所有的MappingInfo来找到匹配的信息。addMatchingMappings方法如下:

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)));
        }
    }
}

//在RequestMappingInfoHandlerMapping实现
protected RequestMappingInfo getMatchingMapping(RequestMappingInfo info, HttpServletRequest request) {
    return info.getMatchingCondition(request);
}

//最终调用了RequestMappingInfo的getMatchingCondition方法
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
    RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
    ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request);
    HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request);
    ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request);
    ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request);

    if (methods == null || params == null || headers == null || consumes == null || produces == null) {
        return null;
    }

    PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request);
    if (patterns == null) {
        return null;
    }

    RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request);
    if (custom == null) {
        return null;
    }

    return new RequestMappingInfo(this.name, patterns,
                                  methods, params, headers, consumes, produces, custom.getCondition());
}

从上面的代码可以看出,在addMatchingMappings中调用getMatchingMapping方法对匹配信息进行精确判断,如果判断通过则加入到结果集合中。最终将调用到RequestMappingInfo的getMatchingCondition方法,该方法对7个要素进行了匹配判断:

  • methods : 请求方法匹配(POST/GET/DELETE/PUT等等),对应RequestMapping注解的method
  • params : 请求参数匹配 例如myParam=myValue, 对应RequestMapping注解的params
  • headers:请求头信息(例如:My-Header!=myValue),对应RequestMapping的headers
  • consumes:提交内容类型(例如:application/json, text/html;),对应RequestMapping的consumes
  • produces:返回的内容类型(例如:application/json),对应RequestMapping的consumes
  • patterns:URL格式(例如:test/testDo),对应RequestMapping的value
  • 自定义条件

全部要素都通过判断后新建一个RequestMappingInfo副本返回。

找到一个url匹配的所有方法后,会对匹配的方法进一步的比较,找出最匹配的方法(bestMatch)返回,lookupHandlerMethod方法后续代码如下:

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
    List<Match> matches = new ArrayList<>();
    ...

    if (!matches.isEmpty()) { //如果找到的匹配方法数量大于0
        //通过定义的Comparator进行排序
        Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
        matches.sort(comparator);
        //第一个即是最匹配的方法
        Match bestMatch = matches.get(0);
        if (matches.size() > 1) {
            if (logger.isTraceEnabled()) {
                logger.trace(matches.size() + " matching mappings: " + matches);
            }
            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();
                String uri = request.getRequestURI();
                throw new IllegalStateException(
                    "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
            }
        }
        request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
        handleMatch(bestMatch.mapping, lookupPath, request);
        return bestMatch.handlerMethod;
    }
    else { //否则进入没有匹配方法的逻辑
        return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
    }
}

找到最最匹配的方法后则返回HandlerMethod对象,让我们从AbstractHandlerMethodMapping的getHandler中往下走,后续代码如下:

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    Object handler = getHandlerInternal(request);
    ...

    //将HandlerMethod包装为HandlerExecutionChain
    //执行的操作就是将注册了对应URL的过滤器挂载到该chain中,形成一条方法执行链。
    HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    ...
    //判断是否是cors请求,是的话添加对应的过滤器
    if (CorsUtils.isCorsRequest(request)) {
        CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
        CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
        CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
        executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
    }

    return executionChain;
}

包装完成后的handler将被回到DispatcherServlet的doDispatch方法中,继续往下执行:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    ...
    mappedHandler = getHandler(processedRequest);
    //如果没找到匹配的handler,调用noHandlerFound方法根据配置抛出异常或者返回404状态码
    if (mappedHandler == null) {
        noHandlerFound(processedRequest, response);
        return;
    }

    // 根据Handler获得对应的HandlerAdapter对象(即配置中的RequestMappingHandlerAdapter)
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

    // 判断获得的handler是否支持last-modified请求头
    String method = request.getMethod();
    boolean isGet = "GET".equals(method);
    if (isGet || "HEAD".equals(method)) {
        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
        if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
            return;
        }
    }

    //执行请求过滤器的preHandler方法,返回TRUE时继续向下执行,返回FALSE代表请求被过滤了,这时直接返回
    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);
    ...
}

判断返回的handler的对象是否为空,若handler为空则抛出异常或者返回404;若handler不为空,根据handler获得对应的HandlerAdapter对象,HandlerAdapter是用来调用HandlerMethod对应的方法的适配器,在spring中具体为RequestMappingHandlerAdapter;之后会执行执行过滤链中的过滤方法,判断请求是否被应该过滤,完成过滤逻辑以后,才会调用HandlerAdapter的handle方法开始真正的方法调用。

//在AbstractHandlerMethodAdapter的实现
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
    throws Exception {

    return handleInternal(request, response, (HandlerMethod) handler);
}

在handle方法中将 HandlerExecutionChain强转回 HandlerMethod 对象,并传递给子类(RequestMappingHandlerAdapter)的 handlerInternal 方法来进行后续处理。

protected ModelAndView handleInternal(HttpServletRequest request,
            HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

    ModelAndView mav;
    // 判断请求类型是否被支持以及请求是否需要session
    checkRequest(request);

    // 判断invokeHandlerMethod方法是否需要在同步块中执行
    if (this.synchronizeOnSession) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            Object mutex = WebUtils.getSessionMutex(session);
            synchronized (mutex) {
                mav = invokeHandlerMethod(request, response, handlerMethod);
            }
        }
        else {
            mav = invokeHandlerMethod(request, response, handlerMethod);
        }
    }
    else {
        mav = invokeHandlerMethod(request, response, handlerMethod);
    }

    if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
        if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
            applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
        }
        else {
            prepareResponse(response);
        }
    }

    return mav;
}

可以看出该方法的主要作用就是对当前请求进行一些判断与处理,然后调用最重要的方法invokeHandlerMethod,这里就不深入该方法的逻辑了(以后有时间再研究吧。。。),只对该方法进行简单的说明。在后续执行过程中会先对方法传入参数进行解析和匹配,如果没有匹配到合适的值就会抛出异常。一个典型的例子便是 @RequestParam 注解,如果你加了这个注解,那么参数名必须与表单名一致,否则会报错。之后会通过反射调用到具体的Controller方法,最后会对方法返回的结果进行处理,例如对添加了@ResponseBody注解的方法,会对其返回值进行json化并将其写入 responseBody 中。

参考

1.http://ddrv.cn/a/58528

2.https://www.jianshu.com/p/ef15e524458e