Spring mvc 之 HandlerAdapter 源码解析

676 阅读4分钟

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 接口的体系结构如下:

image.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;
    }