小架构step系列19:请求和响应

1 概述

作为Web程序,通用形式是发起HTTP请求并获取返回的结果,在这个过程中,需要把请求映射到代码的接口上,提供这种接口的类一般称为Controller,也就是需要把请求映射到Controller的接口方法上,把请求的参数映射到接口的参数中,并从接口返回接口处理的结果。

在后端渲染页面的场景中,返回的结果需要处理为视图View。而现在更普遍的是前后端分离,返回的结果一般处理为JSON格式的数据,前端拿到这种数据再进行处理和页面的渲染。

本文来了解一下这个请求和响应的过程。

2 原理

2.1 源码解析

在使用SpringBoot的时候,内嵌了一个tomcat服务器,做到了不需要感觉到有web服务器就能够开发web程序。内嵌tomcat服务器由tomcat-embed-core包提供,tomcat接收请求时,会调用到StandardWrapperValve的invoke()方法,下面的源码则从这段代码开始。

java 复制代码
// tomcat接收请求时,会调用到StandardWrapperValve的invoke()方法
// 源码位置:org.apache.catalina.core.StandardWrapperValve(在tomcat-embed-core包)
public void invoke(Request request, Response response) throws IOException, ServletException {
    // 省略其它代码
    
    // 1. 组装Filter链
    ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
    Container container = this.container;
    try {
        if ((servlet != null) && (filterChain != null)) {
            // Swallow output if needed
            if (context.getSwallowOutput()) {
                try {
                    SystemLogHandler.startCapture();
                    if (request.isAsyncDispatching()) {
                        request.getAsyncContextInternal().doInternalDispatch();
                    } else {
                        filterChain.doFilter(request.getRequest(), response.getResponse());
                    }
                } finally {
                    String log = SystemLogHandler.stopCapture();
                    if (log != null && log.length() > 0) {
                        context.getLogger().info(log);
                    }
                }
            } else {
                if (request.isAsyncDispatching()) {
                    request.getAsyncContextInternal().doInternalDispatch();
                } else {
                    // 2. 递归调用Filter链,filterChain为ApplicationFilterChain
                    filterChain.doFilter(request.getRequest(), response.getResponse());
                }
            }

        }
    } 
    // 省略其它代码
}

// 源码位置:org.apache.catalina.core.ApplicationFilterChain
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
    if (Globals.IS_SECURITY_ENABLED) {
        // 省略其它代码
    } else {
        // 3. 调用内部方法internalDoFilter()
        internalDoFilter(request, response);
    }
}

// 源码位置:org.apache.catalina.core.ApplicationFilterChain
private void internalDoFilter(ServletRequest request, ServletResponse response)
        throws IOException, ServletException {
    // pos为当前filter在Filter链中的位置,n是filter的个数,也就是递归调Filter,到最后一个后就不满足pos<n条件
    if (pos < n) {
        // 取当前位置的Filter,同时pos加1方便下次取下一个Filter
        ApplicationFilterConfig filterConfig = filters[pos++];
        try {
            Filter filter = filterConfig.getFilter();

            if (request.isAsyncSupported() &&
                    "false".equalsIgnoreCase(filterConfig.getFilterDef().getAsyncSupported())) {
                request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
            }
            if (Globals.IS_SECURITY_ENABLED) {
                final ServletRequest req = request;
                final ServletResponse res = response;
                Principal principal = ((HttpServletRequest) req).getUserPrincipal();

                Object[] args = new Object[] { req, res, this };
                SecurityUtil.doAsPrivilege("doFilter", filter, classType, args, principal);
            } else {
                // 调Filter的doFilter方法,注意Filter里一般要有filterChain.doFilter()才能触发下一个Filter执行
                // this就是filterChain
                filter.doFilter(request, response, this);
            }
        } catch (IOException | ServletException | RuntimeException e) {
            throw e;
        } catch (Throwable e) {
            e = ExceptionUtils.unwrapInvocationTargetException(e);
            ExceptionUtils.handleThrowable(e);
            throw new ServletException(sm.getString("filterChain.filter"), e);
        }
        return;
    }

    // Filter正常结束后继续执行业务,如果不正常跑完Filter则在前面返回或抛异常了
    try {
        if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
            lastServicedRequest.set(request);
            lastServicedResponse.set(response);
        }

        if (request.isAsyncSupported() && !servletSupportsAsync) {
            request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
        }
        // Use potentially wrapped request from this point
        if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse) &&
                Globals.IS_SECURITY_ENABLED) {
            final ServletRequest req = request;
            final ServletResponse res = response;
            Principal principal = ((HttpServletRequest) req).getUserPrincipal();
            Object[] args = new Object[] { req, res };
            SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args, principal);
        } else {
            // 4. servlet为DispatcherServlet,调起servlet的service()方法
            servlet.service(request, response);
        }
    } catch (IOException | ServletException | RuntimeException e) {
        throw e;
    } catch (Throwable e) {
        e = ExceptionUtils.unwrapInvocationTargetException(e);
        ExceptionUtils.handleThrowable(e);
        throw new ServletException(sm.getString("filterChain.servlet"), e);
    } finally {
        if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
            lastServicedRequest.set(null);
            lastServicedResponse.set(null);
        }
    }
}

// 继承关系:DispatcherServlet < FrameworkServlet < HttpServletBean < HttpServlet
// DispatcherServlet本身没有重载service()方法,该方法由HttpServlet提供
// 源码位置:javax.servlet.http.HttpServlet
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    // 强制转了一下request和response的类型,也就是只有HttpServletRequest、HttpServletResponse类型才能往下处理
    HttpServletRequest request;
    HttpServletResponse response;
    try {
        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;
    } catch (ClassCastException e) {
        throw new ServletException(lStrings.getString("http.non_http"));
    }
    // 5. 调service接口,方法名称虽然相同但参数类型不一样
    service(request, response);
}

