1、HandlerAdapter接口继承结构体系
image.png
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类型非常重要,实际的处理就是通过他来执行的,参数绑定、处理请求、以及返回值处理都在他里面完成。












网友评论