SpringMVC源码解析之执行过程篇

阅读须知

  • Spring源码版本:4.3.8
  • 文章中使用/* */注释的方法会做深入分析

正文

承接上文,我们知道 HttpServlet 提供一些处理请求的方法,如 doGet、doPost、service等,在 DispatcherServlet 中的实现都调用了 processRequest 方法,我们来分析这个方法:
FrameworkServlet:

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

FrameworkServlet:

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    // 记录请求处理开始时间
    long startTime = System.currentTimeMillis();
    Throwable failureCause = null;
    // 提取当前线程的 LocaleContext 
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    // 构建国际化语言环境
    LocaleContext localeContext = buildLocaleContext(request);
    // 提取当前线程的 RequestAttributes 
    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
    // 封装请求参数
    ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
    // 构建异步请求管理器,异步请求是 Spring3.2 版本的新特性
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    // 注册 Callable 拦截器
    asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
    // 保存到当前线程,保证当前线程的请求还能获取到
    initContextHolders(request, localeContext, requestAttributes);
    try {
    	/* 子类具体实现处理请求逻辑 */
        doService(request, response);
    }
    catch (ServletException ex) {
        failureCause = ex;
        throw ex;
    }
    catch (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();
        }
        if (logger.isDebugEnabled()) {
            if (failureCause != null) {
                this.logger.debug("Could not complete request", failureCause);
            }
            else {
                if (asyncManager.isConcurrentHandlingStarted()) {
                    logger.debug("Leaving response open for concurrent processing");
                }
                else {
                    this.logger.debug("Successfully completed request");
                }
            }
        }
        publishRequestHandledEvent(request, response, startTime, failureCause); // 发布事件通知
    }
}

这里提到了异步请求,这里给出Spring对异步请求介绍和应用示例的官方文档地址,大家可以进行查阅了解。
DispatcherServlet:

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    if (logger.isDebugEnabled()) {
        String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
        logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
                " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
    }
    // 保存请求属性的快照,以便于包含之后还能够恢复原始属性
    Map<String, Object> attributesSnapshot = null;
    if (WebUtils.isIncludeRequest(request)) {
        attributesSnapshot = new HashMap<String, Object>();
        Enumeration<?> attrNames = request.getAttributeNames();
        while (attrNames.hasMoreElements()) {
            String attrName = (String) attrNames.nextElement();
            if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
                attributesSnapshot.put(attrName, request.getAttribute(attrName));
            }
        }
    }
    // 为请求包含一些属性(将之前初始化好的一些策略对象放入请求属性中)
    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());
    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()) {
            if (attributesSnapshot != null) {
                // 根据之前保存的请求属性快照将请求属性恢复到原始状态
                restoreAttributesAfterInclude(request, attributesSnapshot);
            }
        }
    }
}

DispatcherServlet:

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 {
            /* 检查是否是 multipart 类型的请求,如果是,将请求对象转换为 MultipartHttpServletRequest 类型的请求 */
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);
            /* 根据 request 找到对应的 handler */
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null || mappedHandler.getHandler() == null) {
            	// 没有 handler 通过 response 对象返回错误信息
                noHandlerFound(processedRequest, response);
                return;
            }
            /* 根据 handler 找到对应的 HandlerAdapter */
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
            String method = request.getMethod();
            boolean isGet = "GET".equals(method);
            // 如果 handler 支持处理 last-modified 请求,则处理
            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;
                }
            }
            /* 调用拦截器的 preHandle 方法 */
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }
            /* 真正的请求处理 */
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
            if (asyncManager.isConcurrentHandlingStarted()) {
            	// 如果是异步请求,直接返回,不会应用普通的视图和普通的拦截器后处理方法
                return;
            }
            // 如果没有视图则应用默认的视图名称
            applyDefaultViewName(processedRequest, mv);
            /* 调用拦截器的 postHandle 方法 */
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        }
        catch (Exception ex) {
            dispatchException = ex;
        }
        catch (Throwable err) {
            dispatchException = new NestedServletException("Handler dispatch failed", err);
        }
        /* 处理请求结果 */
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    catch (Exception ex) {
        // 拦截器 afterCompletion 方法的调用
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    }
    catch (Throwable err) {
        // 拦截器 afterCompletion 方法的调用
        triggerAfterCompletion(processedRequest, response, mappedHandler,
                new NestedServletException("Handler processing failed", err));
    }
    finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                // 如果是异步请求,则调用 AsyncHandlerInterceptor 的 afterConcurrentHandlingStarted 代替普通拦截器的 postHandle 和 afterCompletion 方法
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        }
        else {
            if (multipartRequestParsed) {
            	// 清理一些 multipart 类型请求的资源
                cleanupMultipart(processedRequest);
            }
        }
    }
}

DispatcherServlet:

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);
                }
                else {
                    throw ex;
                }
            }
        }
    }
    return request;
}

这里使用之前初始化的 multipartResolver 来判断和解析文件上传请求,这里需要注意的是,multipartResolver 没有默认的策略,所以如果我们的系统需要处理文件上传,就必须配置 multipartResolver,Spring 为我们提供了两种处理类,第一个 StandardServletMultipartResolver,是基于 Servlet3.0 API 来实现的,另一个 CommonsMultipartResolver 是基于 apache 的 commons-fileupload 包实现的,使用时需要引入相关 jar 包。
DispatcherServlet:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    for (HandlerMapping hm : this.handlerMappings) {
        if (logger.isTraceEnabled()) {
            logger.trace(
                    "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
        }
        // 获取 handler 请求处理链
        HandlerExecutionChain handler = hm.getHandler(request);
        if (handler != null) {
            return handler;
        }
    }
    return null;
}