// 源码位置:javax.servlet.http.HttpServlet
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String method = req.getMethod();
    
    // 根据HTTP的Method(GET、POST等)来分别处理,这里只看GET方法,其它方法类似
    if (method.equals(METHOD_GET)) {
        long lastModified = getLastModified(req);
        if (lastModified == -1) {
            // 6. 处理GET请求
            doGet(req, resp);
        } else {
            // 省略部分代码
        }

    } else if (method.equals(METHOD_HEAD)) {
        long lastModified = getLastModified(req);
        maybeSetLastModified(resp, lastModified);
        doHead(req, resp);

    } else if (method.equals(METHOD_POST)) {
        doPost(req, resp);

    } else if (method.equals(METHOD_PUT)) {
        doPut(req, resp);

    } else if (method.equals(METHOD_DELETE)) {
        doDelete(req, resp);

    } else if (method.equals(METHOD_OPTIONS)) {
        doOptions(req, resp);

    } else if (method.equals(METHOD_TRACE)) {
        doTrace(req, resp);

    } else {
        //
        // Note that this means NO servlet supports whatever
        // method was requested, anywhere on this server.
        //

        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[1];
        errArgs[0] = method;
        errMsg = MessageFormat.format(errMsg, errArgs);

        resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
    }
}

// FrameworkServlet重载了父类的doGet方法
// 源码位置:org.springframework.web.servlet.FrameworkServlet
protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 7. 处理请求
    processRequest(request, response);
}
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 {
        // 8. 处理请求
        doService(request, response);
    }
    catch (ServletException | IOException ex) {
        failureCause = ex;
        throw ex;
    }
    catch (Throwable ex) {
        failureCause = ex;
        throw new NestedServletException("Request processing failed", ex);
    }
    // 省略部分代码
}

// DispatcherServlet重载了父类的doService()方法
// 源码位置:org.springframework.web.servlet.DispatcherServlet
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 省略部分代码        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));
            }
        }
    }

    // Make framework objects available to handlers and view objects.
    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());

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

    RequestPath previousRequestPath = null;
    if (this.parseRequestPath) {
        previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
        ServletRequestPathUtils.parseAndCache(request);
    }
    try {
        // 9. 处理请求
        doDispatch(request, response);
    }
    // 省略部分代码
}

// 源码位置:org.springframework.web.servlet.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 {
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // 10. 根据请求中的URL路径匹配到Controller提供的响应请求的http接口方法
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            String method = request.getMethod();
            boolean isGet = HttpMethod.GET.matches(method);
            if (isGet || HttpMethod.HEAD.matches(method)) {
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                    return;
                }
            }

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

            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) {
            dispatchException = new NestedServletException("Handler dispatch failed", err);
        }
        
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    // 省略部分代码
}

// 源码位置:org.springframework.web.servlet.DispatcherServlet
// DispatcherServlet在初始化的时候,通过Spring查找实现了org.springframework.web.servlet.HandlerMapping接口的所有类,
// 找到的类存放到handlerMappings变量中,大体上有下面6个是实现了HandlerMapping接口的类:
//     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
//     org.springframework.boot.autoconfigure.web.servlet.WelcomePageHandlerMapping
//     org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
//     org.springframework.web.servlet.function.support.RouterFunctionMapping
//     org.springframework.boot.autoconfigure.web.servlet.WelcomePageNotAcceptableHandlerMapping
//     org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        for (HandlerMapping mapping : this.handlerMappings) {
            // 11. 这里重点看RequestMappingHandlerMapping对请求的处理
            //     RequestMappingHandlerMapping的getHandler()逻辑是根据请求里的接口路径匹配到Controller提供的http接口方法
            //     如果找到能处理请求的方法则返回,否则尝试下一个HandlerMapping
            //     返回的是封装了RequestMappingHandlerMapping的HandlerExecutionChain
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}

// 回到DispatcherServlet的doDispatch()继续处理
// 源码位置:org.springframework.web.servlet.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 {
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // 10. 根据请求中的URL路径匹配到Controller提供的响应请求的http接口方法
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            // 12. 获取处理请求的HandlerAdapter
            // mappedHandler.getHandler()就是Controller里的方法
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            String method = request.getMethod();
            boolean isGet = HttpMethod.GET.matches(method);
            if (isGet || HttpMethod.HEAD.matches(method)) {
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                    return;
                }
            }

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

            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) {
            dispatchException = new NestedServletException("Handler dispatch failed", err);
        }
        
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    // 省略部分代码
}

// 源码位置:org.springframework.web.servlet.DispatcherServlet
// DispatcherServlet在初始化的时候,通过Spring查找实现了org.springframework.web.servlet.HandlerAdapter接口的类,
// 找到的类存放到handlerAdapters变量中,大体上有下面4个是实现了HandlerAdapter接口的类:
//     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
//     org.springframework.web.servlet.function.support.HandlerFunctionAdapter
//     org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
//     org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        for (HandlerAdapter adapter : this.handlerAdapters) {
            // 13. RequestMappingHandlerAdapter的supports()逻辑是判断参数handler是否是org.springframework.web.method.HandlerMethod类型
            //     从Controller里匹配到的接口方法就是HandlerMethod类型
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
    }
    throw new ServletException("No adapter for handler [" + handler +
            "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

// 回到DispatcherServlet的doDispatch()继续处理
// 源码位置:org.springframework.web.servlet.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 {
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // 10. 根据请求中的URL路径匹配到Controller提供的响应请求的http接口方法
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            // 12. 获取处理请求的HandlerAdapter,这里主要看RequestMappingHandlerAdapter
            // mappedHandler.getHandler()就是Controller里的方法
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            String method = request.getMethod();
            boolean isGet = HttpMethod.GET.matches(method);
            if (isGet || HttpMethod.HEAD.matches(method)) {
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                    return;
                }
            }

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

            // 14. 调用HandlerAdapter的handle()处理请求,以RequestMappingHandlerAdapter为例
            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);
        }
        
        // 13. 处理请求的返回结果,参考13.1
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    // 省略部分代码
}

// 源码位置:org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter
// 继承关系:RequestMappingHandlerAdapter < AbstractHandlerMethodAdapter
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // 15. 调内部方法处理请求
    return handleInternal(request, response, (HandlerMethod) handler);
}

