Spring mvc 之 HandlerAdapter 源码解析

 2023-01-19
原文作者:从入门到入狱 原文地址:https://juejin.cn/post/7029596298768547847

HandlerAdapter 组件

HandlerAdapter 处理器的适配器,因为spring mvc中的处理器是多变的,我们可以通过实现Controller或者HttpRequestHandler接口,也可以通过@RequestMapping注解将方法作为一个处理器,这就导致spring mvc不能直接处理handler,所以这时候就需要一个适配器,让他去执行处理

HandlerAdapter组件之HandlerAdapter接口

    public interface HandlerAdapter {
        //判断当前适配器是否支持该处理器
        boolean supports(Object var1);
    
        //执行Handler
        @Nullable
        ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
    
        //返回请求最新的更新时间,如果不支持返回-1即可
        long getLastModified(HttpServletRequest var1, Object var2);
    }

HandlerAdapter接口总共只有三个方法,相对于来说还是很好理解

  • supports方法就是判断当前适配器是否支持该处理器,因为handler是多变的,所以处理器的类型是object类型的
  • handle方法就是去执行处理器
  • getLastModified方法是Http协议相关的,这边就不多做介绍了

HandlerAdapter 接口的体系结构如下:

202301012105160801.png

初始化过程

在DispatcherServlet.onRefresh()方法中初始化了HandlerAdapter组件

    private void initHandlerAdapters(ApplicationContext context) {
       this.handlerAdapters = null;
       //默认情况下是this.detectAllHandlerAdapters=true,
       //检测容器中所有的HandlerAdapter的bean,并对其进行排序
       if (this.detectAllHandlerAdapters=) {
          // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
          Map<String, HandlerAdapter的bean,并对其进行排序> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
          if (!matchingBeans.isEmpty()) {
             this.handlerAdapters = new ArrayList<>(matchingBeans.values());
             // We keep HandlerAdapters in sorted order.
             AnnotationAwareOrderComparator.sort(this.handlerAdapters);
          }
       }
       else {
         //this.detectAllHandlerAdapters=false的情况下,获取默认的名为handlerAdapter的bean
    
          try {
             HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
             this.handlerAdapters = Collections.singletonList(ha);
          }
          catch (NoSuchBeanDefinitionException ex) {
             // Ignore, we'll add a default HandlerAdapter later.
          }
       }
        
        //如果以上两种方式都没有获取到handlerAdapter的bean,则通过加载配置文件下的默认类
        // 默认文件是DispatcherServlet.properties,
        //org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
       org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
       org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
       org.springframework.web.servlet.function.support.HandlerFunctionAdapter
    
       // Ensure we have at least some HandlerAdapters, by registering
       // default HandlerAdapters if no other adapters are found.
       if (this.handlerAdapters == null) {
          this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
          if (logger.isTraceEnabled()) {
             logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
                   "': using default strategies from DispatcherServlet.properties");
          }
       }
    }

handlerAdapter的初始化只要分为以下几步

  • 首先判断是否需要检测关于HandlerAdapter的所有bean,true的情况下会去检测容器中的所有bean并对其进行排序,false的情况下会去获取名为handlerAdapter的bean
  • 如果以上两种方式都没有获取的handlerAdapter的bean,则去加载配置文件DispatcherServlet.properties中的 org.springframework.web.servlet.HandlerAdapter属性中所有的类

HttpRequestHandlerAdapter

    public class HttpRequestHandlerAdapter implements HandlerAdapter {
    
       //可以看出来supports的具体实现其实是很简单的,就是判断handler是否是HttpRequestHandler类型的
       @Override
       public boolean supports(Object handler) {
          return (handler instanceof HttpRequestHandler);
       }
    
    
        //调用handleRequest方法执行的handler
       @Override
       @Nullable
       public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
             throws Exception {
    
          ((HttpRequestHandler) handler).handleRequest(request, response);
          return null;
       }
    
       
       @Override
       public long getLastModified(HttpServletRequest request, Object handler) {
          if (handler instanceof LastModified) {
             return ((LastModified) handler).getLastModified(request);
          }
          return -1L;
       }
    
    }

