1、HandlerAdapter接口继承结构体系
2、HandlerAdapter接口功能
HandlerAdapter接口中定义了三个方法
public interface HandlerAdapter {
// 判断是否支持传入的handler
boolean supports(Object handler);
// 使用handler处理请求
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
// 获取资源的LastModified值
long getLastModified(HttpServletRequest request, Object handler);
}
3、HandlerAdapter家族成员
从HandlerAdapter接口继承结构体系图中,我们可以发现HandlerAdapter家族的继承结构比较简单,其中AnnotationMethodHandlerAdapter
已经被弃用,而SimpleControllerHandlerAdapter
、SimpleServletHandlerAdapter
、HttpRequestHandlerAdapter
分别适配Controller
、servlet
、HttpRequest
类型的Handler,方法非常简单,都是调用Handler里固定的方法。代码太过简单,就不过多介绍。剩下一个RequestMappingHandlerAdapter
就比较复杂了,可以说,该类是整个SpringMVC中最复杂的类了,却也是目前SpringMVC中使用到的频率最高的类。目前在SpringMVC的使用过程中,对请求的处理主要就是依赖RequestMappingHandlerMapping
和RequestMappingHandlerAdapter
类的配合使用。下面重点介绍下RequestMappingHandlerAdapter
类。
4、RequestMappingHandlerAdapter
4.1、RequestMappingHandlerAdapter概述
RequestMappingHandlerAdapter
继承自AbstractHandlerMethodAdapter
,后者非常简单,三个接口方法分别调用了三个模板方法,这是典型的模板模式。其中supportsInternal
与getLastModifiedInternal
模板方法在RequestMappingHandlerAdapter
中的实现非常简单,一个直接返回true,一个直接返回-1,这里就不过多讲解。最重要的是handleInternal
方法,就是这个方法实际使用Handler处理请求。具体处理过程大致有三步:
1.备好处理器需要的参数
2.使用处理器处理请求
3.处理返回值,也就是将不同类型的返回值统一处理成ModelAndView类型
(PS:如果标注了@RequestBody
注解,则在第三步处理返回值时,会直接操作response对象,输出结果,不会再返回ModelAndView对象)
4.2、RequestMappingHandlerAdapter初始化
RequestMappingHandlerAdapter
实现了InitializingBean
接口,Spring容器会自动调用其afterPropertiesSet
方法。
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBody advice beans
initControllerAdviceCache();
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
该方法主要是初始化RequestMappingHandlerAdapter
类中比较重要的6个属性:
-
modelAttributeAdviceCache
和initBinderAdviceCache
:分别缓存@ControllerAdvice
注解的类里面注释了@ModelAttribute
和@InitBinder
的方法,其中@ModelAttribute
很少使用,而@InitBinder
多用于注册校验器和类型转换器。 -
requestResponseBodyAdvice
:用来保存实现了RequestBodyAdvice
或ResponseBodyAdvice
接口的类,这些类可以修改接受RequestBody
和返回ResponseBody
的类。 -
argumentResolvers
:用于给处理器方法设置参数 -
initBinderArgumentResolvers
:用于给注释了@InitBinder
方法设置参数 -
returnValueHandlers
:用于对处理器返回值进行相应处理
4.3 RequestMappingHandlerAdapter的使用
RequestMappingHandlerAdapter
处理请求的入口方法是handleInternal
,方法中真正执行请求的是invokeHandlerMethod
方法,代码如下:
@Nullable
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);
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 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();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
方法中首先使用request
和response
创建了ServletWebRequest
类型的webRequest
,在argumentResolvers
解析参数时使用的request
就是这个webRequest
。接着对WebDataBinderFactory
、ModelFactory
、ServletInvocableHandlerMethod
三个类型的变量初始化。
-
WebDataBinderFactory
WebDataBinderFactory
的作用是用来创建WebDataBinder
的,后者用于参数绑定,主要功能就是实现参数跟String之间的类型转换(还包括参数校验),argumentResolvers
在进行参数解析的过程中会用到WebDataBinder
。 -
ModelFactory
ModelFactory
是用来处理Model的,主要包含两个功能:1. 在处理器具体处理之前对Model进行初始化;2.在处理完请求之后对Model参数进行更新。一般都是用户@ModelAttibute注解,目前基本不会用到。 -
ServletInvocableHandlerMethod
ServletInvocableHandlerMethod
类型非常重要,实际的处理就是通过他来执行的,参数绑定、处理请求、以及返回值处理都在他里面完成。