// 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
protected ModelAndView handleInternal(HttpServletRequest request, ttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    ModelAndView mav;
    checkRequest(request);

    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 {
        // 16. 调HandlerMethod方法处理请求
        mav = invokeHandlerMethod(request, response, handlerMethod);
    }

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

    return mav;
}

// 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
// 初始化RequestMappingHandlerAdapter时会通过RequestMappingHandlerAdapter#afterPropertiesSet()方法初始化27个argumentResolver:
//     org.springframework.web.method.annotation.RequestParamMethodArgumentResolver
//     org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.PathVariableMapMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMapMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor
//     org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor
//     org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver
//     org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver
//     org.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.ServletCookieValueMethodArgumentResolver
//     org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.SessionAttributeMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.RequestAttributeMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.ServletResponseMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor
//     org.springframework.web.servlet.mvc.method.annotation.RedirectAttributesMethodArgumentResolver
//     org.springframework.web.method.annotation.ModelMethodProcessor
//     org.springframework.web.method.annotation.MapMethodProcessor
//     org.springframework.web.method.annotation.ErrorsMethodArgumentResolver
//     org.springframework.web.method.annotation.SessionStatusMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.UriComponentsBuilderMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.PrincipalMethodArgumentResolver
//     org.springframework.web.method.annotation.RequestParamMethodArgumentResolver
//     org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor
// 初始化RequestMappingHandlerAdapter时会通过RequestMappingHandlerAdapter#afterPropertiesSet()方法初始化15个returnValueHandler:
//     org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler
//     org.springframework.web.method.annotation.ModelMethodProcessor
//     org.springframework.web.servlet.mvc.method.annotation.ViewMethodReturnValueHandler
//     org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler
//     org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBodyReturnValueHandler
//     org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor
//     org.springframework.web.servlet.mvc.method.annotation.HttpHeadersReturnValueHandler
//     org.springframework.web.servlet.mvc.method.annotation.CallableMethodReturnValueHandler
//     org.springframework.web.servlet.mvc.method.annotation.DeferredResultMethodReturnValueHandler
//     org.springframework.web.servlet.mvc.method.annotation.AsyncTaskMethodReturnValueHandler
//     org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor
//     org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor
//     org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler
//     org.springframework.web.method.annotation.MapMethodProcessor
//     org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    try {
        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

        // 17. 把HandlerMethod封装到ServletInvocableHandlerMethod中,
        // 设置上方法参数处理器argumentResolvers、返回值处理器returnValueHandlers、参数名处理器parameterNameDiscoverer
        ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
        if (this.argumentResolvers != null) {
            invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
        }
        if (this.returnValueHandlers != null) {
            invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
        }
        invocableMethod.setDataBinderFactory(binderFactory);
        invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

        // 18. 创建ModelAndViewContainer,用于承载请求结果
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
        modelFactory.initModel(webRequest, mavContainer, invocableMethod);
        mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

        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();
            LogFormatUtils.traceDebug(logger, traceOn -> {
                String formatted = LogFormatUtils.formatValue(result, !traceOn);
                return "Resume with async result [" + formatted + "]";
            });
            invocableMethod = invocableMethod.wrapConcurrentResult(result);
        }

        // 19. 调用ServletInvocableHandlerMethod的invokeAndHandle方法处理请求
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        if (asyncManager.isConcurrentHandlingStarted()) {
            return null;
        }

        return getModelAndView(mavContainer, modelFactory, webRequest);
    }
    finally {
        webRequest.requestCompleted();
    }
}

// 源码位置:org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
    // 20. 处理请求
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    setResponseStatus(webRequest);

    if (returnValue == null) {
        if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
            disableContentCachingIfNecessary(webRequest);
            mavContainer.setRequestHandled(true);
            return;
        }
    }
    else if (StringUtils.hasText(getResponseStatusReason())) {
        mavContainer.setRequestHandled(true);
        return;
    }

    mavContainer.setRequestHandled(false);
    Assert.state(this.returnValueHandlers != null, "No return value handlers");
    try {
        this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
    }
    catch (Exception ex) {
        if (logger.isTraceEnabled()) {
            logger.trace(formatErrorForReturnValue(returnValue), ex);
        }
        throw ex;
    }
}

// 源码位置:org.springframework.web.method.support.InvocableHandlerMethod
// 继承关系:ServletInvocableHandlerMethod < InvocableHandlerMethod
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
    // 21. 遍历Controller接口方法的参数,对参数进行处理
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    if (logger.isTraceEnabled()) {
        logger.trace("Arguments: " + Arrays.toString(args));
    }
    
    return doInvoke(args);
}

// 源码位置:org.springframework.web.method.support.InvocableHandlerMethod
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
    // 22. 从Controller接口方法取到参数列表
    MethodParameter[] parameters = getMethodParameters();
    if (ObjectUtils.isEmpty(parameters)) {
        return EMPTY_ARGS;
    }

    // 23. 遍历参数进行处理
    Object[] args = new Object[parameters.length];
    for (int i = 0; i < parameters.length; i++) {
        MethodParameter parameter = parameters[i];
        // 24. 处理参数名称,参数名称可以有${}等复杂形式的
        parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
        args[i] = findProvidedArgument(parameter, providedArgs);
        if (args[i] != null) {
            continue;
        }
        // 25. 匹配参数处理器,参数处理器的说明参考上面列表
        if (!this.resolvers.supportsParameter(parameter)) {
            throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
        }
        try {
            // 26. 处理参数得到参数值
            args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
        }
        catch (Exception ex) {
            // Leave stack trace for later, exception may actually be resolved and handled...
            if (logger.isDebugEnabled()) {
                String exMsg = ex.getMessage();
                if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
                    logger.debug(formatArgumentError(parameter, exMsg));
                }
            }
            throw ex;
        }
    }
    return args;
}

// 回到InvocableHandlerMethod的invokeForRequest()继续处理
// 源码位置:org.springframework.web.method.support.InvocableHandlerMethod
// 继承关系:ServletInvocableHandlerMethod < InvocableHandlerMethod
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
    // 21. 遍历Controller接口方法的参数,对参数进行处理
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    if (logger.isTraceEnabled()) {
        logger.trace("Arguments: " + Arrays.toString(args));
    }
    
    // 27. 调Controller接口方法
    return doInvoke(args);
}

