HandlerAdapter簡介

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

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接口繼承結(jié)構(gòu)體系圖中,我們可以發(fā)現(xiàn)HandlerAdapter家族的繼承結(jié)構(gòu)比較簡單,其中AnnotationMethodHandlerAdapter已經(jīng)被棄用,而SimpleControllerHandlerAdapter、SimpleServletHandlerAdapterHttpRequestHandlerAdapter分別適配Controller、servlet、HttpRequest類型的Handler,方法非常簡單,都是調(diào)用Handler里固定的方法。代碼太過簡單,就不過多介紹。剩下一個RequestMappingHandlerAdapter就比較復(fù)雜了,可以說,該類是整個SpringMVC中最復(fù)雜的類了,卻也是目前SpringMVC中使用到的頻率最高的類。目前在SpringMVC的使用過程中,對請求的處理主要就是依賴RequestMappingHandlerMappingRequestMappingHandlerAdapter類的配合使用。下面重點介紹下RequestMappingHandlerAdapter類。

4、RequestMappingHandlerAdapter

4.1、RequestMappingHandlerAdapter概述

RequestMappingHandlerAdapter繼承自AbstractHandlerMethodAdapter,后者非常簡單,三個接口方法分別調(diào)用了三個模板方法,這是典型的模板模式。其中supportsInternalgetLastModifiedInternal模板方法在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個屬性:

  • modelAttributeAdviceCacheinitBinderAdviceCache:分別緩存@ControllerAdvice注解的類里面注釋了@ModelAttribute@InitBinder的方法,其中@ModelAttribute很少使用,而@InitBinder多用于注冊校驗器和類型轉(zhuǎn)換器。
  • requestResponseBodyAdvice:用來保存實現(xiàn)了RequestBodyAdviceResponseBodyAdvice接口的類,這些類可以修改接受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();
    }
}

方法中首先使用requestresponse創(chuàng)建了ServletWebRequest類型的webRequest,在argumentResolvers解析參數(shù)時使用的request就是這個webRequest。接著對WebDataBinderFactory、ModelFactoryServletInvocableHandlerMethod三個類型的變量初始化。

  • 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ù)綁定、處理請求、以及返回值處理都在他里面完成。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容