这里获取 handler 请求处理链会涉及到 SpringMVC 中一个重要的角色 HandlerMapping,关于 HandlerMapping 的源码解析详见SpringMVC源码解析之HandlerMapping。下面是根据 Handler 获取 HandlerAdapter 适配器:
DispatcherServlet:

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    for (HandlerAdapter ha : this.handlerAdapters) {
        if (logger.isTraceEnabled()) {
            logger.trace("Testing handler adapter [" + ha + "]");
        }
        /* 判断当前 HandlerAdapter 是否支持当前 Handler */
        if (ha.supports(handler)) {
            return ha;
        }
    }
    throw new ServletException("No adapter for handler [" + handler +
            "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

这里的 handlerAdapters 在上面初始化的过程中在用户不指定的情况下,Spring 会默认注册三个策略,分别为HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、AnnotationMethodHandlerAdapter,其中 HttpRequestHandlerAdapter 用来适配实现了 HttpRequestHandler 的 handler,SimpleControllerHandlerAdapter 用于适配继承了 AbstractController 和实现了 Controller 接口的 Controller,AnnotationMethodHandlerAdapter 在 Spring3.2 版本被注解了 @Deprecated,已经不推荐使用了,用 RequestMappingHandlerAdapter 代替,用于适配注解了 @Controller 和 @RequestMapping 的 Controller,这种也是我们最常用的方式,我们就以 RequestMappingHandlerAdapter 为例来进行分析:

public final boolean supports(Object handler) {
    return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

我们在分析注解方式的 handler 注册的过程时看到了,handler 被封装成了 HandlerMethod,所以这里会匹配注解方式注册的 handler。接下来是对 Last-Modified 缓存机制的支持,简单介绍一下 Last-Modified 缓存机制,在客户端第一次输入 URL 时,服务器端会返回内容和状态码200,表示请求成功,同时会添加一个 Last-Modified 响应头,表示该请求内容在服务器上的最后更新时间,客户端第二次请求相同的 URL 时,客户端会向服务器发送请求头 If-Modified-Since 询问服务器该时间之后当前请求内容是否有被修改过,如果内容没有变化,则自动返回 HTTP304 状态码,内容为空,这样就节省了网络带宽。下面是拦截器 preHandle 方法的调用:
HandlerExecutionChain:

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HandlerInterceptor[] interceptors = getInterceptors();
    if (!ObjectUtils.isEmpty(interceptors)) {
        for (int i = 0; i < interceptors.length; i++) {
            HandlerInterceptor interceptor = interceptors[i];
            // 遍历拦截器调用 preHandle 方法
            if (!interceptor.preHandle(request, response, this.handler)) {
            	// 如果有没通过的,遍历拦截器调用 afterCompletion 方法
                triggerAfterCompletion(request, response, null);
                return false;
            }
            this.interceptorIndex = i;
        }
    }
    return true;
}

下面就是真正的请求处理阶段了,调用 HandlerAdapter 的 handle 方法,我们同样以 RequestMappingHandlerAdapter 来分析,首先看一下它的类层次结构:
这里写图片描述
我们发现它实现了 InitializingBean,所以分析一下 afterPropertiesSet 方法的实现:
RequestMappingHandlerAdapter:

public void afterPropertiesSet() {
	/* 初始化 ControllerAdvice 缓存 */
    initControllerAdviceCache();
    if (this.argumentResolvers == null) {
    	/* 获取默认参数解析器 */
        List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
        // 封装到组合类中
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.initBinderArgumentResolvers == null) {
    	// 获取参数绑定解析器,这里添加的解析器已经添加到了默认参数解析器的集合中,这里是为了区分出用于参数绑定的解析器
        List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
        // 封装到组合类中
        this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.returnValueHandlers == null) {
    	// 获取方法返回值解析器,这里添加的解析器已经添加到了默认参数解析器的集合中,这里是为了区分出用于解析方法返回值的解析器
        List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
        // 封装到组合类中
        this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
    }
}

RequestMappingHandlerAdapter:

private void initControllerAdviceCache() {
    if (getApplicationContext() == null) {
        return;
    }
    if (logger.isInfoEnabled()) {
        logger.info("Looking for @ControllerAdvice: " + getApplicationContext());
    }
    // 获取@ControllerAdvice注解的beanName,并封装到ControllerAdviceBean中
    List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
    AnnotationAwareOrderComparator.sort(beans);
    List<Object> requestResponseBodyAdviceBeans = new ArrayList<Object>();
    for (ControllerAdviceBean bean : beans) {
        // 获取@ModelAttribute注解的方法
        Set<Method> attrMethods = MethodIntrospector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);
        if (!attrMethods.isEmpty()) {
            this.modelAttributeAdviceCache.put(bean, attrMethods); // 记录到相应缓存中
            if (logger.isInfoEnabled()) {
                logger.info("Detected @ModelAttribute methods in " + bean);
            }
        }
        // 获取@InitBinder注解的方法
        Set<Method> binderMethods = MethodIntrospector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);
        if (!binderMethods.isEmpty()) {
            this.initBinderAdviceCache.put(bean, binderMethods); // 记录到相应缓存中
            if (logger.isInfoEnabled()) {
                logger.info("Detected @InitBinder methods in " + bean);
            }
        }
        // RequestBodyAdvice类型bean的记录
        if (RequestBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
            requestResponseBodyAdviceBeans.add(bean);
            if (logger.isInfoEnabled()) {
                logger.info("Detected RequestBodyAdvice bean in " + bean);
            }
        }
        if (ResponseBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
            requestResponseBodyAdviceBeans.add(bean);
            if (logger.isInfoEnabled()) {
                logger.info("Detected ResponseBodyAdvice bean in " + bean);
            }
        }
    }
    if (!requestResponseBodyAdviceBeans.isEmpty()) {
        this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
    }
}