// 源码位置:org.springframework.web.method.support.InvocableHandlerMethod
protected Object doInvoke(Object... args) throws Exception {
    Method method = getBridgedMethod();
    try {
        if (KotlinDetector.isSuspendingFunction(method)) {
            return CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args);
        }
        // 28. method已经是java.lang.reflect.Method,即通过jdk提供的反射机制执行实际接口并返回结果
        return method.invoke(getBean(), args);
    }
    // 省略部分代码
}

// 回到ServletInvocableHandlerMethod的invokeAndHandle()继续处理
// 源码位置:org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
    // 20. 处理请求,得到调Controller接口的返回值
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    setResponseStatus(webRequest);

    if (returnValue == null) {
        if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
            disableContentCachingIfNecessary(webRequest);
            mavContainer.setRequestHandled(true);
            return;
        }
    }
    else if (StringUtils.hasText(getResponseStatusReason())) {
        mavContainer.setRequestHandled(true);
        return;
    }

    mavContainer.setRequestHandled(false);
    Assert.state(this.returnValueHandlers != null, "No return value handlers");
    try {
        // 29. 调用returnValueHandler处理Controller接口的返回值
        this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
    }
    catch (Exception ex) {
        if (logger.isTraceEnabled()) {
            logger.trace(formatErrorForReturnValue(returnValue), ex);
        }
        throw ex;
    }
}

// 源码位置:org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
    // 30. 匹配ReturnValueHandler,参考12.4.2.1.1
    HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
    if (handler == null) {
        throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
    }
    handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
    boolean isAsyncValue = isAsyncReturnValue(value, returnType);
    for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
        if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
            continue;
        }
        // 31. 匹配ReturnValueHandler
        if (handler.supportsReturnType(returnType)) {
            return handler;
        }
    }
    return null;
}

// 回到HandlerMethodReturnValueHandlerComposite的handleReturnValue()继续处理
// 源码位置:org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
    // 30. 匹配ReturnValueHandler,参考12.4.2.1.1
    HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
    if (handler == null) {
        throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
    }
    // 32. 处理返回值,以RequestResponseBodyMethodProcessor为例
    handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}

// 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
        ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
        throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

    mavContainer.setRequestHandled(true); // 注意:匹配到RequestResponseBodyMethodProcessor的时候,处理返回结果时已经置位"请求已处理"
    ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
    ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

    // 33. 使用MessageConverter写结果到ServletServerHttpResponse
    writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}

// 源码位置:org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor
// 继承关系:RequestResponseBodyMethodProcessor < AbstractMessageConverterMethodProcessor
protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,
        ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
        throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

    Object body;
    Class<?> valueType;
    Type targetType;

    if (value instanceof CharSequence) {
        body = value.toString();
        valueType = String.class;
        targetType = String.class;
    }
    else {
        body = value;
        valueType = getReturnValueType(body, returnType);
        targetType = GenericTypeResolver.resolveType(getGenericType(returnType), returnType.getContainingClass());
    }

    // 34. 返回结果的类型实现了Resource接口时,用Resource的方式处理
    if (isResourceType(value, returnType)) {
        outputMessage.getHeaders().set(HttpHeaders.ACCEPT_RANGES, "bytes");
        if (value != null && inputMessage.getHeaders().getFirst(HttpHeaders.RANGE) != null &&
                outputMessage.getServletResponse().getStatus() == 200) {
            Resource resource = (Resource) value;
            try {
                List<HttpRange> httpRanges = inputMessage.getHeaders().getRange();
                outputMessage.getServletResponse().setStatus(HttpStatus.PARTIAL_CONTENT.value());
                body = HttpRange.toResourceRegions(httpRanges, resource);
                valueType = body.getClass();
                targetType = RESOURCE_REGION_LIST_TYPE;
            }
            catch (IllegalArgumentException ex) {
                outputMessage.getHeaders().set(HttpHeaders.CONTENT_RANGE, "bytes */" + resource.contentLength());
                outputMessage.getServletResponse().setStatus(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value());
            }
        }
    }

    MediaType selectedMediaType = null;
    MediaType contentType = outputMessage.getHeaders().getContentType();
    boolean isContentTypePreset = contentType != null && contentType.isConcrete();
    if (isContentTypePreset) {
        if (logger.isDebugEnabled()) {
            logger.debug("Found 'Content-Type:" + contentType + "' in response");
        }
        selectedMediaType = contentType;
    }
    else {
        HttpServletRequest request = inputMessage.getServletRequest();
        List<MediaType> acceptableTypes;
        try {
            // acceptableTypes:text/html, application/xhtml+xml, image/avif, image/webp, image/apng, application/xml;q=0.9, application/signed-exchange;v=b3;q=0.7, */*;q=0.8
            acceptableTypes = getAcceptableMediaTypes(request);
        }
        catch (HttpMediaTypeNotAcceptableException ex) {
            int series = outputMessage.getServletResponse().getStatus() / 100;
            if (body == null || series == 4 || series == 5) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Ignoring error response content (if any). " + ex);
                }
                return;
            }
            throw ex;
        }
        // producibleTypes:text/plain, */*, text/plain, */*, application/json, application/*+json, application/json, application/*+json
        List<MediaType> producibleTypes = getProducibleMediaTypes(request, valueType, targetType);

        if (body != null && producibleTypes.isEmpty()) {
            throw new HttpMessageNotWritableException(
                    "No converter found for return value of type: " + valueType);
        }
        List<MediaType> mediaTypesToUse = new ArrayList<>();
        for (MediaType requestedType : acceptableTypes) {
            for (MediaType producibleType : producibleTypes) {
                if (requestedType.isCompatibleWith(producibleType)) {
                    mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType));
                }
            }
        }
        if (mediaTypesToUse.isEmpty()) {
            if (logger.isDebugEnabled()) {
                logger.debug("No match for " + acceptableTypes + ", supported: " + producibleTypes);
            }
            if (body != null) {
                throw new HttpMediaTypeNotAcceptableException(producibleTypes);
            }
            return;
        }

        MediaType.sortBySpecificityAndQuality(mediaTypesToUse);

        for (MediaType mediaType : mediaTypesToUse) {
            if (mediaType.isConcrete()) {
                selectedMediaType = mediaType;
                break;
            }
            else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) {
                selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
                break;
            }
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Using '" + selectedMediaType + "', given " +
                    acceptableTypes + " and supported " + producibleTypes);
        }
    }

    if (selectedMediaType != null) {
        selectedMediaType = selectedMediaType.removeQualityValue();
        for (HttpMessageConverter<?> converter : this.messageConverters) {
            GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ?
                    (GenericHttpMessageConverter<?>) converter : null);
            if (genericConverter != null ?
                    ((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) :
                    converter.canWrite(valueType, selectedMediaType)) {
                body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,
                        (Class<? extends HttpMessageConverter<?>>) converter.getClass(),
                        inputMessage, outputMessage);
                if (body != null) {
                    Object theBody = body;
                    LogFormatUtils.traceDebug(logger, traceOn ->
                            "Writing [" + LogFormatUtils.formatValue(theBody, !traceOn) + "]");
                    addContentDispositionHeader(inputMessage, outputMessage);
                    if (genericConverter != null) {
                        genericConverter.write(body, targetType, selectedMediaType, outputMessage);
                    }
                    else {
                        // 35. 匹配到messageConverter后进行写入数据,这里以StringHttpMessageConverter为例
                        ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);
                    }
                }
                else {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Nothing to write: null body");
                    }
                }
                return;
            }
        }
    }

    if (body != null) {
        Set<MediaType> producibleMediaTypes =
                (Set<MediaType>) inputMessage.getServletRequest()
                        .getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);

        if (isContentTypePreset || !CollectionUtils.isEmpty(producibleMediaTypes)) {
            throw new HttpMessageNotWritableException(
                    "No converter for [" + valueType + "] with preset Content-Type '" + contentType + "'");
        }
        throw new HttpMediaTypeNotAcceptableException(getSupportedMediaTypes(body.getClass()));
    }
}

