HandlerAdapter简介

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已经被弃用,而SimpleControllerHandlerAdapterSimpleServletHandlerAdapterHttpRequestHandlerAdapter分别适配ControllerservletHttpRequest类型的Handler,方法非常简单,都是调用Handler里固定的方法。代码太过简单,就不过多介绍。剩下一个RequestMappingHandlerAdapter就比较复杂了,可以说,该类是整个SpringMVC中最复杂的类了,却也是目前SpringMVC中使用到的频率最高的类。目前在SpringMVC的使用过程中,对请求的处理主要就是依赖RequestMappingHandlerMappingRequestMappingHandlerAdapter类的配合使用。下面重点介绍下RequestMappingHandlerAdapter类。

4、RequestMappingHandlerAdapter

4.1、RequestMappingHandlerAdapter概述

RequestMappingHandlerAdapter继承自AbstractHandlerMethodAdapter,后者非常简单,三个接口方法分别调用了三个模板方法,这是典型的模板模式。其中supportsInternalgetLastModifiedInternal模板方法在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 resolvers = getDefaultArgumentResolvers();
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.initBinderArgumentResolvers == null) {
        List resolvers = getDefaultInitBinderArgumentResolvers();
        this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.returnValueHandlers == null) {
        List handlers = getDefaultReturnValueHandlers();
        this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
    }
}

该方法主要是初始化RequestMappingHandlerAdapter类中比较重要的6个属性:

  • modelAttributeAdviceCacheinitBinderAdviceCache:分别缓存@ControllerAdvice注解的类里面注释了@ModelAttribute@InitBinder的方法,其中@ModelAttribute很少使用,而@InitBinder多用于注册校验器和类型转换器。
  • requestResponseBodyAdvice:用来保存实现了RequestBodyAdviceResponseBodyAdvice接口的类,这些类可以修改接受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();
    }
}

方法中首先使用requestresponse创建了ServletWebRequest类型的webRequest,在argumentResolvers解析参数时使用的request就是这个webRequest。接着对WebDataBinderFactoryModelFactoryServletInvocableHandlerMethod三个类型的变量初始化。

  • WebDataBinderFactory
    WebDataBinderFactory的作用是用来创建WebDataBinder的,后者用于参数绑定,主要功能就是实现参数跟String之间的类型转换(还包括参数校验),argumentResolvers在进行参数解析的过程中会用到WebDataBinder
  • ModelFactory
    ModelFactory是用来处理Model的,主要包含两个功能:1. 在处理器具体处理之前对Model进行初始化;2.在处理完请求之后对Model参数进行更新。一般都是用户@ModelAttibute注解,目前基本不会用到。
  • ServletInvocableHandlerMethod
    ServletInvocableHandlerMethod类型非常重要,实际的处理就是通过他来执行的,参数绑定、处理请求、以及返回值处理都在他里面完成。

你可能感兴趣的:(HandlerAdapter简介)