SimpleContrllerHandlerAdapter

    public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    
       @Override
       public boolean supports(Object handler) {
          return (handler instanceof Controller);
       }
    
       @Override
       @Nullable
       public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
             throws Exception {
    
          return ((Controller) handler).handleRequest(request, response);
       }
    
       @Override
       public long getLastModified(HttpServletRequest request, Object handler) {
          if (handler instanceof LastModified) {
             return ((LastModified) handler).getLastModified(request);
          }
          return -1L;
       }
    
    }
  • SimpleControllerHandlerAdapter和HttpRequestHandlerAdapter的实现几乎是一样的,唯一的不同就是supports方法判断当前处理器是否是Controller类型的

AbstractHandlerMethodAdapter

AbstractHandlerMethodAdapter实现了HandlerAdapter和Ordered接口,继承了WebContentGenerator类

初始化

    //最低优先级
    private int order = Ordered.LOWEST_PRECEDENCE;
    
    //调用了WebContentGenerator的构造方法,当参数为false的时候,表示表示不需要严格效验HttpMethod
    
    public AbstractHandlerMethodAdapter() {
       // no restriction of HTTP methods by default
       super(false);
    }

supports方法

    //判断handler是否是HandlerMethod类型,调用supportsInternal方法
    @Override
    public final boolean supports方法,判断(Object handler) {
       return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
    }
    
    /**
     * Given a handler method, return whether or not this adapter can support it.
     * @param handlerMethod the handler method to check
     * @return whether or not this adapter can adapt the given method
     */
     
     //具体实现交于子类
    protected abstract boolean supportsInternal(HandlerMethod handlerMethod);
  • 实现supports方法,判断handler是否是HandlerMethod类型,调用supportsInternal方法,supportsInternal方法交于子类去实现,目前子类只有RequestMappingHandlerAdapter,其实现是直接返回true

handler方法

    @Override
    @Nullable
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
          throws Exception {
       //调用handleInternal方法
       return handleInternal(request, response, (HandlerMethod) handler);
    }
    
    /**
     * Use the given handler method to handle the request.
     * @param request current HTTP request
     * @param response current HTTP response
     * @param handlerMethod handler method to use. This object must have previously been passed to the
     * {@link #supportsInternal(HandlerMethod)} this interface, which must have returned {@code true}.
     * @return a ModelAndView object with the name of the view and the required model data,
     * or {@code null} if the request has been handled directly
     * @throws Exception in case of errors
     */
     //交于其子类去实现
    @Nullable
    protected abstract ModelAndView handleInternal(HttpServletRequest request,
          HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;
  • handler 调用handleInternal方法,handleInternal方法交于其子类去实现

getLastModified方法

    
    //调用的getLastModifiedInternal方法,getLastModifiedInternal方法交于其子类去实现
    @Override
    public final long getLastModified(HttpServletRequest request, Object handler) {
       return getLastModifiedInternal(request, (HandlerMethod) handler);
    }
    
    /**
     * Same contract as for {@link javax.servlet.http.HttpServlet#getLastModified(HttpServletRequest)}.
     * @param request current HTTP request
     * @param handlerMethod handler method to use
     * @return the lastModified value for the given handler
     */
    protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);
  • 调用的getLastModifiedInternal方法,getLastModifiedInternal方法交于其子类去实现

AbstractHandlerMethodAdapter实现了HandlerAdapter中的三个方法,每一个方法都是调用自定义方法,而自定义的方法都是交于其子类去实现

RequestMappingHandlerAdapter