// 源码位置:org.springframework.http.converter.AbstractHttpMessageConverter
public final void write(final T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
    final HttpHeaders headers = outputMessage.getHeaders();
    addDefaultHeaders(headers, t, contentType);

    if (outputMessage instanceof StreamingHttpOutputMessage) {
        StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
        streamingOutputMessage.setBody(outputStream -> writeInternal(t, new HttpOutputMessage() {
            @Override
            public OutputStream getBody() {
                return outputStream;
            }
            @Override
            public HttpHeaders getHeaders() {
                return headers;
            }
        }));
    }
    else {
        // 36. 写入数据
        writeInternal(t, outputMessage);
        outputMessage.getBody().flush();
    }
}
protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
    HttpHeaders headers = outputMessage.getHeaders();
    if (this.writeAcceptCharset && headers.get(HttpHeaders.ACCEPT_CHARSET) == null) {
        headers.setAcceptCharset(getAcceptedCharsets());
    }
    Charset charset = getContentTypeCharset(headers.getContentType());
    // 37. 数据写入到HttpOutputMessage的body里,参考12.4.2.2.1
    // outputMessage就是之前的ServletServerHttpResponse,继承关系:ServletServerHttpResponse < ServerHttpResponse < HttpOutputMessage
    StreamUtils.copy(str, charset, outputMessage.getBody());
}

// 回到RequestMappingHandlerAdapter的invokeHandlerMethod()处理View
// 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    try {
        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

        // 17. 把HandlerMethod封装到ServletInvocableHandlerMethod中,
        // 设置上方法参数处理器argumentResolvers、返回值处理器returnValueHandlers、参数名处理器parameterNameDiscoverer
        ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
        if (this.argumentResolvers != null) {
            invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
        }
        if (this.returnValueHandlers != null) {
            invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
        }
        invocableMethod.setDataBinderFactory(binderFactory);
        invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

        // 18. 创建ModelAndViewContainer,用于承载请求结果
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
        modelFactory.initModel(webRequest, mavContainer, invocableMethod);
        mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

        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();
            LogFormatUtils.traceDebug(logger, traceOn -> {
                String formatted = LogFormatUtils.formatValue(result, !traceOn);
                return "Resume with async result [" + formatted + "]";
            });
            invocableMethod = invocableMethod.wrapConcurrentResult(result);
        }

        // 19. 调用ServletInvocableHandlerMethod的invokeAndHandle方法处理请求
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        if (asyncManager.isConcurrentHandlingStarted()) {
            return null;
        }

        // 38. 处理返回的结果,结果信息在mavContainer
        return getModelAndView(mavContainer, modelFactory, webRequest);
    }
    finally {
        webRequest.requestCompleted();
    }
}

// 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
        ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

    modelFactory.updateModel(webRequest, mavContainer);
    // 39. 参考步骤33,有些ReturnValueHandler会提前置为"请求已处理",一般应用于直接返回数据而不需要渲染View的场景
    if (mavContainer.isRequestHandled()) {
        return null;
    }
    
    // 40. 初始化ModelAndView并返回
    ModelMap model = mavContainer.getModel();
    ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
    if (!mavContainer.isViewReference()) {
        mav.setView((View) mavContainer.getView());
    }
    if (model instanceof RedirectAttributes) {
        Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        if (request != null) {
            RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
        }
    }
    return mav;
}

// 源码位置:org.springframework.web.servlet.DispatcherServlet
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
        @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
        @Nullable Exception exception) throws Exception {
    boolean errorView = false;

    // 41. 如果有一次,则处理为异常ModelAndView
    if (exception != null) {
        if (exception instanceof ModelAndViewDefiningException) {
            logger.debug("ModelAndViewDefiningException encountered", exception);
            mv = ((ModelAndViewDefiningException) exception).getModelAndView();
        }
        else {
            Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
            mv = processHandlerException(request, response, handler, exception);
            errorView = (mv != null);
        }
    }

    if (mv != null && !mv.wasCleared()) {
        // 42. 渲染ModelAndView,如果是返回数据的则mv=null,不需要渲染
        render(mv, request, response);
        if (errorView) {
            WebUtils.clearErrorRequestAttributes(request);
        }
    }
    else {
        if (logger.isTraceEnabled()) {
            logger.trace("No view rendering, null ModelAndView returned.");
        }
    }

    if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
        return;
    }

    if (mappedHandler != null) {
        mappedHandler.triggerAfterCompletion(request, response, null);
    }
}