RequestMappingHandlerAdapter:

private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
    List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
    // 添加各种注解参数解析器
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); // @RequestParam
    resolvers.add(new RequestParamMapMethodArgumentResolver()); // @RequestParam,参数为Map类型
    resolvers.add(new PathVariableMethodArgumentResolver()); // @PathVariable
    resolvers.add(new PathVariableMapMethodArgumentResolver()); // @PathVariable,参数为Map类型
    resolvers.add(new MatrixVariableMethodArgumentResolver()); // @MatrixVariable
    resolvers.add(new MatrixVariableMapMethodArgumentResolver()); // @MatrixVariable,参数为Map类型
    resolvers.add(new ServletModelAttributeMethodProcessor(false)); // @ModelAttribute
    resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); // @RequestBody
    resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice)); // @RequestPart
    resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory())); // @RequestHeader
    resolvers.add(new RequestHeaderMapMethodArgumentResolver()); // @RequestHeader,参数为Map类型
    resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory())); // @CookieValue
    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); // @Value
    resolvers.add(new SessionAttributeMethodArgumentResolver()); // @SessionAttribute
    resolvers.add(new RequestAttributeMethodArgumentResolver()); // @RequestAttribute
    // 添加各种类型参数解析器
    resolvers.add(new ServletRequestMethodArgumentResolver()); // 请求类型的参数,如ServletRequest、MultipartRequest、HttpSession等
    resolvers.add(new ServletResponseMethodArgumentResolver()); // 响应类型的参数,如ServletResponse等
    resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); // HttpEntity、RequestEntity类型的参数和返回值
    resolvers.add(new RedirectAttributesMethodArgumentResolver()); // RedirectAttributes类型的参数
    resolvers.add(new ModelMethodProcessor()); // Model类型的参数和返回值
    resolvers.add(new MapMethodProcessor()); // Map类型的参数和返回值
    resolvers.add(new ErrorsMethodArgumentResolver()); // Errors类型的参数
    resolvers.add(new SessionStatusMethodArgumentResolver()); // SessionStatus类型的参数
    resolvers.add(new UriComponentsBuilderMethodArgumentResolver()); // UriComponentsBuilder类型的参数
    // 自定义参数解析器
    if (getCustomArgumentResolvers() != null) {
        resolvers.addAll(getCustomArgumentResolvers());
    }
    // 上面已经添加过,这里不同的是构造方法的第二个参数传了true,表示使用默认的解析方法,当参数是一个简单类型的时候,会把请求参数的名称看做方法参数的名称
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
    // 上面已经添加过,这里不同的是构造方法的参数传了true,表示非简单类型的参数和返回值会被看作为model属性
    resolvers.add(new ServletModelAttributeMethodProcessor(true));
    return resolvers;
}

初始化各种资源之后,下面是请求处理的过程:
AbstractHandlerMethodAdapter:

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    /* 处理请求 */
    return handleInternal(request, response, (HandlerMethod) handler);
}

RequestMappingHandlerAdapter:

protected ModelAndView handleInternal(HttpServletRequest request,
        HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    ModelAndView mav;
    checkRequest(request); // 请求校验,主要是校验请求的method是否支持和session的必要性校验
    if (this.synchronizeOnSession) { // 如果需要session内的同步执行
        HttpSession session = request.getSession(false);
        if (session != null) {
            Object mutex = WebUtils.getSessionMutex(session); // 获取session锁
            synchronized (mutex) {
                /* 调用HandlerMethod */
                mav = invokeHandlerMethod(request, response, handlerMethod);
            }
        }
        else {
            /* 调用HandlerMethod */
            mav = invokeHandlerMethod(request, response, handlerMethod);
        }
    }
    else {
        /* 调用HandlerMethod */
        mav = invokeHandlerMethod(request, response, handlerMethod);
    }
    // 对Cache-Control的支持
    if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
        // 如果有session属性(如@SessionAttributes注解的controller)
        if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
            applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
        }
        else {
            prepareResponse(response);
        }
    }
    return mav;
}