构造方法

    @Nullable
    private List<HandlerMethodArgumentResolver> customArgumentResolvers;
    
    @Nullable
    private HandlerMethodArgumentResolverComposite argumentResolvers;
    
    @Nullable
    private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;
    
    @Nullable
    private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
    
    @Nullable
    private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
    
    @Nullable
    private List<ModelAndViewResolver> modelAndViewResolvers;
    
    private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
    
    private List<HttpMessageConverter<?>> messageConverters;
    
    private List<Object> requestResponseBodyAdvice = new ArrayList<>();
    
    @Nullable
    private WebBindingInitializer webBindingInitializer;
    
    private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync");
    
    @Nullable
    private Long asyncRequestTimeout;
    
    private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0];
    
    private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[0];
    
    private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
    
    private boolean ignoreDefaultModelOnRedirect = false;
    
    private int cacheSecondsForSessionAttributeHandlers = 0;
    
    private boolean synchronizeOnSession = false;
    
    private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
    
    private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
    
    @Nullable
    private ConfigurableBeanFactory beanFactory;
    
    //缓存
    private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64);
    private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64);
    private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>();
    private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64);
    private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>();
    
    //添加了消息转换器
    public RequestMappingHandlerAdapter() {
       this.messageConverters = new ArrayList<>(4);
       this.messageConverters.add(new ByteArrayHttpMessageConverter());
       this.messageConverters.add(new StringHttpMessageConverter());
       try {
          this.messageConverters.add(new SourceHttpMessageConverter<>());
       }
       catch (Error err) {
          // Ignore when no TransformerFactory implementation is available
       }
       this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
    }
    
    public AllEncompassingFormHttpMessageConverter() {
       try {
          addPartConverter(new SourceHttpMessageConverter<>());
       }
       catch (Error err) {
          // Ignore when no TransformerFactory implementation is available
       }
    
       if (jaxb2Present && !jackson2XmlPresent) {
          addPartConverter(new Jaxb2RootElementHttpMessageConverter());
       }
    
       if (jackson2Present) {
          addPartConverter(new MappingJackson2HttpMessageConverter());
       }
       else if (gsonPresent) {
          addPartConverter(new GsonHttpMessageConverter());
       }
       else if (jsonbPresent) {
          addPartConverter(new JsonbHttpMessageConverter());
       }
    
       if (jackson2XmlPresent) {
          addPartConverter(new MappingJackson2XmlHttpMessageConverter());
       }
    
       if (jackson2SmilePresent) {
          addPartConverter(new MappingJackson2SmileHttpMessageConverter());
       }
    }

以上有许多属性,这边只介绍几个简单的属性

  • HandlerMethodArgumentResolverComposite argumentResolvers : 参数解析组合对象

  • HandlerMethodReturnValueHandlerComposite returnValueHandlers : 返回参数处理器组合对象

  • List<HttpMessageConverter<?>> messageConverters : HTTP消息转换器集合

  • List requestResponseBodyAdvice :requestResponseBodyAdvice 对象集合 从以上代码可以看出构造方法中初始化了多种消息转换器

    afterPropertiesSet方法 RequestMappingHandler实现了InitializingBean接口,所以在bean初始化后一定会执行afterPropertiesSet方法

        @Override
        public void afterPropertiesSet() {
          
           // Do this first, it may add ResponseBody advice beans
           //初始化ControllerAdvice
           initControllerAdviceCache();
        
           //初始化argumentResolvers参数解析对象
           if (this.argumentResolvers == null) {
              List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
              this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
           }
           初始化initBinderArgumentResolver
           if (this.initBinderArgumentResolvers == null) {
              List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
              this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
           }
           //初始化returnValueHandler
           if (this.returnValueHandlers == null) {
              List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
              this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
           }
        }
 *  调用initControllerAdviceCache()初始化ControllerAdvice相关
 *  初始化argumentResolvers属性,调用getDefaultArgumentResolvers()获取到默认的参数解析对象数组
 *  初始化initBinderArgumentResolvers属性,调用getDefaultInitBinderArgumentResolvers()获取到HandlerMethodArgumentResolver对象数组
 *  初始化returnValueHandlers属性,调用getDefaultReturnValueHandlers获取到HandlerMethodReturnValueHandler(返回参数处理器集合)
 *  getDefaultArgumentResolvers()和getDefaultInitBinderArgumentResolvers()以及getDefaultReturnValueHandlers()方法都没有什么好说的,都是初始化一些默认的对象,然后封装成集合返回