2.2 源码分析

如果简略一点地理解,则可以理解为:

  • 由HandlerMapping匹配到Controller的方法HandlerMethod;
  • 由HandlerMethodArgumentResolver把请求的参数处理为Controller方法的参数;
  • 由ReturnValueHandler把Controller方法的返回值处理为响应数据,其里面包含了MessageConverter对Controller方法的返回值进行转换处理;
  • 由ViewResolver把Controller方法的返回值处理为响应的视图,由
  • 由DispatcherServlet进行协调HandlerMapping、HandlerAdapter、ViewResolver这些对象的关系;
  • HandlerAdapter则协调HandlerMethodArgumentResolver、ReturnValueHandler的关系;
  • DispatcherServlet对外暴露service接口,由tomcat服务器在接收请求后,通过service接口派发请求。

2.2.1 DispatcherServlet初始化

在发起请求的时候,tomcat处理请求会调到StandardWrapperValve的invoke方法,在这个方法才初始化DispatcherServlet:

java 复制代码
// 源码位置:org.apache.catalina.core.StandardWrapperValve
public void invoke(Request request, Response response) throws IOException, ServletException {       boolean unavailable = false;
    Throwable throwable = null;
    long t1 = System.currentTimeMillis();
    requestCount.incrementAndGet();
    StandardWrapper wrapper = (StandardWrapper) getContainer();
    Servlet servlet = null;
    Context context = (Context) wrapper.getParent();

    // 省略部分代码

    try {
        if (!unavailable) {
            // 1. 创建DispatcherServlet
            servlet = wrapper.allocate();
        }
    } 
    // 省略部分代码

    MessageBytes requestPathMB = request.getRequestPathMB();
    DispatcherType dispatcherType = DispatcherType.REQUEST;
    if (request.getDispatcherType() == DispatcherType.ASYNC) {
        dispatcherType = DispatcherType.ASYNC;
    }
    request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, dispatcherType);
    request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);
    
    ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
    // 省略其它代码
}

// 源码位置:org.apache.catalina.core.StandardWrapper
public Servlet allocate() throws ServletException {
    if (unloading) {
        throw new ServletException(sm.getString("standardWrapper.unloading", getName()));
    }

    boolean newInstance = false;

    if (!singleThreadModel) {
        if (instance == null || !instanceInitialized) {
            synchronized (this) {
                if (instance == null) {
                    try {
                        if (log.isDebugEnabled()) {
                            log.debug("Allocating non-STM instance");
                        }
                        instance = loadServlet();
                        newInstance = true;
                        if (!singleThreadModel) {
                            countAllocated.incrementAndGet();
                        }
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        ExceptionUtils.handleThrowable(e);
                        throw new ServletException(sm.getString("standardWrapper.allocate"), e);
                    }
                }
                if (!instanceInitialized) {
                    // 2. 初始化DispatcherServlet
                    initServlet(instance);
                }
            }
        }
        // 省略其它代码
    }
    // 省略其它代码
}
private synchronized void initServlet(Servlet servlet) throws ServletException {
    if (instanceInitialized && !singleThreadModel) {
        return;
    }

    try {
        if (Globals.IS_SECURITY_ENABLED) {
            boolean success = false;
            try {
                Object[] args = new Object[] { facade };
                SecurityUtil.doAsPrivilege("init", servlet, classType, args);
                success = true;
            } finally {
                if (!success) {
                    SecurityUtil.remove(servlet);
                }
            }
        } else {
            // 3. 初始化DispatcherServlet
            servlet.init(facade);
        }

        instanceInitialized = true;
    }
    // 省略其它代码
}

// 回到StandardWrapperValve的invoke()继续处理
// 源码位置:org.apache.catalina.core.StandardWrapperValve
public void invoke(Request request, Response response) throws IOException, ServletException {       boolean unavailable = false;
    Throwable throwable = null;
    long t1 = System.currentTimeMillis();
    requestCount.incrementAndGet();
    StandardWrapper wrapper = (StandardWrapper) getContainer();
    Servlet servlet = null;
    Context context = (Context) wrapper.getParent();

    // 省略部分代码

    try {
        if (!unavailable) {
            // 1. 创建DispatcherServlet
            servlet = wrapper.allocate();
        }
    } 
    // 省略部分代码

    MessageBytes requestPathMB = request.getRequestPathMB();
    DispatcherType dispatcherType = DispatcherType.REQUEST;
    if (request.getDispatcherType() == DispatcherType.ASYNC) {
        dispatcherType = DispatcherType.ASYNC;
    }
    request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, dispatcherType);
    request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);
    
    // 4. 把DispatcherServlet设置到ApplicationFilterChain中进行服务响应
    ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
    // 省略其它代码
}

2.2.2 HandlerMapping和HandlerInterceptor的初始化

HandlerMapping和HandlerInterceptor都是在WebMvcConfigurationSupport初始化的:

java 复制代码
// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
// WebMvcConfigurationSupport会创建HandlerMapping,大致有以下几个(源码只列了两个为例):
//    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
//    org.springframework.boot.autoconfigure.web.servlet.WelcomePageHandlerMapping
//    org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
//    org.springframework.web.servlet.function.support.RouterFunctionMapping
//    org.springframework.boot.autoconfigure.web.servlet.WelcomePageNotAcceptableHandlerMapping
//    org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
@Bean
@SuppressWarnings("deprecation")
public RequestMappingHandlerMapping requestMappingHandlerMapping(
        @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
        @Qualifier("mvcConversionService") FormattingConversionService conversionService,
        @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
     // 1. 创建RequestMappingHandlerMapping
     RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
    mapping.setOrder(0);
    mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider)); // 设置HandlerInterceptor
    mapping.setContentNegotiationManager(contentNegotiationManager);
    mapping.setCorsConfigurations(getCorsConfigurations());
    // 省略其它代码
}
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
    // 2. 创建RequestMappingHandlerMapping
    return new RequestMappingHandlerMapping();
}

