1、HandlerAdapter接口繼承結(jié)構(gòu)體系

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接口繼承結(jié)構(gòu)體系圖中,我們可以發(fā)現(xiàn)HandlerAdapter家族的繼承結(jié)構(gòu)比較簡單,其中AnnotationMethodHandlerAdapter已經(jīng)被棄用,而SimpleControllerHandlerAdapter、SimpleServletHandlerAdapter、HttpRequestHandlerAdapter分別適配Controller、servlet、HttpRequest類型的Handler,方法非常簡單,都是調(diào)用Handler里固定的方法。代碼太過簡單,就不過多介紹。剩下一個RequestMappingHandlerAdapter就比較復(fù)雜了,可以說,該類是整個SpringMVC中最復(fù)雜的類了,卻也是目前SpringMVC中使用到的頻率最高的類。目前在SpringMVC的使用過程中,對請求的處理主要就是依賴RequestMappingHandlerMapping和RequestMappingHandlerAdapter類的配合使用。下面重點介紹下RequestMappingHandlerAdapter類。
4、RequestMappingHandlerAdapter
4.1、RequestMappingHandlerAdapter概述
RequestMappingHandlerAdapter繼承自AbstractHandlerMethodAdapter,后者非常簡單,三個接口方法分別調(diào)用了三個模板方法,這是典型的模板模式。其中supportsInternal與getLastModifiedInternal模板方法在RequestMappingHandlerAdapter中的實現(xiàn)非常簡單,一個直接返回true,一個直接返回-1,這里就不過多講解。最重要的是handleInternal方法,就是這個方法實際使用Handler處理請求。具體處理過程大致有三步:
1.備好處理器需要的參數(shù)
2.使用處理器處理請求
3.處理返回值,也就是將不同類型的返回值統(tǒng)一處理成ModelAndView類型
(PS:如果標(biāo)注了@RequestBody注解,則在第三步處理返回值時,會直接操作response對象,輸出結(jié)果,不會再返回ModelAndView對象)
4.2、RequestMappingHandlerAdapter初始化
RequestMappingHandlerAdapter實現(xiàn)了InitializingBean接口,Spring容器會自動調(diào)用其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多用于注冊校驗器和類型轉(zhuǎn)換器。 -
requestResponseBodyAdvice:用來保存實現(xiàn)了RequestBodyAdvice或ResponseBodyAdvice接口的類,這些類可以修改接受RequestBody和返回ResponseBody的類。 -
argumentResolvers:用于給處理器方法設(shè)置參數(shù) -
initBinderArgumentResolvers:用于給注釋了@InitBinder方法設(shè)置參數(shù) -
returnValueHandlers:用于對處理器返回值進(jìn)行相應(yīng)處理
4.3 RequestMappingHandlerAdapter的使用
RequestMappingHandlerAdapter處理請求的入口方法是handleInternal,方法中真正執(zhí)行請求的是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創(chuàng)建了ServletWebRequest類型的webRequest,在argumentResolvers解析參數(shù)時使用的request就是這個webRequest。接著對WebDataBinderFactory、ModelFactory、ServletInvocableHandlerMethod三個類型的變量初始化。
-
WebDataBinderFactory
WebDataBinderFactory的作用是用來創(chuàng)建WebDataBinder的,后者用于參數(shù)綁定,主要功能就是實現(xiàn)參數(shù)跟String之間的類型轉(zhuǎn)換(還包括參數(shù)校驗),argumentResolvers在進(jìn)行參數(shù)解析的過程中會用到WebDataBinder。 -
ModelFactory
ModelFactory是用來處理Model的,主要包含兩個功能:1. 在處理器具體處理之前對Model進(jìn)行初始化;2.在處理完請求之后對Model參數(shù)進(jìn)行更新。一般都是用戶@ModelAttibute注解,目前基本不會用到。 -
ServletInvocableHandlerMethod
ServletInvocableHandlerMethod類型非常重要,實際的處理就是通過他來執(zhí)行的,參數(shù)綁定、處理請求、以及返回值處理都在他里面完成。