总结摘要
SpringMVC Web DispatcherServlet#doDispatch Method Execution Process
请求入口
1
2
3
4
5
6
7
| -> Tomcat 网络连接
-> StandardEngineValve
-> StandardHostValve
-> StandardContextValve
-> StandardContextValve
-> ApplicationFilterChain
-> HttpServlet
|
Servlet 入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // 请求流程
// javax.servlet.http.HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
-> org.springframework.web.servlet.FrameworkServlet#service
-> 如果是 PATCH 方法或空方法。if (httpMethod == HttpMethod.PATCH || httpMethod == null)
-> 详情参加 POST 方法。org.springframework.web.servlet.FrameworkServlet#processRequest
-> javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
-> 根据方法类型路由到不同的方法。
-> GET:lastModified 参数相关适配。
-> POST:org.springframework.web.servlet.FrameworkServlet#doPost
-> org.springframework.web.servlet.FrameworkServlet#processRequest
-> LocaleContext,RequestAttributes 等处理,略。
-> org.springframework.web.servlet.DispatcherServlet#doService
-> 详情参加分支 DispatcherServlet#doDispatch。org.springframework.web.servlet.DispatcherServlet#doDispatch
-> PUT:略。
-> OPTION:略。
-> 其它方法略。
|
请求分发
分支 DispatcherServlet#doDispatch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
| 分支 DispatcherServlet#doDispatch
org.springframework.web.servlet.DispatcherServlet#doDispatch
-> WebAsyncManager 预处理,获取或创建 WebAsyncManager。org.springframework.web.context.request.async.WebAsyncUtils#getAsyncManager(javax.servlet.ServletRequest)
-> 场景一:获取。servletRequest.getAttribute(WEB_ASYNC_MANAGER_ATTRIBUTE)
-> 场景二:创建。new WebAsyncManager(),存储到属性中。
-> 当前获取成功。
-> multipart 相关处理,如果是 multipart 请求,则将 request 封装为 StandardMultipartHttpServletRequest 或 DefaultMultipartHttpServletRequest。org.springframework.web.servlet.DispatcherServlet#checkMultipart
-> this.multipartResolver 的默认实现类是 org.springframework.web.multipart.support.StandardServletMultipartResolver。另外一种实现是 org.springframework.web.multipart.commons.CommonsMultipartResolver。
-> 校验 Multipart。org.springframework.web.multipart.support.StandardServletMultipartResolver#isMultipart
-> 默认是宽松校验方式。
-> 宽松校验方式:校验 ContentType 是 `multipart/` 开头。
-> 严格校验方式:严格遵守 Servlet 规范,校验 ContentType 是 `multipart/form-data`。
-> if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class)) 如果 request instanceof MultipartHttpServletRequest,则返回。
-> else 将 request 封装为 MultipartHttpServletRequest 的实现类 StandardMultipartHttpServletRequest(默认)或 DefaultMultipartHttpServletRequest。
-> 封装 request。org.springframework.web.multipart.MultipartResolver#resolveMultipart
-> 从 this.handlerMappings 查找适用的 Handler,返回第一个匹配的 HandlerExecutionChain。org.springframework.web.servlet.DispatcherServlet#getHandler
-> for-each this.handlerMappings。
-> 默认有 6 个,有序排列,分别如下。其中第一个是关键实现,即 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping。
-> RequestMappingHandlerMapping
-> WelcomePageHandlerMapping
-> BeanNameUrlHandlerMapping
-> RouterFunctionMapping
-> WelcomePageNotAcceptableHandlerMapping
-> SimpleUrlHandlerMapping
-> 调用 mapping.getHandler(request),如果找到了适用的 HandlerExecutionChain,退出 for-each,即返回第一个。
-> 以 RequestMappingHandlerMapping 为例分析,详情参见《分支 RequestMappingHandlerMapping#getHandler》。
-> 如果未找到,则抛出异常。org.springframework.web.servlet.DispatcherServlet#noHandlerFound。
-> 从 this.handlerAdapters 查找并返回第一个匹配的 HandlerAdapter。org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter
-> for-each this.handlerAdapters
-> 当前有 4 个,默认始终返回 RequestMappingHandlerAdapter。
-> 如果 org.springframework.web.servlet.HandlerAdapter#supports 为 true,则退出 for-each,返回第一个匹配的 HandlerAdapter。
-> 以 RequestMappingHandlerAdapter 为例分析。
-> org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports
-> 要求 handle 是 HandlerMethod 的实例且 supportsInternal 方法返回 true。
-> RequestMappingHandlerAdapter#supportsInternal 始终返回 true。因此几乎所有请求都会使用 RequestMappingHandlerAdapter。
-> 例外场景,CORS 预检查请求 handler PreFlightHandler 不是 HandlerMethod 实例,而是 HttpRequestHandler 实例。
-> 如果未找到匹配的,则抛出 ServletException 异常。
-> 如果请求方法是 GET 或 HEAD,分析 lastModified 判断是否可以直接返回请求。
-> 拦截器处理,执行上一步筛选出的 interceptor。org.springframework.web.servlet.HandlerExecutionChain#applyPreHandle
-> for-each interceptorList
-> 调用 preHandle 方法。org.springframework.web.servlet.HandlerInterceptor#preHandle
-> 如果有 preHandle 方法返回 false,则调用 org.springframework.web.servlet.HandlerExecutionChain#triggerAfterCompletion,然后返回 false。
-> 默认返回 true。
-> 如果 applyPreHandle 返回 false,则退出方法。
-> 执行 handle 方法。org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
-> 执行 handle 方法。以 RequestMappingHandlerAdapter,详情参见《RequestMappingHandlerAdapter#handleInternal》。
-> 如果满足 if (asyncManager.isConcurrentHandlingStarted()),则返回方法。
-> 视图名称处理。org.springframework.web.servlet.DispatcherServlet#applyDefaultViewName
-> 默认视图。org.springframework.web.servlet.DispatcherServlet#getDefaultViewName
-> 调用默认视图处理器。org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator#getViewName
-> 拦截器处理。org.springframework.web.servlet.HandlerExecutionChain#applyPostHandle
-> for-each interceptorList
-> 调用 postHandle 方法。org.springframework.web.servlet.HandlerInterceptor#postHandle
-> 处理请求结果。org.springframework.web.servlet.DispatcherServlet#processDispatchResult
-> 异常处理。详情参见其它篇章。org.springframework.web.servlet.DispatcherServlet#processHandlerException
-> 拦截器 AfterCompletion 方法。org.springframework.web.servlet.HandlerExecutionChain#triggerAfterCompletion
-> for-each interceptorList, org.springframework.web.servlet.HandlerInterceptor#afterCompletion
-> 异步请求相关处理,详情略。asyncManager.isConcurrentHandlingStarted()
-> 文件上传相关处理,详情略。if (multipartRequestParsed),org.springframework.web.servlet.DispatcherServlet#cleanupMultipart
|
分支
分支 RequestMappingHandlerMapping#getHandler
入口方法
org.springframework.web.servlet.DispatcherServlet#getHandler
org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
主流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
| // org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
-> org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#getHandlerInternal
-> org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal
-> org.springframework.web.servlet.handler.AbstractHandlerMapping#initLookupPath
-> if (usesPathPatterns()) 当前满足条件。
-> 判断逻辑是判断 this.patternParser 是否存在,即 org.springframework.web.servlet.handler.AbstractHandlerMapping#patternParser。
-> 当前使用 org.springframework.web.util.pattern.PathPatternParser。
-> 查找已解析并缓存在属性中的 RequestPath。org.springframework.web.util.ServletRequestPathUtils#getParsedRequestPath
-> 删除 path 中的分号及之后的内容,包含 JsessionId。org.springframework.web.util.UrlPathHelper#removeSemicolonContent
-> else
-> 使用 this.urlPathHelper 解析 request path。org.springframework.web.util.UrlPathHelper#resolveAndCacheLookupPath
-> org.springframework.web.util.UrlPathHelper#getLookupPathForRequest(javax.servlet.http.HttpServletRequest) 详情略。
-> this.mappingRegistry 锁处理,并发控制。
-> org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#lookupHandlerMethod
-> 根据 path 筛选符合条件的处理器,常用实现类是 RequestMappingInfo,此处为宽松匹配。org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#getMappingsByDirectPath
-> 调用 this.pathLookup.get(urlPath);
-> 变量定义 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#pathLookup
-> 变量定义 private final MultiValueMap<String, T> pathLookup = new LinkedMultiValueMap<>();
-> 严格匹配。org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#addMatchingMappings
-> for-each mappings, 即上一步宽松匹配的结果。
-> 严格匹配。org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#getMatchingMapping
-> 调用 org.springframework.web.servlet.mvc.method.RequestMappingInfo#getMatchingCondition
-> 严格匹配 Request 的各种属性是否满足条件,如果不满足则返回 null,如果满足则返回重新封装的 RequestMappingInfo 对象。
-> 校验的属性包括 http method,params,headers,consumes,produces 等。
-> 封装为包含 HandlerMethod 和关联 mapping 的 Match。org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.Match
-> 如果未找到,则从全量候选值中进行严格匹配,筛选核实的 mapping。
-> 如果匹配多个,则排序,找到最优的选择。org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MatchComparator#MatchComparator
-> 暴露 URL 中涉及的变量。org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
-> 为 Request 缓存属性,值为 lookupPath。org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#handleMatch
-> matrix variables 处理。org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#extractMatchDetails(org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition, java.lang.String, javax.servlet.http.HttpServletRequest)
-> mediaTypes 处理。
-> 返回 HandlerMethod。
-> org.springframework.web.method.HandlerMethod#createWithResolvedBean
-> 从 beanFactory 中获取 Controller bean。
-> 重新封装为 HandlerMethod。new HandlerMethod。
-> this.mappingRegistry 锁处理,并发控制。
-> 如果未找到合适的 handler,则使用 this.defaultHandler,默认为 null。
-> 确认 URL path 属性已缓存。org.springframework.web.util.ServletRequestPathUtils#hasCachedPath
-> org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandlerExecutionChain
-> for-each this.adaptedInterceptors
-> 当前有 4 个,其中 3 个是默认的(均非 MappedInterceptor),有序排列,分别是:
-> MappedInterceptor,内部是自定义的 TraceIdInterceptor implements HandlerInterceptor 的封装体。关联定义为 registry.addInterceptor(new TraceIdInterceptor()).addPathPatterns("/**");。
-> WebRequestHandlerInterceptorAdapter,内部是 org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor,与 JPA 有关,略。
-> ConversionServiceExposingInterceptor,主要适用于 JSP 标签,具体是将 ConversionService 添加到 request 的属性中,略。
-> ResourceUrlProviderExposingInterceptor,将 ResourceUrlProvider 配置在属性中,略。
-> if (interceptor instanceof MappedInterceptor) 则进一步判断是否匹配,如果不匹配则忽略。
-> 如果 if (mappedInterceptor.matches(request)) 为 true,将 interceptor 则追加到 HandlerExecutionChain。
-> chain.addInterceptor(mappedInterceptor.getInterceptor());
-> else
-> 将 interceptor 追加到 HandlerExecutionChain。
-> Cors 相关处理。
-> 判断请求是否涉及 CORS 配置。org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#hasCorsConfigurationSource
-> org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#getCorsConfiguration
-> 使用缓存 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#corsLookup
-> 判断是否是 CORS 预检查请求,方法是 OPTIONS,且包含相关请求属性。org.springframework.web.cors.CorsUtils#isPreFlightRequest
-> if 是 CORS 预检查请求,则 new PreFlightHandler 并配置 interceptors 后作为 HandlerExecutionChain 返回。
-> else 将 new CorsInterceptor 添加到 interceptors 并作为第一个。校验 ORIGIN 等等。
|
包含路径参数的 url,例如 /explore/hello//hello/{name}/morning不会被缓存到 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#pathLookup中。
debug 验证
this.mappingRegistry.getMappingsByDirectPath("/explore/hello/hello/user1/morning") = null。
1
2
3
4
| @GetMapping("/hello/{name}/morning")
public Map<String, String> hello2(@PathVariable(value = "name") @Length(min = 2) String name) {
return Collections.singletonMap("body", "Hello, " + name + " , morning");
}
|
客户端请求可能会精确匹配到多个@RequestMapping的场景构造。
包含通配符的 URL 的优先级更低。
1
2
3
4
5
| @GetMapping("/morning/{name}")
public Map<String, String> morning1(@PathVariable(value = "name") @Length(min = 2) String name);
@GetMapping("/morning/**")
public Map<String, String> morning2();
|
分支 RequestMappingHandlerAdapter#handleInternal
入口方法
org.springframework.web.servlet.DispatcherServlet#doDispatch
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
主流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
| -> 预检查,无实际作用。org.springframework.web.servlet.support.WebContentGenerator#checkRequest
-> if (this.synchronizeOnSession) 相关 session 处理。略。
-> 执行 handle 方法。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod
-> 将 request 和 response 封装为 ServletWebRequest 类。new ServletWebRequest。
-> 获取 WebDataBinderFactory。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getDataBinderFactory
-> 根据 Controller 的 class 从缓存 this.initBinderCache 中获取。第一次请求为空。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#initBinderCache
-> 如果缓存中未找到,则从 Controller 的 class 中筛选注解 @InitBinder 修饰的方法,并存储在缓存。
-> 遍历 initBinderAdviceCache
-> 变量位置 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#initBinderAdviceCache
-> 变量定义 private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>();
-> 如果 org.springframework.web.method.ControllerAdviceBean#isApplicableToBeanType 满足条件
-> 从 beanFactory 中获取 controller bean
-> for-each methodSet,即 initBinderAdviceCache 的 value。
-> 将 bean 与 method 封装为 InvocableHandlerMethod。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#createInitBinderMethod。
-> 配置属性 HandlerMethodArgumentResolvers,DataBinderFactory,ParameterNameDiscoverer。
-> 并临时缓存到方法变量中。
-> for-each methods,即从 this.initBinderCache 的 value。
-> 参考上文,详情略。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#createInitBinderMethod
-> 并临时缓存到方法变量中。
-> 创建 InitBinderDataBinderFactory。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#createDataBinderFactory
-> 将 binderMethods 与 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#webBindingInitializer 封装为 ServletRequestDataBinderFactory。new ServletRequestDataBinderFactory。
-> 此处的 this.webBindingInitializer 实例是 ConfigurableWebBindingInitializer,其中的 validator 和 conversionService 属性不为空,而 propertyEditorRegistrars 属性为空,其它属性是默认值或为 null。
-> 获取 ModelFactory。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getModelFactory
-> 以 controller class 作为 key 获取或生成 SessionAttributesHandler,其支持解析 @SessionAttributes 注解定义的属性。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getSessionAttributesHandler
-> 默认 this.sessionAttributeStore 的实例是 org.springframework.web.bind.support.DefaultSessionAttributeStore。
-> 以 controller class 作为 key 从 this.modelAttributeCache 获取 method。
-> 如果上一步缓存为空,则筛选并解析 controller class 中同时由 @RequestMapping 注解和 @ModelAttribute 注解修饰的方法,并存储到缓存。
-> for-each modelAttributeAdviceCache
-> 变量定义 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#modelAttributeAdviceCache
-> 变量定义 private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>();
-> 如果 isApplicableToBeanType 满足条件,则创建 ModelAttributeMethod。
-> 判断逻辑。org.springframework.web.method.ControllerAdviceBean#isApplicableToBeanType
-> 判断逻辑。org.springframework.web.method.HandlerTypePredicate#test
-> for-each methodSet,即 modelAttributeAdviceCache 的 value。
-> 封装为 InvocableHandlerMethod。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#createModelAttributeMethod
-> 配置属性 HandlerMethodArgumentResolvers,ParameterNameDiscoverer,DataBinderFactory。
-> for-each methods,即 modelAttributeCache 的 value。
-> 封装为 InvocableHandlerMethod,详情略。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#createModelAttributeMethod。
-> 将 ModelAttribute、SessionAttribute 和 WebDataBinderFactory 封装为 ModelFactory。new ModelFactory。
-> 获取 ServletInvocableHandlerMethod。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#createInvocableHandlerMethod
-> new ServletInvocableHandlerMethod
-> 为 ServletInvocableHandlerMethod 填充 argumentResolvers,returnValueHandlers,binderFactory 和 parameterNameDiscoverer 属性。
-> 此时属性分别是 HandlerMethodArgumentResolverComposite,HandlerMethodReturnValueHandlerComposite,ServletRequestDataBinderFactory,DefaultParameterNameDiscoverer。
-> 创建 ModelAndViewContainer。new ModelAndViewContainer。
-> ModelAndViewContainer 初始化,包括配置 InputFlashMap,@SessionAttributes 和 @ModelAttribut 注解处理等。
-> 创建 AsyncWebRequest 实例 StandardServletAsyncWebRequest。org.springframework.web.context.request.async.WebAsyncUtils#createAsyncWebRequest
-> 将 request 和 response 封装为 StandardServletAsyncWebRequest 实例。new StandardServletAsyncWebRequest
-> 始终创建实例,与请求是否是异步无关。
-> 获取或创建 WebAsyncManager 实例。org.springframework.web.context.request.async.WebAsyncUtils#getAsyncManager(javax.servlet.ServletRequest)
-> 场景一:获取,servletRequest.getAttribute(WEB_ASYNC_MANAGER_ATTRIBUTE)。debug 时(第一次请求)成功获取。
-> 场景二:创建,new WebAsyncManager()
-> 配置 WebAsyncManager,包括 taskExecutor,asyncWebRequest,callableInterceptors,deferredResultInterceptors。
-> 当前未进行任何异步或线程池相关配置,因此 this.taskExecutor 属性默认实例是 SimpleAsyncTaskExecutor。
-> this.callableInterceptors 和 this.deferredResultInterceptors 均为空集合。
-> if (asyncManager.hasConcurrentResult()),则进行相关处理。debug 时不满足条件。
-> 调用 handle 方法。org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle
-> 调用方法。org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest
-> 解析方法参数。org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues
-> 获取 HandlerMethod 方法的形式参数(入参)。org.springframework.web.method.HandlerMethod#getMethodParameters
-> for-each parameters
-> 如果方法入参 providedArgs 包含当前期望的 parameter,则直接返回;根据对象类型匹配。org.springframework.web.method.HandlerMethod#findProvidedArgument
-> 目前发现正常请求不会使用 providedArgs,仅异常处理相关会使用 providedArgs。org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#doResolveHandlerMethodException
-> 如果处理器不支持处理该参数,则抛出异常 IllegalStateException。org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#supportsParameter
-> this.resolvers 的实例为 HandlerMethodArgumentResolverComposite。
-> 查找匹配的处理器。org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#getArgumentResolver
-> 首先将 MethodParameter 作为 key 从缓存 this.argumentResolverCache 中获取。
-> 如果缓存为空,则遍历 this.argumentResolvers 查找匹配的处理器,并存储到缓存。
-> for-each this.argumentResolvers, org.springframework.web.method.support.HandlerMethodArgumentResolver#supportsParameter
-> 解析参数。org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#resolveArgument
-> 获取 ArgumentResolver。org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#getArgumentResolver
-> 从缓存 this.argumentResolverCache 获取,因为上一步已存储到缓存中,因此缓存一定不为空。否则抛出异常 IllegalArgumentException。
-> 调用 resolver。org.springframework.web.method.support.HandlerMethodArgumentResolver#resolveArgument
-> debug 场景为 @RequestBody 注解参数,因此调用 org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor#resolveArgument。详情参见《分支 RequestResponseBodyMethodProcessor#resolveArgument》。
-> 调用 handler 方法。org.springframework.web.method.support.InvocableHandlerMethod#doInvoke。
-> 反射调用 controller bean 中的方法。method.invoke(getBean(), args);
-> 适配 this.responseStatus,即 ResponseStatus 注解的相关配置。org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#setResponseStatus
-> 标识 response 响应体已处理,无需视图处理。mavContainer.setRequestHandled(false);
-> 变量位置 org.springframework.web.method.support.ModelAndViewContainer#requestHandled
-> 处理返回值。org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite#handleReturnValue
-> 查找匹配的方法。org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite#handleReturnValue
-> 选择。org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite#selectHandler
-> 判断是否是 AsyncReturnValue。org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite#isAsyncReturnValue
-> for-each this.returnValueHandlers,校验条件是 handler instanceof AsyncHandlerMethodReturnValueHandler 且 AsyncHandlerMethodReturnValueHandler#isAsyncReturnValue。
-> for-each this.returnValueHandlers 返回匹配的第一个。org.springframework.web.method.support.HandlerMethodReturnValueHandler#supportsReturnType
-> 执行方法。org.springframework.web.method.support.HandlerMethodReturnValueHandler#handleReturnValue
-> if (asyncManager.isConcurrentHandlingStarted()) 满足条件,则返回 null。
-> 处理 ModelAndView。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getModelAndView
-> 如果响应体不包含 "Cache-Control" heander。
-> 如果当前请求包含了 session attribute,则进行相关配置。
|
END