// 回到WebMvcConfigurationSupport的requestMappingHandlerMapping()继续处理
// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
public RequestMappingHandlerMapping requestMappingHandlerMapping(
        @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
        @Qualifier("mvcConversionService") FormattingConversionService conversionService,
        @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
    // 1. 创建RequestMappingHandlerMapping
    RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
    mapping.setOrder(0);
    
    // 3. 设置HandlerInterceptor
    mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider)); 
    mapping.setContentNegotiationManager(contentNegotiationManager);
    mapping.setCorsConfigurations(getCorsConfigurations());
    // 省略其它代码
}
protected final Object[] getInterceptors(
        FormattingConversionService mvcConversionService,
        ResourceUrlProvider mvcResourceUrlProvider) {

    if (this.interceptors == null) {
        InterceptorRegistry registry = new InterceptorRegistry();
        // 4. 加载自定义的HandlerInterceptor
        addInterceptors(registry);
        // 默认的两个HandlerInterceptor
        registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService));
        registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider));
        this.interceptors = registry.getInterceptors();
    }
    return this.interceptors.toArray();
}

// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
@Bean
public HandlerMapping viewControllerHandlerMapping(
        @Qualifier("mvcConversionService") FormattingConversionService conversionService,
        @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
    ViewControllerRegistry registry = new ViewControllerRegistry(this.applicationContext);
    addViewControllers(registry);

    // 5. 创建HandlerMapping
    AbstractHandlerMapping handlerMapping = registry.buildHandlerMapping();
    if (handlerMapping == null) {
        return null;
    }
    PathMatchConfigurer pathConfig = getPathMatchConfigurer();
    if (pathConfig.getPatternParser() != null) {
        handlerMapping.setPatternParser(pathConfig.getPatternParser());
    }
    else {
        handlerMapping.setUrlPathHelper(pathConfig.getUrlPathHelperOrDefault());
        handlerMapping.setPathMatcher(pathConfig.getPathMatcherOrDefault());
    }
    handlerMapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
    handlerMapping.setCorsConfigurations(getCorsConfigurations());
    return handlerMapping;
}
protected SimpleUrlHandlerMapping buildHandlerMapping() {
    if (this.registrations.isEmpty() && this.redirectRegistrations.isEmpty()) {
        return null;
    }

    Map<String, Object> urlMap = new LinkedHashMap<>();
    for (ViewControllerRegistration registration : this.registrations) {
        urlMap.put(registration.getUrlPath(), registration.getViewController());
    }
    for (RedirectViewControllerRegistration registration : this.redirectRegistrations) {
        urlMap.put(registration.getUrlPath(), registration.getViewController());
    }

    // 6. 创建SimpleUrlHandlerMapping
    return new SimpleUrlHandlerMapping(urlMap, this.order);
}

// 回到WebMvcConfigurationSupport的viewControllerHandlerMapping()继续处理
// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
@Bean
public HandlerMapping viewControllerHandlerMapping(
        @Qualifier("mvcConversionService") FormattingConversionService conversionService,
        @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
    ViewControllerRegistry registry = new ViewControllerRegistry(this.applicationContext);
    addViewControllers(registry);

    // 5. 创建HandlerMapping
    AbstractHandlerMapping handlerMapping = registry.buildHandlerMapping();
    if (handlerMapping == null) {
        return null;
    }
    PathMatchConfigurer pathConfig = getPathMatchConfigurer();
    if (pathConfig.getPatternParser() != null) {
        handlerMapping.setPatternParser(pathConfig.getPatternParser());
    }
    else {
        handlerMapping.setUrlPathHelper(pathConfig.getUrlPathHelperOrDefault());
        handlerMapping.setPathMatcher(pathConfig.getPathMatcherOrDefault());
    }
    
    // 7. 设置HandlerInterceptor,把同样的Interceptor设置到handlerMapping里
    handlerMapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
    handlerMapping.setCorsConfigurations(getCorsConfigurations());
    return handlerMapping;
}

// DispatcherServlet初始化的时候,会初始化HandlerMapping
// 源码位置:org.springframework.web.servlet.DispatcherServlet
private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;

    // 8. 初始化HandlerMapping,先找接口HandlerMapping,如果没有则从Context里取名称位handlerMapping的
    if (this.detectAllHandlerMappings) {
        Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerMappings = new ArrayList<>(matchingBeans.values());
            AnnotationAwareOrderComparator.sort(this.handlerMappings);
        }
    }
    else {
        try {
            // HANDLER_MAPPING_BEAN_NAME = "handlerMapping"
            HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
            this.handlerMappings = Collections.singletonList(hm);
        }
        catch (NoSuchBeanDefinitionException ex) {
        }
    }

    if (this.handlerMappings == null) {
        this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
        if (logger.isTraceEnabled()) {
            logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
                    "': using default strategies from DispatcherServlet.properties");
        }
    }

    for (HandlerMapping mapping : this.handlerMappings) {
        if (mapping.usesPathPatterns()) {
            this.parseRequestPath = true;
            break;
        }
    }
}

// DispatcherServlet在响应请求的时候,会使用HandlerMapping匹配Controller方法,同时执行HandlerInterceptor
// 源码位置:org.springframework.web.servlet.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 {
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // 9. mappedHandler为HandlerExecutionChain,里面包含了HandlerMethod和HandlerInterceptor
            // 通过HandlerMapping找到HandlerMethod,创建HandlerExecutionChain时把HandlerMethod设置到里面
            // 在初始化的时候每个HandlerMapping都设置了所有的HandlerInterceptor,取出来设置到HandlerExecutionChain里面
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            String method = request.getMethod();
            boolean isGet = HttpMethod.GET.matches(method);
            if (isGet || HttpMethod.HEAD.matches(method)) {
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                    return;
                }
            }

            // 10. 执行HandlerInterceptor拦截器的preHandle()方法
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            // Actually invoke the handler.
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }

            applyDefaultViewName(processedRequest, mv);
            
            // 11. 执行HandlerInterceptor拦截器的postHandle()方法
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        }
    // 省略其它代码
}

