SpringMVC 源码之网络请求(3)

常见三种 HandlerAdapter

  • SimpleControllerHandlerAdapter 处理实现 Controller 接口的方法
  • HttpRequestHandlerAdapter 处理实现 HttpRequestHandler 接口的方法
  • RequestMappingHandlerAdapter 处理使用 @RequestMapping 注解的方法

SimpleControllerHandlerAdapter#handle

定位: org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#handle

处理实现 Controller 接口的方法

1
2
3
4
5
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// Controller 类型的调用
return ((Controller) handler).handleRequest(request, response);
}

HttpRequestHandlerAdapter#handle

定位: org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter#handle

处理实现 HttpRequestHandler 接口的方法

1
2
3
4
5
6
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// HttpRequestHandler 类型的调用
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}

RequestMappingHandlerAdapter

定位: org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
定位: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal

处理实现 Controller 接口的方法

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
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

ModelAndView mav;
// 校验请求(HttpMethod 和 Session 的校验)
checkRequest(request);

// Execute invokeHandlerMethod in synchronized block if required.
// 如果synchronizeOnSession为true,则对session进行同步,否则不同步
if (this.synchronizeOnSession) {
// 同步相同 Session 的逻辑,默认情况false
HttpSession session = request.getSession(false);
if (session != null) {
// 获取Session的锁对象
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}

// 响应不包含'Cache-Control'头
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}

return mav;
}

RequestMappingHandlerAdapter#invokeHandlerMethod

定位: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod

构造 Controller 方法的参数和执行方法

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
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

// 使用request和response创建ServletWebRequest对象
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
// 创建WebDataBinderFactory对象,此对象用来创建WebDataBinder对象,进行参数绑定,
// 实现参数跟String之间的类型转换,ArgumentResolver在进行参数解析的过程中会用到WebDataBinder
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
// 创建ModelFactory对象,此对象主要用来处理model,主要是两个功能,1是在处理器具体处理之前对model进行初始化,2是在处理完请求后对model参数进行更新
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

// 创建ServletInvocableHandlerMethod对象,并设置其相关属性,实际的请求处理就是通过此对象来完成的,参数绑定、处理请求以及返回值处理都在里边完成
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);

// 创建ModelAndViewContainer对象,用于保存model和View对象
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
// 将flashmap中的数据设置到model中
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
// 使用modelFactory将sessionAttributes和注释了@ModelAttribute的方法的参数设置到model中
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
// 根据配置对ignoreDefaultModelOnRedirect进行设置
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

// 创建AsyncWebRequest异步请求对象
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);

// 创建WebAsyncManager异步请求管理器对象
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);
}

// 执行调用
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
// 处理完请求后的后置处理,此处一共做了三件事,
// 1、调用ModelFactory的updateModel方法更新model,包括设置SessionAttribute和给Model设置BinderResult
// 2、根据mavContainer创建了ModelAndView
// 3、如果mavContainer里的model是RedirectAttributes类型,则将其设置到FlashMap
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
// 标记请求完成
webRequest.requestCompleted();
}
}

RequestMappingHandlerAdapter#getDataBinderFactory

定位: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getDataBinderFactory

处理 @InitBinder 注解

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
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
Class<?> handlerType = handlerMethod.getBeanType();
// 检查当前Handler中的initBinder方法是否已经存在于缓存中
Set<Method> methods = this.initBinderCache.get(handlerType);
// 如果没有则查找并设置到缓冲中
if (methods == null) {
methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);// 将当前Controller中所有被@InitBinder注解修饰的方法都获取到
this.initBinderCache.put(handlerType, methods);
}
// 定义保存InitBinder方法的临时变量
List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();
// Global methods first
// 将所有符合条件的全局InitBinder方法添加到initBinderMethods
this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
Object bean = controllerAdviceBean.resolveBean();
for (Method method : methodSet) {
initBinderMethods.add(createInitBinderMethod(bean, method));
}
}
});
// 将当前handler中的initBinder方法添加到initBinderMethods
for (Method method : methods) {
// 创建当前方法对应的bean对象
Object bean = handlerMethod.getBean();
// 将method适配为可执行的invocableHandlerMethod
initBinderMethods.add(createInitBinderMethod(bean, method));
}
// 创建DataBinderFactory并返回
return createDataBinderFactory(initBinderMethods);
}

RequestMappingHandlerAdapter#getModelFactory

定位: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getModelFactory

处理 @ModelAttribute 注解

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
private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
// 获取sessionAttributesHandler
SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
// 获取处理器类的类型
Class<?> handlerType = handlerMethod.getBeanType();
// 获取处理器类中注释了@modelAttribute而且没有注释@RequestMapping的类型,第一个获取后添加到缓存,以后直接从缓存中获取
Set<Method> methods = this.modelAttributeCache.get(handlerType);
if (methods == null) {
methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
this.modelAttributeCache.put(handlerType, methods);
}
// 注释了@ModelAttribute的方法
List<InvocableHandlerMethod> attrMethods = new ArrayList<>();
// Global methods first
// 先添加全局的@ModelAttribute方法,后添加当前处理器定义的@ModelAttribute方法
this.modelAttributeAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
Object bean = controllerAdviceBean.resolveBean();
for (Method method : methodSet) {
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
}
}
});
for (Method method : methods) {
Object bean = handlerMethod.getBean();
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
}
// 新建ModelFactory对象,此处需要三个参数,第一个是注释了@ModelAttribute的方法,第二个是WebDataBinderFactory,第三个是SessionAttributeHandler
return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
}

ServletInvocableHandlerMethod#invokeAndHandle

定位: org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle

执行方法, 处理返回值

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
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {

// 调用父类的invokeForRequest执行请求
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// 处理@ResponseStatus注解
setResponseStatus(webRequest);

// 处理返回值,判断返回值是否为空
if (returnValue == null) {
// request的NotModified为true,有@ResponseStatus,RequestHandled为true,三个条件有一个成立,则设置请求处理完成并返回
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
disableContentCachingIfNecessary(webRequest);
mavContainer.setRequestHandled(true);
return;
}
}
// 返回值不为null,@ResponseStatus存在reason,这是请求处理完成并返回
else if (StringUtils.hasText(getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}

// 前面都不成立,则设置RequestHandled为false即请求完成??????????
mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
// 使用returnValueHandlers处理返回值
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
InvocableHandlerMethod#invokeForRequest

定位: org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest

执行方法

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
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {

// 准备方法所需要的参数
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
// 具体调用method
return doInvoke(args);
}
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {

// 获取方法的参数
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}

// 用于保存解析出参数的值
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
// 给parameter设置参数名解析器
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
// 如果相应类型的参数已经在providedArgs中提供了,则直接设置到parameter
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
// 使用argumentResolvers解析参数
if (!this.resolvers.supportsParameter(parameter)) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
try {
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;
}
protected Object doInvoke(Object... args) throws Exception {
//强制方法可调用
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
// 执行
return getBridgedMethod().invoke(getBean(), args);
}
catch (IllegalArgumentException ex) {
assertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
throw new IllegalStateException(formatInvokeError(text, args), ex);
}
catch (InvocationTargetException ex) {
// Unwrap for HandlerExceptionResolvers ...
Throwable targetException = ex.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException) targetException;
}
else if (targetException instanceof Error) {
throw (Error) targetException;
}
else if (targetException instanceof Exception) {
throw (Exception) targetException;
}
else {
throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
}
}
}
HandlerMethodReturnValueHandlerComposite#handleReturnValue

定位: org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite#handleReturnValue

处理返回值

1
2
3
4
5
6
7
8
9
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 根据返回值确定 Handler
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}