**initControllerAdviceCache**
        private void initControllerAdviceCache() {
           if (getApplicationContext() == null) {
              return;
           }
        
           //获取到所有带有@ControllerAdvice注解的的bean,并进行排序
           List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
           AnnotationAwareOrderComparator.sort(adviceBeans);
        
           List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();
        
           //遍历到获取到的bean
           for (ControllerAdviceBean adviceBean : adviceBeans) {
              Class<?> beanType = adviceBean.getBeanType();
              if (beanType == null) {
                 throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
              }
              //扫描带有'@ModelAttribute'注解却没有带有@RequestMapping注解的bean的方法,添加到modelAttributeAdviceCache属性中
              //该方法用于处理执行方法前的Model
              Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
              if (!attrMethods.isEmpty()) {
                 this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
              }
              //扫描带有'@InitBinder'注解的方法,添加到initBinderAdviceCache属性中
              //该类方法用于方法执行前初始化数据绑定器
              Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
              if (!binderMethods.isEmpty()) {
                 this.initBinderAdviceCache.put(adviceBean, binderMethods);
              }
              //如果是RequestBodyAdvice的子类则添加到requestResponseBodyAdviceBeans中
              if (RequestBodyAdvice.class.isAssignableFrom(beanType)) {
                 requestResponseBodyAdviceBeans.add(adviceBean);
              }
              //如果是ResponseBodyAdvice的子类则添加到requestResponseBodyAdviceBeans中
              if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
                 requestResponseBodyAdviceBeans.add(adviceBean);
              }
           }
        
           //如果requestResponseBodyAdviceBeans不为空则全部添加到requestResponseBodyAdvice中
           if (!requestResponseBodyAdviceBeans.isEmpty()) {
              this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
           }
        
           //日志打印不多做介绍
           if (logger.isDebugEnabled()) {
              int modelSize = this.modelAttributeAdviceCache.size();
              int binderSize = this.initBinderAdviceCache.size();
              int reqCount = getBodyAdviceCount(RequestBodyAdvice.class);
              int resCount = getBodyAdviceCount(ResponseBodyAdvice.class);
              if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) {
                 logger.debug("ControllerAdvice beans: none");
              }
              else {
                 logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize +
                       " @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice");
              }
           }
        }
 *  initControllerAdviceCache()方法中首先会去扫描带有@ControllerAdvice注解的bean,封装成一个ControllerAdviceBean类型的集合
 *  遍历所有的ControllerAdviceBean对象,将带有'@ModelAttribute'注解却没有带有@RequestMapping注解的bean的方法,添加到modelAttributeAdviceCache属性中
 *  遍历所有带有'@InitBinder'注解的方法,添加到initBinderAdviceCache属性中
 *  判断ControllerAdviceBean是否是RequestBodyAdvice子类或者ResponseBodyAdvice子类,将其添加到requestResponseBodyAdviceBeans中,最后在将requestResponseBodyAdviceBeans中对象全部添加的requestResponseBodyAdvice中

**supportsInternal方法** supportsInternal方法中直接返回的true,这个就没有什么好说的了
        @Override
        protected boolean supportsInternal(HandlerMethod handlerMethod) {
           return true;
        }
**getLastModifiedInternal方法** getLastModifiedInternal方法中直接返回的-1,这个也没有什么好说的
        @Override
        protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {
           return -1;
        }
**handleInternal**
        @Override
        protected ModelAndView handleInternal(HttpServletRequest request,
              HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        
           ModelAndView mav;
              // <1> 校验请求(HttpMethod 和 Session 的校验)
           checkRequest(request);
        
           // Execute invokeHandlerMethod in synchronized block if required.
           // 同步相同 Session 的逻辑,默认情况false
           if (this.synchronizeOnSession) {
              HttpSession session = request.getSession(false);
              if (session != null) {
              // 获取Session的锁对象
                 Object mutex = WebUtils.getSessionMutex(session);
                 synchronized (mutex) {
                    mav = invokeHandlerMethod(request, response, handlerMethod);
                 }
              }
              else {
                 // No HttpSession available -> no mutex necessary
                 mav = invokeHandlerMethod(request, response, handlerMethod);
              }
           }
           else {
              // No synchronization on session demanded at all...
              mav = invokeHandlerMethod(request, response, handlerMethod);
           }
        
           if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
              if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
                 applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
              }
              else {
                 prepareResponse(response);
              }
           }
        
           return mav;
        }