2.2.3 RequestMappingHandlerAdapter初始化

RequestMappingHandlerAdapter是在启动的时候,加载WebMvcAutoConfiguration这个自动配置时作为一个bean初始化的,在DispatcherServlet初始化的时候通过bean查找设置到DispatcherServlet里:

java 复制代码
// 源码位置:org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.EnableWebMvcConfiguration
@AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class WebMvcAutoConfiguration {
    @Configuration(proxyBeanMethods = false)
    @EnableConfigurationProperties(WebProperties.class)
    public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
        @Bean
        @Override
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
                @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
                @Qualifier("mvcConversionService") FormattingConversionService conversionService,
                @Qualifier("mvcValidator") Validator validator) {
            // 调父类方法创建RequestMappingHandlerAdapter
            RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(contentNegotiationManager, conversionService, validator);
            adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect());
            return adapter;
        }
    }
}
// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
        @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
        @Qualifier("mvcConversionService") FormattingConversionService conversionService,
        @Qualifier("mvcValidator") Validator validator) {
    // 创建RequestMappingHandlerAdapter
    RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
    adapter.setContentNegotiationManager(contentNegotiationManager);
    adapter.setMessageConverters(getMessageConverters());
    adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
    adapter.setCustomArgumentResolvers(getArgumentResolvers());
    adapter.setCustomReturnValueHandlers(getReturnValueHandlers());

    if (jackson2Present) {
        adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
        adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
    }

    AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
    if (configurer.getTaskExecutor() != null) {
        adapter.setTaskExecutor(configurer.getTaskExecutor());
    }
    if (configurer.getTimeout() != null) {
        adapter.setAsyncRequestTimeout(configurer.getTimeout());
    }
    adapter.setCallableInterceptors(configurer.getCallableInterceptors());
    adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());

    return adapter;
}
protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
    // 继承关系:RequestMappingHandlerAdapter < AbstractHandlerMethodAdapter < HandlerAdapter
    return new RequestMappingHandlerAdapter();
}


// 源码位置:org.springframework.web.servlet.DispatcherServlet
private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;

    if (this.detectAllHandlerAdapters) {
        // 用Spring工具,查找实现了HandlerAdapter接口的类,RequestMappingHandlerAdapter实现了HandlerAdapter接口
        Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerAdapters = new ArrayList<>(matchingBeans.values());
            AnnotationAwareOrderComparator.sort(this.handlerAdapters);
        }
    }
    else {
        try {
            // HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter"
            // 根据名称和类型查找对应的bean
            HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
            this.handlerAdapters = Collections.singletonList(ha);
        }
        catch (NoSuchBeanDefinitionException ex) {
        }
    }

    if (this.handlerAdapters == null) {
        // 查找在DispatcherServlet.properties(与DispatcherServlet同目录)中配置的HandlerAdapter
        this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
        if (logger.isTraceEnabled()) {
            logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
                    "': using default strategies from DispatcherServlet.properties");
        }
    }
}

2.2.4 ViewResolver初始化

ViewResolver也是在WebMvcAutoConfiguration中自动配置为Bean,然后在DispatcherServlet中用Spring工具查找所有实现了ViewResolver接口得到:

java 复制代码
// org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter
@Bean
@ConditionalOnMissingBean
public InternalResourceViewResolver defaultViewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix(this.mvcProperties.getView().getPrefix());
    resolver.setSuffix(this.mvcProperties.getView().getSuffix());
    return resolver;
}
@Bean
@ConditionalOnBean(View.class)
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
    BeanNameViewResolver resolver = new BeanNameViewResolver();
    resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
    return resolver;
}
@Bean
@ConditionalOnBean(ViewResolver.class)
@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
    ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
    resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class));
    // ContentNegotiatingViewResolver uses all the other view resolvers to locate
    resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return resolver;
}


// 源码位置:org.springframework.web.servlet.DispatcherServlet
private void initViewResolvers(ApplicationContext context) {
    this.viewResolvers = null;

    if (this.detectAllViewResolvers) {
        // 根据ViewResolver接口获取到已经注册的Bean
        Map<String, ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.viewResolvers = new ArrayList<>(matchingBeans.values());
            AnnotationAwareOrderComparator.sort(this.viewResolvers);
        }
    }
    else {
        try {
            ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
            this.viewResolvers = Collections.singletonList(vr);
        }
        catch (NoSuchBeanDefinitionException ex) {
        }
    }

    if (this.viewResolvers == null) {
        this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
        if (logger.isTraceEnabled()) {
            logger.trace("No ViewResolvers declared for servlet '" + getServletName() +
                    "': using default strategies from DispatcherServlet.properties");
        }
    }
}

3 架构一小步

SpringMVC在调Controller的接口方法前后会分别先调HandlerInterceptor的preHandle()和postHandle(),后面可以用来做扩展。

相关推荐
brzhang9 分钟前
我十几个项目都是这套Flutter 快速开发框架,今天开源了,从此你只用关心业务了
前端·后端·架构
东边有耳1 小时前
一文深扒银行会计科目(收藏备查)
后端·架构·产品经理
shinelord明5 小时前
【计算机网络架构】树型架构简介
计算机网络·架构·计算机科学·计算机科学与技术
杨进军5 小时前
微前端之子应用的启动与改造
前端·架构
俞凡8 小时前
Netflix 数据网关实践
架构
_花卷8 小时前
🌟ELPIS-如何基于vue3完成领域模型架构
前端·vue.js·架构
司铭鸿10 小时前
Java无服务架构新范式:Spring Native与AWS Lambda冷启动深度优化
数据结构·算法·架构·排序算法·代理模式
小哈里10 小时前
【管理】持续交付2.0:业务引领的DevOps-精要增订本,读书笔记(理论模型,技术架构,业务价值)
运维·架构·devops·管理·交付
曾经的三心草12 小时前
微服务的编程测评系统-网关-身份认证-redis-jwt
redis·微服务·架构