1 概述
作为Web程序,通用形式是发起HTTP请求并获取返回的结果,在这个过程中,需要把请求映射到代码的接口上,提供这种接口的类一般称为Controller,也就是需要把请求映射到Controller的接口方法上,把请求的参数映射到接口的参数中,并从接口返回接口处理的结果。
在后端渲染页面的场景中,返回的结果需要处理为视图View。而现在更普遍的是前后端分离,返回的结果一般处理为JSON格式的数据,前端拿到这种数据再进行处理和页面的渲染。
本文来了解一下这个请求和响应的过程。
2 原理
2.1 源码解析
在使用SpringBoot的时候,内嵌了一个tomcat服务器,做到了不需要感觉到有web服务器就能够开发web程序。内嵌tomcat服务器由tomcat-embed-core包提供,tomcat接收请求时,会调用到StandardWrapperValve的invoke()方法,下面的源码则从这段代码开始。
// 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 neededif (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为ApplicationFilterChainfilterChain.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方便下次取下一个FilterApplicationFilterConfig 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就是filterChainfilter.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 pointif ((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的HandlerExecutionChainHandlerExecutionChain 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.1processDispatchResult(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、参数名处理器parameterNameDiscovererServletInvocableHandlerMethod 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.1HandlerMethodReturnValueHandler 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. 匹配ReturnValueHandlerif (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.1HandlerMethodReturnValueHandler 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写结果到ServletServerHttpResponsewriteWithMessageConverters(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.8acceptableTypes = 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/*+jsonList<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() {@Overridepublic OutputStream getBody() {return outputStream;}@Overridepublic 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 < HttpOutputMessageStreamUtils.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、参数名处理器parameterNameDiscovererServletInvocableHandlerMethod 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. 处理返回的结果,结果信息在mavContainerreturn 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. 如果有一次,则处理为异常ModelAndViewif (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初始化
// 源码位置: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. 创建DispatcherServletservlet = 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. 初始化DispatcherServletinitServlet(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. 初始化DispatcherServletservlet.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. 创建DispatcherServletservlet = 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初始化的:
// 源码位置: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. 创建RequestMappingHandlerMappingRequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();mapping.setOrder(0);mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider)); // 设置HandlerInterceptormapping.setContentNegotiationManager(contentNegotiationManager);mapping.setCorsConfigurations(getCorsConfigurations());// 省略其它代码
}
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {// 2. 创建RequestMappingHandlerMappingreturn 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. 创建RequestMappingHandlerMappingRequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();mapping.setOrder(0);// 3. 设置HandlerInterceptormapping.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. 加载自定义的HandlerInterceptoraddInterceptors(registry);// 默认的两个HandlerInterceptorregistry.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. 创建HandlerMappingAbstractHandlerMapping 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. 创建SimpleUrlHandlerMappingreturn 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. 创建HandlerMappingAbstractHandlerMapping 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里:
// 源码位置: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@Overridepublic RequestMappingHandlerAdapter requestMappingHandlerAdapter(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,@Qualifier("mvcConversionService") FormattingConversionService conversionService,@Qualifier("mvcValidator") Validator validator) {// 调父类方法创建RequestMappingHandlerAdapterRequestMappingHandlerAdapter 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) {// 创建RequestMappingHandlerAdapterRequestMappingHandlerAdapter 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 < HandlerAdapterreturn 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"// 根据名称和类型查找对应的beanHandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);this.handlerAdapters = Collections.singletonList(ha);}catch (NoSuchBeanDefinitionException ex) {}}if (this.handlerAdapters == null) {// 查找在DispatcherServlet.properties(与DispatcherServlet同目录)中配置的HandlerAdapterthis.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接口得到:
// 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 locateresolver.setOrder(Ordered.HIGHEST_PRECEDENCE);return resolver;
}// 源码位置:org.springframework.web.servlet.DispatcherServlet
private void initViewResolvers(ApplicationContext context) {this.viewResolvers = null;if (this.detectAllViewResolvers) {// 根据ViewResolver接口获取到已经注册的BeanMap<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(),后面可以用来做扩展。