RequestMappingHandlerAdapter:

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
        HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    try {
        /* 获取数据绑定工厂 */
        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        /* 获取 Model 工厂 */
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
        // 封装 HandlerMethod
        ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
        invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
        invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
        invocableMethod.setDataBinderFactory(binderFactory);
        invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
        /* 初始化 Model */
        modelFactory.initModel(webRequest, mavContainer, invocableMethod);
        mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
        // 创建异步请求对象,这里会根据 servlet 的 ServletRequest 接口类是否包含 startAsync 方法来判断是否支持异步请求,servlet3.0 开始支持异步请求
        AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
        asyncWebRequest.setTimeout(this.asyncRequestTimeout);
        // 创建异步请求管理器
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        asyncManager.setTaskExecutor(this.taskExecutor);
        asyncManager.setAsyncWebRequest(asyncWebRequest);
        asyncManager.registerCallableInterceptors(this.callableInterceptors);
        asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
        // 判断是否有并发返回值,如果有需要进行包装
        if (asyncManager.hasConcurrentResult()) {
            Object result = asyncManager.getConcurrentResult();
            mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
            asyncManager.clearConcurrentResult();
            if (logger.isDebugEnabled()) {
                logger.debug("Found concurrent result value [" + result + "]");
            }
            invocableMethod = invocableMethod.wrapConcurrentResult(result);
        }
        /* 调用方法,处理返回结果 */
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        if (asyncManager.isConcurrentHandlingStarted()) {
        	// 如果是异步请求直接返回 null,不会走下面构建 ModelAndView 的逻辑,判断是否是异步请求的逻辑是调用 servlet 的 API,检查是否调用了 startAsync 方法将当前请求放入了异步模式中
            return null;
        }
        // 构建 ModelAndView 并返回
        return getModelAndView(mavContainer, modelFactory, webRequest);
    }
    finally {
    	// 请求销毁的回调,session 的处理
        webRequest.requestCompleted();
    }
}

RequestMappingHandlerAdapter:

private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
    Class<?> handlerType = handlerMethod.getBeanType();
    Set<Method> methods = this.initBinderCache.get(handlerType);
    if (methods == null) {
        // 获取 @InitBinder 注解的方法
        methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
        this.initBinderCache.put(handlerType, methods);
    }
    List<InvocableHandlerMethod> initBinderMethods = new ArrayList<InvocableHandlerMethod>();
    // initBinderAdviceCache 缓存的初始化过程在上文分析过
    for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache.entrySet()) {
        // 根据包名、类型、注解判断当前 ControllerAdviceBean 是否可以应用到目标 handler 类
        if (entry.getKey().isApplicableToBeanType(handlerType)) {
            Object bean = entry.getKey().resolveBean();
            for (Method method : entry.getValue()) {
                // 封装到 InvocableHandlerMethod 中
                initBinderMethods.add(createInitBinderMethod(bean, method));
            }
        }
    }
    for (Method method : methods) {
        Object bean = handlerMethod.getBean();
        // 封装到 InvocableHandlerMethod 中
        initBinderMethods.add(createInitBinderMethod(bean, method));
    }
    // 创建数据绑定工厂
    return createDataBinderFactory(initBinderMethods);
}

RequestMappingHandlerAdapter:

private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
    // 从缓存中获取 SessionAttributesHandler,没有则创建并放入缓存
    SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
    Class<?> handlerType = handlerMethod.getBeanType();
    Set<Method> methods = this.modelAttributeCache.get(handlerType);
    if (methods == null) {
        // 获取 @ModelAttribute 注解的方法
        methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
        this.modelAttributeCache.put(handlerType, methods);
    }
    List<InvocableHandlerMethod> attrMethods = new ArrayList<InvocableHandlerMethod>();
    // modelAttributeAdviceCache 的注册过程上文分析过
    for (Entry<ControllerAdviceBean, Set<Method>> entry : this.modelAttributeAdviceCache.entrySet()) {
        // 根据包名、类型、注解判断当前 ControllerAdviceBean 是否可以应用到目标 handler 类
        if (entry.getKey().isApplicableToBeanType(handlerType)) {
            Object bean = entry.getKey().resolveBean();
            for (Method method : entry.getValue()) {
                // 封装到 InvocableHandlerMethod 中
                attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
            }
        }
    }
    for (Method method : methods) {
        Object bean = handlerMethod.getBean();
        // 封装到 InvocableHandlerMethod 中
        attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
    }
    return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
}

ModelFactory:

public void initModel(NativeWebRequest request, ModelAndViewContainer container,
        HandlerMethod handlerMethod) throws Exception {
    // 检索 session 属性
    Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);
    // 合并到 ModelAndView 容器,放入 ModelMap 中
    container.mergeAttributes(sessionAttributes);
    /* 调用 model 属性方法填充 model,仅仅填充那些 model 中没有出现的的属性 */
    invokeModelAttributeMethods(request, container);
    // 获取 handlerMethod 的方法参数上注解的 @ModelAttribute 的 name 属性
    for (String name : findSessionAttributeArguments(handlerMethod)) {
        if (!container.containsAttribute(name)) {
        	// 检索 session 属性
            Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
            if (value == null) {
                throw new HttpSessionRequiredException("Expected session attribute '" + name + "'", name);
            }
            container.addAttribute(name, value);
        }
    }
}

ModelFactory:

private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container)
        throws Exception {
    while (!this.modelMethods.isEmpty()) {
        // 这里获取的 modelMethod 是在构造 ModelFactory 时传入的从 ControllerAdviceBean 和 HandlerMethod 中提取的由 @ModelAttribute 注解的方法,这里会提取并从缓存中移除掉
        InvocableHandlerMethod modelMethod = getNextModelMethod(container).getHandlerMethod();
        ModelAttribute ann = modelMethod.getMethodAnnotation(ModelAttribute.class);
        // 如果容器的 ModelMap 的 key 中已经包含当前注解的 name 值,则不在调用
        if (container.containsAttribute(ann.name())) {
            if (!ann.binding()) {
                // 如果注解的 binding 属性设置为 false,则添加到不可用绑定属性集合中
                container.setBindingDisabled(ann.name());
            }
            continue;
        }
        /* 调用 HandlerMethod,这里调用的是 ModelMethod */
        Object returnValue = modelMethod.invokeForRequest(request, container);
        if (!modelMethod.isVoid()){
            // 获取返回值名称,按照如下顺序,首先获取注解声明的 value 属性,为空则判断声明的返回值类型是否比 Object 类型更具体,否则使用实际的返回值类型
            String returnValueName = getNameForReturnValue(returnValue, modelMethod.getReturnType());
            if (!ann.binding()) {
                container.setBindingDisabled(returnValueName);
            }
            if (!container.containsAttribute(returnValueName)) {
                container.addAttribute(returnValueName, returnValue);
            }
        }
    }
}

InvocableHandlerMethod:

public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {
    /* 获取当前请求的方法参数 */
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    if (logger.isTraceEnabled()) {
        logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
                "' with arguments " + Arrays.toString(args));
    }
    /* 调用 */
    Object returnValue = doInvoke(args);
    if (logger.isTraceEnabled()) {
        logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
                "] returned [" + returnValue + "]");
    }
    return returnValue;
}

InvocableHandlerMethod:

private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {
    MethodParameter[] parameters = getMethodParameters();
    Object[] args = new Object[parameters.length];
    // 遍历方法参数列表
    for (int i = 0; i < parameters.length; i++) {
        MethodParameter parameter = parameters[i];
        parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
        // 试图从提供的参数值列表中解析方法参数
        args[i] = resolveProvidedArgument(parameter, providedArgs);
        if (args[i] != null) {
            continue;
        }
        // 这里的 argumentsResolvers 我们在分析 RequestMappingHandlerAdapter 的 afterPropertiesSet 方法时看到过它的初始化过程,并且在构建 InvocableHandlerMethod 时 set 进来的
        /* 判断是否支持解析当前方法参数 */
        if (this.argumentResolvers.supportsParameter(parameter)) {
            try {
                /* 解析方法参数 */
                args[i] = this.argumentResolvers.resolveArgument(
                        parameter, mavContainer, request, this.dataBinderFactory);
                continue;
            }
            catch (Exception ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug(getArgumentResolutionErrorMessage("Failed to resolve", i), ex);
                }
                throw ex;
            }
        }
        if (args[i] == null) {
            throw new IllegalStateException("Could not resolve method parameter at index " +
                    parameter.getParameterIndex() + " in " + parameter.getMethod().toGenericString() +
                    ": " + getArgumentResolutionErrorMessage("No suitable resolver for", i));
        }
    }
    return args;
}

参数解析器在初始化过程中创建很多种,并将它们都封装到了组合类中,这里我们以RequestParamMethodArgumentResolver为例来分析解析过程。
HandlerMethodArgumentResolverComposite:

public boolean supportsParameter(MethodParameter parameter) {
    // 判断是否支持解析就是判断适合当前方法参数的解析器是否为null
    return (getArgumentResolver(parameter) != null);
}

HandlerMethodArgumentResolverComposite:

private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
    HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
    if (result == null) {
        for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
            if (logger.isTraceEnabled()) {
                logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" +
                        parameter.getGenericParameterType() + "]");
            }
            /* 遍历封装的所有ArgumentResolver,判断是否支持当前参数的解析 */
            if (methodArgumentResolver.supportsParameter(parameter)) {
                result = methodArgumentResolver;
                this.argumentResolverCache.put(parameter, result);
                break;
            }
        }
    }
    return result;
}

RequestParamMethodArgumentResolver:

public boolean supportsParameter(MethodParameter parameter) {
    // 如果参数有@RequestParam注解,需要判断是否是Map类型,如果是注解必须指定具体的名称,否则交给RequestParamMapMethodArgumentResolver解析
    if (parameter.hasParameterAnnotation(RequestParam.class)) {
        if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
            String paramName = parameter.getParameterAnnotation(RequestParam.class).name();
            return StringUtils.hasText(paramName);
        }
        else {
            return true;
        }
    }
    else {
        // @RequestPart注解不支持
        if (parameter.hasParameterAnnotation(RequestPart.class)) {
            return false;
        }
        parameter = parameter.nestedIfOptional();
        // 支持解析MultipartFile类型和Part类型
        if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
            return true;
        }
        else if (this.useDefaultResolution) {
            // 支持解析简单的类型,如基本类型、String类型、Number类型等等
            return BeanUtils.isSimpleProperty(parameter.getNestedParameterType());
        }
        else {
            return false;
        }
    }
}

HandlerMethodArgumentResolverComposite:

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); // 获取解析器
    if (resolver == null) {
        throw new IllegalArgumentException("Unknown parameter type [" + parameter.getParameterType().getName() + "]");
    }
    return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); /* 进行参数解析 */
}

