前面已经研究过spring mvc的简单流程:
- 根据
request
,从RequestMapping
中获取handler
- 使用
HandlerAdapter
执行handler
- 使用执行结果,渲染视图
我们要研究的RequestMapping
是RequestMappingHandlerMapping
,HandlerAdapter
是RequestMappingHandlerAdapter
.
RequestMappingHandlerMapping获取handler
###初始化RequestMappingHandlerMapping
RequestMappingHandlerMapping
实现了InitializingBean
接口,当其被实例化完成,参数注入完成之后会调用afterPropertiesSet
方法.
这个方法会遍历ApplicationContext
中的所有BeanDefinition
,找到所有的handler
.那么什么样的类才算是handler
呢?看下面代码:
protected boolean isHandler(Class<?> beanType) {
return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
}
类头上顶着@Controller
或者@RequestMapping
的才算handler
.
找到handler
以后,会遍历寻找其下属的HandlerMethod
.问题又来了,怎样的方法才算是HandlerMethod
呢?看下面代码:
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = null;
RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
if (methodAnnotation != null) {
RequestCondition<?> methodCondition = getCustomMethodCondition(method);
info = createRequestMappingInfo(methodAnnotation, methodCondition);
RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
if (typeAnnotation != null) {
RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
}
}
return info;
}
如果方法签名上有@RequestMapping
,则根据注解信息创建RequestMappingInfo
,接着判断所属类的类签名是否有@RequestMapping
,有的话,将类签名中包含的mapping
信息合并到刚才的RequestMappingInfo
中,然后返回.
通过该方法后返回结果RequestMappingInfo
不为null
的,就是可用的HandlerMethod
.然后就是把Method
转成HandlerMethod
,此处只需要简单封装一下就OK了.接着通过RequestMappingInfo
分析出对应的URL模式
(该模式使用的是类Ant
的匹配语法).最后将URL
与RequestMappingInfo
的对应关系,RequestMappingInfo
与HandlerMethod
的对应关系放入两个Map
中(其中URL的Map
是一个MultiValueMap
),留待后面使用.
###请求(Request)到来
当Request
到来的时候,先从Request
中解析出请求的地址URL.然后根据地址去urlMap
中查找,如果没找到的话,就遍历handlerMethods
中所有的RequestMappingInfo,进行匹配.如果找到则返回对应的RequestMethod.如果找不到则执行handleNoMatch
方法,这个方法会针对找不到的原因进行分析,必要的话抛出一大堆的异常来提醒开发者.
找到HandlerMethod
之后,将其封装为HandlerExecutionChain
,封装过程就是new HandlerExecutionChain(handler)
,然后把符合本次请求Url模式的HandlerInterceptor
添加到HandlerExecutionChain
里面,最后返回.
对于HandlerExecutionChain
,这是DispatcherServlet
要用到的,我们真正需要的还是HandlerMethod
. 对于HandlerMethod
的具体执行请看下面,因为spring mvc中对HandlerMethod
的调用不是在HandlerMapping
中进行的,而是通过HandlerAdapter
进行的.
RequestMappingHandlerAdapter执行handler
###初始化RequestMappingHandlerAdapter
首先在构造其中对messageConverters
做了初始化:
this.messageConverters = new ArrayList<HttpMessageConverter<?>>();
this.messageConverters.add(new ByteArrayHttpMessageConverter());
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316
this.messageConverters.add(stringHttpMessageConverter);
this.messageConverters.add(new SourceHttpMessageConverter<Source>());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
这个类也实现了InitializingBean
,同样有afterPropertiesSet
方法,该方法做的工作如下:
- 初始化
argumentResolvers
默认加载的HandlerMethodArgumentResolver
如下:
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
其中包括了自定义的ArgumentResolver
.
- 初始化
initBinderArgumentResolvers
默认加载的HandlerMethodArgumentResolver
如下:
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
其中包含了自定义的内容.注意这里的自定义跟argumentResolvers
的是同一个方法.
- 初始化
returnValueHandlers
默认加载HandlerMethodReturnValueHandler
如下:
// Single-purpose return value types
handlers.add(new ModelAndViewMethodReturnValueHandler());
handlers.add(new ModelMethodProcessor());
handlers.add(new ViewMethodReturnValueHandler());
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
handlers.add(new HttpHeadersReturnValueHandler());
handlers.add(new CallableMethodReturnValueHandler());
handlers.add(new DeferredResultMethodReturnValueHandler());
handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
// Annotation-based return value types
handlers.add(new ModelAttributeMethodProcessor(false));
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
// Multi-purpose return value types
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());
// Custom return value types
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
// Catch-all
if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
}
else {
handlers.add(new ModelAttributeMethodProcessor(true));
}
其中包含了自定义的内容.
###执行handler
RequestMappingHandlerAdapter
是HandlerAdapter
的子类.HandlerAdapter
接口的内容如下:
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler);
}
本文我们要关注的主要是supports
和handle
两个方法.support
是用来判断一个handler
是否能被该adapter
处理的.handle
方法是用来实际处理handler
的.
RequestMappingHandlerAdapter
的support
方法代码如下:
public final boolean supports(Object handler) {
return handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler);
}
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
这个没什么好解释的,只要handler
是HandlerMethod
的实例,RequestMappingHandlerAdapter
都会接受.
RequestMappingHandlerAdapter
的handle
方法就没这么简单了.梳理后的执行逻辑如下:
- 构建
WebDataBinderFactory
对象binderFactory
.根据HandlerMethod
,binderFactory
,argumentResolvers
,returnValueHandlers
构建ServletInvocableHandlerMethod
的对象requestMappingMethod
- 构建
ModelAndViewContainer
的对象mavContainer
,并进行一些特殊的设置. - 调用方法
requestMappingMethod.invokeAndHandle(webRequest, mavContainer)
.
这个方法调,我们所关心的主要有三块:
-
InvocableHandlerMethod#getMethodArgumentValues
,该方法作用是:为被调用的方法准备参数,比如Model
,各种Request
以及@RequestParam
,@RequestEntity
等各种注解. 这些参数是使用从RequestMappingHandlerMapping
中传过来的argumentResolvers
进行处理的(原理就是遍历其中所有的HandlerMethodArgumentResolver
,谁支持谁上). -
InvocableHandlerMethod#invoke
,该方法就是通过反射进行方法调用,并返回结果. (此处涉及到了Java中的Bridge Method
的概念java bridge method) - 最后调用
this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest)
.
其中的this.returnValueHandlers
是从RequestMappingHandlerMapping
传递过来的.
这个方法的作用是对HandlerMethod
的执行结果进行深加工.比如说把返回值放到Session或者Request中,再比如说处理@ResponseBody
把json
写入Response
等等.
- 根据上述过程参数及执行结果构建
ModelAndView
,并将其作为RequestMappingHandlerAdapter#invokeHandleMethod
的结果返回.
后续:DispatcherServlet
的processDispatchResult
方法,进行视图的渲染及一些异常处理.接着是清理使用痕迹,还原现场之类的操作.