AbstractNamedValueMethodArgumentResolver:

public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    /* 获取给定方法参数的命名值 */
    NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
    MethodParameter nestedParameter = parameter.nestedIfOptional();
    // 解析注解的name属性值,可能包含占位符和表达式
    Object resolvedName = resolveStringValue(namedValueInfo.name);
    if (resolvedName == null) {
        throw new IllegalArgumentException(
                "Specified name must not resolve to null: [" + namedValueInfo.name + "]");
    }
    /* 将给定的参数类型和值名称解析为参数值 */
    Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
    if (arg == null) {
        if (namedValueInfo.defaultValue != null) {
            // 解析并使用默认参数值
            arg = resolveStringValue(namedValueInfo.defaultValue);
        }
        else if (namedValueInfo.required && !nestedParameter.isOptional()) {
            // 设置required=true但参数值为null,则根据参数和请求对象抛出不同的异常
            handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
        }
        /* 处理null值 */
        arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
    }
    else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
        // 如果参数值是空字符串并且默认值不为null,则解析并使用默认值
        arg = resolveStringValue(namedValueInfo.defaultValue);
    }
    if (binderFactory != null) {
        // 创建并初始化数据绑定器,并调用@InitBinder注解的bindMethod,这里的bindMethod我们在分析解析器初始化过程时看到了它的初始化过程
        WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
        try {
            // 如果需要,则用类型转换器转换参数
            arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
        }
        catch (ConversionNotSupportedException ex) {
            throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
                    namedValueInfo.name, parameter, ex.getCause());
        }
        catch (TypeMismatchException ex) {
            throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
                    namedValueInfo.name, parameter, ex.getCause());
        }
    }
    // 留给子类实现处理解析后的参数值,默认空实现
    handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
    return arg;
}

AbstractNamedValueMethodArgumentResolver:

private NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
    NamedValueInfo namedValueInfo = this.namedValueInfoCache.get(parameter);
    if (namedValueInfo == null) {
        namedValueInfo = createNamedValueInfo(parameter); /* 创建NamedValueInfo */
        namedValueInfo = updateNamedValueInfo(parameter, namedValueInfo);
        this.namedValueInfoCache.put(parameter, namedValueInfo);
    }
    return namedValueInfo;
}

RequestParamMethodArgumentResolver:

protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
    RequestParam ann = parameter.getParameterAnnotation(RequestParam.class);
    // 获取参数@RequestParam注解对象封装到RequestParamNamedValueInfo中
    return (ann != null ? new RequestParamNamedValueInfo(ann) : new RequestParamNamedValueInfo());
}

AbstractNamedValueMethodArgumentResolver:

private Object handleNullValue(String name, Object value, Class<?> paramType) {
    if (value == null) {
        // 如果传入的参数值null并且参数为Boolean类型,则默认返回false
        if (Boolean.TYPE.equals(paramType)) {
            return Boolean.FALSE;
        }
        // 如果参数类型为基本类型,抛出异常
        else if (paramType.isPrimitive()) {
            throw new IllegalStateException("Optional " + paramType.getSimpleName() + " parameter '" + name +
                    "' is present but cannot be translated into a null value due to being declared as a " +
                    "primitive type. Consider declaring it as object wrapper for the corresponding primitive type.");
        }
    }
    return value;
}

参数解析并处理好之后,下面就是调用过程:
InvocableHandlerMethod:

protected Object doInvoke(Object... args) throws Exception {
    ReflectionUtils.makeAccessible(getBridgedMethod());
    try {
        // 获取bridge方法反射执行
        return getBridgedMethod().invoke(getBean(), args);
    }
    catch (IllegalArgumentException ex) {
        assertTargetBean(getBridgedMethod(), getBean(), args);
        String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
        throw new IllegalStateException(getInvocationErrorMessage(text, args), ex);
    }
    catch (InvocationTargetException ex) {
        Throwable targetException = ex.getTargetException();
        if (targetException instanceof RuntimeException) {
            throw (RuntimeException) targetException;
        }
        else if (targetException instanceof Error) {
            throw (Error) targetException;
        }
        else if (targetException instanceof Exception) {
            throw (Exception) targetException;
        }
        else {
            String text = getInvocationErrorMessage("Failed to invoke handler method", args);
            throw new IllegalStateException(text, targetException);
        }
    }
}

下面是handler目标方法的调用和返回结果的处理:
ServletInvocableHandlerMethod:

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {
    // 这里的调用过程在分析Model的初始化时已经分析过,不再重复
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    // 根据@ResponseStatus注解的内容设置响应状态,@ResponseStatus注解是用来设置响应状态码和错误提示信息给出提示的
    setResponseStatus(webRequest);
    if (returnValue == null) {
        if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
            mavContainer.setRequestHandled(true);
            return;
        }
    }
    else if (StringUtils.hasText(getResponseStatusReason())) {
        mavContainer.setRequestHandled(true);
        return;
    }
    mavContainer.setRequestHandled(false);
    try {
        /* 处理返回值 */
        this.returnValueHandlers.handleReturnValue(
                returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
    }
    catch (Exception ex) {
        if (logger.isTraceEnabled()) {
            logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
        }
        throw ex;
    }
}

HandlerMethodReturnValueHandlerComposite:

public void handleReturnValue(Object returnValue, MethodParameter returnType,
        ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
    // 选择合适的返回值处理器,这里会忽略掉异步返回值处理器
    HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
    if (handler == null) {
        throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
    }
    /* 处理返回值 */
    handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}

我们之前看到了返回值处理器的注册过程,这里选择合适的返回值处理器也就是在注册的这个集合中选择,我们以ViewNameMethodReturnValueHandler为例来看它如何处理返回值:

public void handleReturnValue(Object returnValue, MethodParameter returnType,
        ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
    // 处理字符序列类型的返回值,当然也包括String类型
    if (returnValue instanceof CharSequence) {
        String viewName = returnValue.toString();
        mavContainer.setViewName(viewName); // 设置视图名称
        // 判断是否是重定向视图并设置标记,判断依据就是是否有redirect:前缀或者用户自己配置的匹配模式
        if (isRedirectViewName(viewName)) {
            mavContainer.setRedirectModelScenario(true);
        }
    }
    else if (returnValue != null){
        throw new UnsupportedOperationException("Unexpected return type: " +
                returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
    }
}

到这里,调用HandlerAdapter对请求的处理就完成了。我们用了大篇幅来分析RequestMappingHandlerAdapter对请求处理的过程,下面我们回到主流程,下面是对拦截器postHandle方法的调用:
HandlerExecutionChain:

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
    HandlerInterceptor[] interceptors = getInterceptors();
    if (!ObjectUtils.isEmpty(interceptors)) {
        for (int i = interceptors.length - 1; i >= 0; i--) {
            HandlerInterceptor interceptor = interceptors[i];
            interceptor.postHandle(request, response, this.handler, mv); // 调用拦截器的postHandle方法
        }
    }
}

最后是对转发结果的加工:
DispatcherServlet:

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
        HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
    boolean errorView = false;
    if (exception != null) {
        if (exception instanceof ModelAndViewDefiningException) {
            logger.debug("ModelAndViewDefiningException encountered", exception);
            mv = ((ModelAndViewDefiningException) exception).getModelAndView();
        }
        else {
            Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
            /* HandlerExceptionResolver处理异常 */
            mv = processHandlerException(request, response, handler, exception);
            errorView = (mv != null);
        }
    }
    if (mv != null && !mv.wasCleared()) {
        /* 根据视图跳转页面 */
        render(mv, request, response);
        if (errorView) {
            // 如果是异常视图处理完成之后将之前曝光的异常信息从request对象中移除掉
            WebUtils.clearErrorRequestAttributes(request);
        }
    }
    else {
        if (logger.isDebugEnabled()) {
            logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
                    "': assuming HandlerAdapter completed request handling");
        }
    }
    if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
        return;
    }
    if (mappedHandler != null) {
        // 拦截器afterCompletion方法的调用
        mappedHandler.triggerAfterCompletion(request, response, null);
    }
}

DispatcherServlet:

protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
        Object handler, Exception ex) throws Exception {
    ModelAndView exMv = null;
    for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
        // 遍历注册的HandlerExceptionResolver集合来处理本次异常请求
        exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
        if (exMv != null) {
            break;
        }
    }
    if (exMv != null) {
        if (exMv.isEmpty()) {
            request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
            return null;
        }
        if (!exMv.hasView()) {
            exMv.setViewName(getDefaultViewName(request));
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);
        }
        // 将错误的异常信息放入request属性中
        WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
        return exMv;
    }
    throw ex;
}

在用户不指定HandlerExceptionResolver的情况下,Spring默认为我们注册了三个HandlerExceptionResolver,AnnotationMethodHandlerExceptionResolver、ResponseStatusExceptionResolver和DefaultHandlerExceptionResolver,它们的应用就是在这里,具体的处理逻辑在这里就不多赘述了,感兴趣的读者可以自行研究,最后我们来看视图的跳转:
DispatcherServlet:

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 国际化处理,如果用户没有指定LocaleResolver,Spring默认为我们注册了AcceptHeaderLocaleResolver来处理国际化
    Locale locale = this.localeResolver.resolveLocale(request);
    response.setLocale(locale);
    View view;
    if (mv.isReference()) {
        /* 解析视图名称 */
        view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
        if (view == null) {
            throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
                    "' in servlet with name '" + getServletName() + "'");
        }
    }
    else {
        view = mv.getView();
        if (view == null) {
            throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
                    "View object in servlet with name '" + getServletName() + "'");
        }
    }
    if (logger.isDebugEnabled()) {
        logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
    }
    try {
        if (mv.getStatus() != null) {
            response.setStatus(mv.getStatus().value());
        }
        /* 视图渲染 */
        view.render(mv.getModelInternal(), request, response);
    }
    catch (Exception ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
                    getServletName() + "'", ex);
        }
        throw ex;
    }
}

DispatcherServlet:

protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
        HttpServletRequest request) throws Exception {
    for (ViewResolver viewResolver : this.viewResolvers) {
        /* 遍历注册的视图解析器集合解析视图 */
        View view = viewResolver.resolveViewName(viewName, locale);
        if (view != null) {
            return view;
        }
    }
    return null;
}

在用户不指定ViewResolver的情况下,Spring为我们注册了InternalResourceViewResolver作为默认的视图解析器,我们来看它如何解析视图:
AbstractCachingViewResolver:

public View resolveViewName(String viewName, Locale locale) throws Exception {
    if (!isCache()) {
        /* 没有缓存直接创建视图 */
        return createView(viewName, locale);
    }
    else { // 尝试从缓存中获取
        Object cacheKey = getCacheKey(viewName, locale);
        View view = this.viewAccessCache.get(cacheKey);
        if (view == null) {
            synchronized (this.viewCreationCache) {
                view = this.viewCreationCache.get(cacheKey);
                if (view == null) {
                    view = createView(viewName, locale); // 缓存中没有获取到同样要创建
                    if (view == null && this.cacheUnresolved) {
                        view = UNRESOLVED_VIEW;
                    }
                    if (view != null) {
                        this.viewAccessCache.put(cacheKey, view);
                        this.viewCreationCache.put(cacheKey, view);
                        if (logger.isTraceEnabled()) {
                            logger.trace("Cached view [" + cacheKey + "]");
                        }
                    }
                }
            }
        }
        return (view != UNRESOLVED_VIEW ? view : null);
    }
}

UrlBasedViewResolver:

protected View createView(String viewName, Locale locale) throws Exception {
    // 判断当前ViewResolver是否能够处理当前视图,如果不能返回null继续遍历下一个ViewResolver来处理
    if (!canHandle(viewName, locale)) {
        return null;
    }
    // 视图名称以redirect:为前缀的处理
    if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
        String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
        RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
        view.setHosts(getRedirectHosts());
        return applyLifecycleMethods(viewName, view);
    }
    // 视图名称以forward:为前缀的处理
    if (viewName.startsWith(FORWARD_URL_PREFIX)) {
        String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
        return new InternalResourceView(forwardUrl);
    }
    /* 否则调用父类的方法来创建视图 */
    return super.createView(viewName, locale);
}

AbstractCachingViewResolver:

protected View createView(String viewName, Locale locale) throws Exception {
    return loadView(viewName, locale); /* 加载视图 */
}

UrlBasedViewResolver:

protected View loadView(String viewName, Locale locale) throws Exception {
    /* 构建视图 */
    AbstractUrlBasedView view = buildView(viewName);
    View result = applyLifecycleMethods(viewName, view);
    return (view.checkResource(locale) ? result : null);
}

InternalResourceViewResolver:

protected AbstractUrlBasedView buildView(String viewName) throws Exception {
    /* 调用父类方法构建视图 */
    InternalResourceView view = (InternalResourceView) super.buildView(viewName);
    if (this.alwaysInclude != null) {
        view.setAlwaysInclude(this.alwaysInclude);
    }
    view.setPreventDispatchLoop(true);
    return view;
}

UrlBasedViewResolver:

protected AbstractUrlBasedView buildView(String viewName) throws Exception {
    AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());
    // 拼接前缀后缀
    view.setUrl(getPrefix() + viewName + getSuffix());
    String contentType = getContentType();
    if (contentType != null) {
        // 设置contentType
        view.setContentType(contentType);
    }
    view.setRequestContextAttribute(getRequestContextAttribute());
    view.setAttributesMap(getAttributesMap());
    Boolean exposePathVariables = getExposePathVariables();
    if (exposePathVariables != null) {
        view.setExposePathVariables(exposePathVariables);
    }
    Boolean exposeContextBeansAsAttributes = getExposeContextBeansAsAttributes();
    if (exposeContextBeansAsAttributes != null) {
        view.setExposeContextBeansAsAttributes(exposeContextBeansAsAttributes);
    }
    String[] exposedContextBeanNames = getExposedContextBeanNames();
    if (exposedContextBeanNames != null) {
        view.setExposedContextBeanNames(exposedContextBeanNames);
    }
    return view;
}

解析视图过后,接下来就是视图的渲染:
AbstractView:

public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
    if (logger.isTraceEnabled()) {
        logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
            " and static attributes " + this.staticAttributes);
    }
    // 创建一个包含动态值和静态属性的组合输出映射,动态值优先于静态属性
    Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
    prepareResponse(request, response);
    /* 视图跳转 */
    renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}

在构建视图的时候我们看到以forward:为前缀的视图名称会返回InternalResourceView对象,以redirect:为前缀的视图会返回RedirectView对象,其他情况也同样会返回InternalResourceView对象,我们以InternalResourceView为例来分析视图跳转过程:

protected void renderMergedOutputModel(
        Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 曝光model中的对象到request属性中
    exposeModelAsRequestAttributes(model, request);
    exposeHelpers(request);
    // 获取转发路径并检查循环转发
    String dispatcherPath = prepareForRendering(request, response);
    // 获取servlet的请求转发器
    RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
    if (rd == null) {
        throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
                "]: Check that the corresponding file exists within your web application archive!");
    }
    if (useInclude(request, response)) {
        response.setContentType(getContentType());
        if (logger.isDebugEnabled()) {
            logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
        }
        rd.include(request, response);
    }
    else {
        if (logger.isDebugEnabled()) {
            logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
        }
        rd.forward(request, response); // 转发
    }
}

到这里整个SpringMVC的流程就结束了,篇幅较长,请大家耐心阅读,相信您一定会有所收获。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值