跳至主要內容

11.HandlerAdapter 组件(一)之 HandlerAdapter

Java突击队大约 18 分钟

11.HandlerAdapter 组件(一)之 HandlerAdapter

Spring 版本:5.1.14.RELEASE

该系列其他文档请查看:《死磕 Spring MVC 源码分析 - 文章导读》open in new window

HandlerAdapter 组件

HandlerAdapter 组件,处理器的适配器。因为处理器 handler 的类型是 Object 类型,需要有一个调用者来实现 handler 是怎么被执行。Spring 中的处理器的实现多变,比如用户的处理器可以实现 Controller 接口或者 HttpRequestHandler 接口,也可以用 @RequestMapping 注解将方法作为一个处理器等,这就导致 Spring MVC 无法直接执行这个处理器。所以这里需要一个处理器适配器,由它去执行处理器

由于HandlerMapping 组件涉及到的内容较多,考虑到内容的排版,所以将这部分内容拆分成了五个模块,依次进行分析:

HandlerAdapter 组件(一)之 HandlerAdapter

先来回顾一下在 DispatcherServlet 中处理请求的过程中哪里使用到 HandlerMapping 组件,可以回到《一个请求的旅行过程》open in new window中的 DispatcherServletdoDispatch 方法中看看,如下:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
   HttpServletRequest processedRequest = request;
   HandlerExecutionChain mappedHandler = null;
   ModelAndView mv = null;
   // ... 省略相关代码
   // <3> 获得请求对应的 HandlerExecutionChain 对象(HandlerMethod 和 HandlerInterceptor 拦截器们)
   mappedHandler = getHandler(processedRequest);
   // ... 省略相关代码
   // <4> 获得当前 handler 对应的 HandlerAdapter 对象
   HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
   // ... 省略相关代码
   // <6> 真正的调用 handler 方法,也就是执行对应的方法,并返回视图
   mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
   // ... 省略相关代码
}
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
   if (this.handlerAdapters != null) {
       for (HandlerAdapter adapter : this.handlerAdapters) {
           if (adapter.supports(handler)) {
               return adapter;
           }
       }
   }
   throw new ServletException("No adapter for handler [...");
}

通过遍历 HandlerAdapter 组件们,判断是否支持处理该 handler 处理器,支持则返回该 HandlerAdapter 组件。注意,这里是通过一个一个的 HandlerAdapter 组件去判断是否支持该处理器,如果支持则直接返回这个 HandlerAdapter 组件,不会继续下去,所以获取处理器对应 HandlerAdapter 组件是有一定的先后顺序的,默认是HttpRequestHandlerAdapter -> SimpleControllerHandlerAdapter -> RequestMappingHandlerAdapter

本文涉及到的内容适中,可以先查看我的总结

HandlerAdapter 接口

org.springframework.web.servlet.HandlerAdapter接口,处理器的适配器,去执行处理器,代码如下:

public interface HandlerAdapter {
	/**
	 * 是否支持该处理器
	 */
	boolean supports(Object handler);

	/**
	 * 执行处理器,返回 ModelAndView 结果
	 */
	@Nullable
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

	/**
	 * 返回请求的最新更新时间,如果不支持该操作,则返回 -1 即可
	 */
	long getLastModified(HttpServletRequest request, Object handler);
}

HandlerAdapter 接口的体系结构如下:

 

没有特别多😈 心里有点点欣慰,其中 RequestMappingHandlerAdapter 就是基于@RequestMapping 等注解的 HandlerMethod 的 HandlerMethodAdapter 实现类,名字都差不多

初始化过程

DispatcherServletinitHandlerAdapters(ApplicationContext context) 方法,会在 onRefresh 方法被调用,初始化 HandlerAdapter 组件,方法如下:

private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;

    if (this.detectAllHandlerAdapters) {
        // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
        Map<String, HandlerAdapter> 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 {
        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.
        }
    }

    // Ensure we have at least some HandlerAdapters, by registering
    // default HandlerAdapters if no other adapters are found.
    /**
     * 如果未获得到,则获得默认配置的 HandlerAdapter 类
     * {@link org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter}
     * {@link org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter}
     * {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter}
     */
    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");
        }
    }
}

1、 如果“开启”探测功能,则扫描已注册的HandlerAdapter的Bean们,添加到handlerAdapters中,默认开启,这里会进行排序,可以通过实现Order接口设置排序值;
2、 如果“关闭”探测功能,则获得Bean名称为"handlerAdapter"对应的Bean,将其添加至handlerAdapters
3、 如果未获得到,则获得默认配置的HandlerAdapter类,调用getDefaultStrategies(ApplicationContextcontext,Class<T>strategyInterface)方法,就是从DispatcherServlet.properties文件中读取HandlerAdapter的默认实现类,如下:;

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

可以看到对应的是 HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter 三个实现类,接下来就一个一个分析

HttpRequestHandlerAdapter

org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,实现 HandlerAdapter 接口,基于 HttpRequestHandler 接口的 HandlerAdapter 实现类,代码如下:

public class HttpRequestHandlerAdapter implements HandlerAdapter {
	@Override
	public boolean supports(Object handler) {
		// 判断是 HttpRequestHandler 类型
		return (handler instanceof HttpRequestHandler);
	}
    
	@Override
	@Nullable
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// HttpRequestHandler 类型的调用
		((HttpRequestHandler) handler).handleRequest(request, response);
		return null;
	}
    
	@Override
	public long getLastModified(HttpServletRequest request, Object handler) {
		// 处理器实现了 LastModified 接口的情况下
		if (handler instanceof LastModified) {
			return ((LastModified) handler).getLastModified(request);
		}
		return -1L;
	}
}

//  org.springframework.web.HttpRequestHandler.java
@FunctionalInterface
public interface HttpRequestHandler {
	/**
	 * 处理请求
	 */
	void handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException;
}

逻辑比较简单,如果这个处理器实现了 HttpRequestHandler 接口,则使用 HttpRequestHandlerAdapter 调用该处理器的 handleRequest(HttpServletRequest request, HttpServletResponse response)方法去处理器请求,返回 null

这种处理器如何配置呢?

可以回到《HandlerMapping 组件(四)之 AbstractUrlHandlerMapping》open in new windowSimpleUrlHandlerMapping 或者 BeanNameUrlHandlerMapping 小节中的使用示例看看

SimpleControllerHandlerAdapter

org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,实现 HandlerAdapter 接口,基于 Controller 接口的 HandlerAdapter 实现类,代码如下:

public class SimpleControllerHandlerAdapter implements HandlerAdapter {
	@Override
	public boolean supports(Object handler) {
		// <1> 判断是 Controller 类型
		return (handler instanceof Controller);
	}

	@Override
	@Nullable
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// <2> Controller 类型的调用
		return ((Controller) handler).handleRequest(request, response);
	}

	@Override
	public long getLastModified(HttpServletRequest request, Object handler) {
		// 处理器实现了 LastModified 接口的情况下
		if (handler instanceof LastModified) {
			return ((LastModified) handler).getLastModified(request);
		}
		return -1L;
	}
}

@FunctionalInterface
public interface Controller {
	/**
	 * 处理请求
	 */
	@Nullable
	ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}

逻辑比较简单,和 HttpRequestHandlerAdapter 差不多,如果这个处理器实现了 Controoler 接口,则使用 HttpRequestHandlerAdapter 调用该处理器的 handleRequest(HttpServletRequest request, HttpServletResponse response)方法去处理器请求,直接返回处理器执行后返回 ModelAndView

这种处理器如何配置和 HttpRequestHandlerAdapter 相同,见上文描述

SimpleServletHandlerAdapter 实现类就不讲述了,因为默认的 HandlerAdapter 实现类中没有它

逻辑实现和 SimpleControllerHandlerAdapter 差不多,区别在于它判断是否为 javax.servlet.Servlet 对象,是的话则调用其 service方法,返回该方法执行后返回的 ModelAndView 对象

AbstractHandlerMethodAdapter

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter,实现 HandlerAdapter、Ordered 接口,继承 WebContentGenerator 抽象类,基于 HandlerMethod 的 HandlerMethodAdapter 抽象类

构造方法

public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
    /** 最低优先级 */
	private int order = Ordered.LOWEST_PRECEDENCE;

	public AbstractHandlerMethodAdapter() {
		// no restriction of HTTP methods by default
		// 调用 WebContentGenerator 类的构造方法
	    // 参数 restrictDefaultSupportedMethods 参数为 false ,表示不需要严格校验 HttpMethod
		super(false);
	}
}

supports方法

实现supports(Object handler) 方法,判断是否支持该处理器,代码如下:

@Override
public final boolean supports(Object handler) {
    return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

protected abstract boolean supportsInternal(HandlerMethod handlerMethod);

handle方法

实现handle(HttpServletRequest request, HttpServletResponse response, Object handler) 方法,用于处理请求,执行该处理器,代码如下:

@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    return handleInternal(request, response, (HandlerMethod) handler);
}

@Nullable
protected abstract ModelAndView handleInternal(HttpServletRequest request,
        HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;

  • 如果该 HandlerAdapter 支持这个处理器,那么则会调用该方法去处理请求,执行这个处理器
  • 直接调用 handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) 抽象方法,交由子类去实现,详情见下文

getLastModified方法

实现getLastModified(HttpServletRequest request, Object handler) 方法,获得最后更新时间,代码如下

@Override
public final long getLastModified(HttpServletRequest request, Object handler) {
    return getLastModifiedInternal(request, (HandlerMethod) handler);
}

protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);

  • 直接调用getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod)抽象方法,交由子类去实现,详情见下文

RequestMappingHandlerAdapter

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,实现 BeanFactoryAware、InitializingBean 接口,继承 AbstractHandlerMethodAdapter 抽象类,基于 @RequestMapping 注解的 HandlerMethod 处理器的 HandlerMethodAdapter 实现类

构造方法

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
		implements BeanFactoryAware, InitializingBean {

	/**
	 * MethodFilter that matches {@link InitBinder @InitBinder} methods.
	 */
	public static final MethodFilter INIT_BINDER_METHODS = method ->
			AnnotatedElementUtils.hasAnnotation(method, InitBinder.class);
	/**
	 * MethodFilter that matches {@link ModelAttribute @ModelAttribute} methods.
	 */
	public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method ->
			(!AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class) &&
					AnnotatedElementUtils.hasAnnotation(method, ModelAttribute.class));

	@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;

	/**
	 * 是否对相同 Session 加锁
	 */
	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<>();
    
    // ... 省略 getter、setter 方法
	public RequestMappingHandlerAdapter() {
		// 初始化 messageConverters
		StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
		stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316

		this.messageConverters = new ArrayList<>(4);
		this.messageConverters.add(new ByteArrayHttpMessageConverter());
		this.messageConverters.add(stringHttpMessageConverter);
		try {
			this.messageConverters.add(new SourceHttpMessageConverter<>());
		}
		catch (Error err) {
			// Ignore when no TransformerFactory implementation is available
		}
		this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
	}
}

有许多的属性,不着急理解,先列几个主要的属性对象:

  • HandlerMethodArgumentResolverComposite argumentResolvers:参数处理器组合对象
  • HandlerMethodReturnValueHandlerComposite returnValueHandlers:返回值处理器组合对象
  • List<HttpMessageConverter<?>>` messageConverters:HTTP 消息转换器集合对象
  • List<Object> requestResponseBodyAdvice: RequestResponseAdvice 集合对象

在构造方法中默认会添加了四个 HttpMessageConverter 对象,当然,默认还会添加其他的,例如 MappingJackson2HttpMessageConverter 为 JSON 消息格式的转换器

1.afterPropertiesSet 初始化方法

因为RequestMappingHandlerAdapter 实现了 InitializingBean 接口,在 Sping 初始化该 Bean 的时候,会调用该方法,完成一些初始化工作,方法如下:

@Override
public void afterPropertiesSet() {
    // Do this first, it may add ResponseBody advice beans
    // <1> 初始化 ControllerAdvice 相关
    initControllerAdviceCache();

    // <2> 初始化 argumentResolvers 属性
    if (this.argumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    // <3> 初始化 initBinderArgumentResolvers 属性
    if (this.initBinderArgumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
        this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    // <4> 初始化 returnValueHandlers 属性
    if (this.returnValueHandlers == null) {
        List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
        this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
    }
}

1、 调用initControllerAdviceCache()方法,初始化ControllerAdvice相关,详情见下文;
2、 初始化argumentResolvers属性,调用getDefaultArgumentResolvers()方法,获得默认的HandlerMethodArgumentResolver数组,详情见下文;
3、 初始化initBinderArgumentResolvers属性,调用getDefaultInitBinderArgumentResolvers()方法,获得默认的HandlerMethodArgumentResolver数组,详情见下文;
4、 初始化returnValueHandlers属性,调用getDefaultReturnValueHandlers()方法,获得默认的HandlerMethodReturnValueHandler数组,详情见下文;

1.1 initControllerAdviceCache

initControllerAdviceCache() 方法,初始化 ControllerAdvice 相关,方法如下:

private void initControllerAdviceCache() {
    if (getApplicationContext() == null) {
        return;
    }

    // <1> 扫描 @ControllerAdvice 注解的 Bean 们,生成对应的 ControllerAdviceBean 对象,并将进行排序
    List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
    AnnotationAwareOrderComparator.sort(adviceBeans);

    List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();

    // <2> 遍历 ControllerAdviceBean 数组
    for (ControllerAdviceBean adviceBean : adviceBeans) {
        Class<?> beanType = adviceBean.getBeanType();
        if (beanType == null) {
            throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
        }
        // `<2.1>` 扫描有 @ModelAttribute ,无 @RequestMapping 注解的方法,添加到 modelAttributeAdviceCache 属性中
		// 该类方法用于在执行方法前修改 Model 对象
        Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
        if (!attrMethods.isEmpty()) {
            this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
        }
        // `<2.2>` 扫描有 @InitBinder 注解的方法,添加到 initBinderAdviceCache 属性中
		// 该类方法用于在执行方法前初始化数据绑定器
        Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
        if (!binderMethods.isEmpty()) {
            this.initBinderAdviceCache.put(adviceBean, binderMethods);
        }
        // <2.3> 如果是 RequestBodyAdvice 或 ResponseBodyAdvice 的子类,添加到 requestResponseBodyAdviceBeans 中
        if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
            requestResponseBodyAdviceBeans.add(adviceBean);
        }
    }

    // <2.3> 将 requestResponseBodyAdviceBeans 添加到 this.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");
        }
    }
}

1、 从Spring上下文扫描@ControllerAdvice注解的Bean们,生成对应的ControllerAdviceBean对象,并将进行排序,方法如下:;

public static List<ControllerAdviceBean> findAnnotatedBeans(ApplicationContext context) {
    return Arrays.stream(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, Object.class))
            // 排除代理目标类,AOP 相关
            .filter(name -> !ScopedProxyUtils.isScopedTarget(name))
            // 包含 @ControllerAdvice 注解
            .filter(name -> context.findAnnotationOnBean(name, ControllerAdvice.class) != null)
            // 生成对应的 ControllerAdviceBean 对象
            .map(name -> new ControllerAdviceBean(name, context))
            .collect(Collectors.toList());
}

@ControllerAdvice 注解:用于 Controller 类的增强类,其中可定义多种增强的方法,例如 @ExceptionHandler 注解的方法用于处理器 Controller 抛出的异常
2、 遍历1中生成ControllerAdviceBean数组;

1、 扫描@ModelAttribute@RequestMapping注解的方法,添加到modelAttributeAdviceCache属性中,该类方法用于在执行方法前修改Model对象;
2、 扫描@InitBinder注解的方法,添加到initBinderAdviceCache属性中,该类方法用于在执行方法前初始化数据绑定器;
3、 如果是RequestBodyAdvice或ResponseBodyAdvice的子类,保存至requestResponseBodyAdviceBeans临时变量中;
3、2.3的requestResponseBodyAdviceBeans保存至requestResponseBodyAdvice属性中;

1.2 getDefaultArgumentResolvers

getDefaultArgumentResolvers(),初始化默认的参数解析器,方法如下:

private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
    List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();

    // Annotation-based argument resolution
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
    resolvers.add(new RequestParamMapMethodArgumentResolver());
    resolvers.add(new PathVariableMethodArgumentResolver());
    resolvers.add(new PathVariableMapMethodArgumentResolver());
    resolvers.add(new MatrixVariableMethodArgumentResolver());
    resolvers.add(new MatrixVariableMapMethodArgumentResolver());
    resolvers.add(new ServletModelAttributeMethodProcessor(false));
    resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new RequestHeaderMapMethodArgumentResolver());
    resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new SessionAttributeMethodArgumentResolver());
    resolvers.add(new RequestAttributeMethodArgumentResolver());

    // Type-based argument resolution
    resolvers.add(new ServletRequestMethodArgumentResolver());
    resolvers.add(new ServletResponseMethodArgumentResolver());
    resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RedirectAttributesMethodArgumentResolver());
    resolvers.add(new ModelMethodProcessor());
    resolvers.add(new MapMethodProcessor());
    resolvers.add(new ErrorsMethodArgumentResolver());
    resolvers.add(new SessionStatusMethodArgumentResolver());
    resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

    // Custom arguments
    if (getCustomArgumentResolvers() != null) {
        resolvers.addAll(getCustomArgumentResolvers());
    }

    // Catch-all
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
    resolvers.add(new ServletModelAttributeMethodProcessor(true));

    return resolvers;
}

  • 按顺序添加了非常多的参数解析器对象

1.3 getDefaultInitBinderArgumentResolvers

getDefaultInitBinderArgumentResolvers(),初始化默认的参数绑定器,方法如下:

private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {
    List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();

    // Annotation-based argument resolution
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
    resolvers.add(new RequestParamMapMethodArgumentResolver());
    resolvers.add(new PathVariableMethodArgumentResolver());
    resolvers.add(new PathVariableMapMethodArgumentResolver());
    resolvers.add(new MatrixVariableMethodArgumentResolver());
    resolvers.add(new MatrixVariableMapMethodArgumentResolver());
    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new SessionAttributeMethodArgumentResolver());
    resolvers.add(new RequestAttributeMethodArgumentResolver());

    // Type-based argument resolution
    resolvers.add(new ServletRequestMethodArgumentResolver());
    resolvers.add(new ServletResponseMethodArgumentResolver());

    // Custom arguments
    if (getCustomArgumentResolvers() != null) {
        resolvers.addAll(getCustomArgumentResolvers());
    }

    // Catch-all
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));

    return resolvers;
}

1.4 getDefaultReturnValueHandlers

getDefaultReturnValueHandlers(),初始化默认的返回值处理器,方法如下:

private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();

    // Single-purpose return value types
    handlers.add(new ModelAndViewMethodReturnValueHandler());
    handlers.add(new ModelMethodProcessor());
    handlers.add(new ViewMethodReturnValueHandler());
    handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
            this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
    handlers.add(new StreamingResponseBodyReturnValueHandler());
    handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
            this.contentNegotiationManager, this.requestResponseBodyAdvice));
    handlers.add(new HttpHeadersReturnValueHandler());
    handlers.add(new CallableMethodReturnValueHandler());
    handlers.add(new DeferredResultMethodReturnValueHandler());
    handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));

    // Annotation-based return value types
    handlers.add(new ModelAttributeMethodProcessor(false));
    handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
            this.contentNegotiationManager, this.requestResponseBodyAdvice));

    // Multi-purpose return value types
    handlers.add(new ViewNameMethodReturnValueHandler());
    handlers.add(new MapMethodProcessor());

    // Custom return value types
    if (getCustomReturnValueHandlers() != null) {
        handlers.addAll(getCustomReturnValueHandlers());
    }

    // Catch-all
    if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
        handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
    }
    else {
        handlers.add(new ModelAttributeMethodProcessor(true));
    }

    return handlers;
}

  • 按顺序添加了非常多的返回值处理器对象

supportsInternal 方法

实现supportsInternal() 接口,方法如下:

@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
    return true;
}

直接返回 true,也就是说处理器只要是 HandlerMethod 对象就可以

getLastModifiedInternal 方法

@Override
protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {
    return -1;
}

直接返回 -1

handleInternal 方法

实现handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) 方法,处理请求,执行处理器,方法如下:

@Override
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, 
                                      HandlerMethod handlerMethod) throws Exception {
    ModelAndView mav;
    // <1> 校验请求(HttpMethod 和 Session 的校验)
    checkRequest(request);
    // <2> 调用 HandlerMethod 方法
    // Execute invokeHandlerMethod in synchronized block if required.
    if (this.synchronizeOnSession) { // 同步相同 Session 的逻辑,默认情况false
        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)) { // 响应不包含'Cache-Control'头
        if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
            applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
        }
        else {
            prepareResponse(response);
        }
    }
    return mav;
}

1、 调用父类WebContentGenerator的checkRequest(ttpServletRequestrequest)方法,校验请求(HttpMethod和Session)是否合法;

protected final void checkRequest(HttpServletRequest request) throws ServletException {
    // Check whether we should support the request method.
    String method = request.getMethod();
    if (this.supportedMethods != null && !this.supportedMethods.contains(method)) {
        throw new HttpRequestMethodNotSupportedException(method, this.supportedMethods);
    }
    // Check whether a session is required.
    if (this.requireSession && request.getSession(false) == null) {
        throw new HttpSessionRequiredException("Pre-existing session required but none found");
    }
}

在 AbstractHandlerMethodAdapter 的构造方法中,传入 restrictDefaultSupportedMethods 参数为 false,表示不需要严格校验 HttpMethod,这里正常情况都会校验通过
2、 调用invokeHandlerMethod(HttpServletRequestrequest,HttpServletResponseresponse,HandlerMethodhandlerMethod)方法,执行HandlerMethod处理器;

这里会判断 synchronizeOnSession 属性,控制是否**同步相同 Session** 的逻辑,其中 WebUtils#getSessionMutex(session) 方法,获得用来锁的对象,方法如下:
public static Object getSessionMutex(HttpSession session) {
    Assert.notNull(session, "Session must not be null");
    Object mutex = session.getAttribute(SESSION_MUTEX_ATTRIBUTE);
    if (mutex == null) {
        mutex = session;
    }
    return mutex;
}

当然,因为锁是通过 synchronized 是 JVM 进程级,所以在分布式环境下,无法达到同步相同 Session 的功能

默认情况下,synchronizeOnSessionfalse

【重点】invokeHandlerMethod方法

invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) 方法,执行 HandlerMethod 处理器,方法如下:

@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, 
                                           HandlerMethod handlerMethod) throws Exception {
    // <1> 创建 ServletWebRequest 对象
    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    try {
        // <2> 创建 WebDataBinderFactory 对象
        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        // <3> 创建 ModelFactory 对象
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

        // <4> 创建 ServletInvocableHandlerMethod 对象,并设置其相关属性
        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);

        // <5> 创建 ModelAndViewContainer 对象,并初始其相关属性
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
        modelFactory.initModel(webRequest, mavContainer, invocableMethod);
        mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

        // <6> 创建 AsyncWebRequest 异步请求对象
        AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
        asyncWebRequest.setTimeout(this.asyncRequestTimeout);

        // <7> 创建 WebAsyncManager 异步请求管理器对象
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        asyncManager.setTaskExecutor(this.taskExecutor);
        asyncManager.setAsyncWebRequest(asyncWebRequest);
        asyncManager.registerCallableInterceptors(this.callableInterceptors);
        asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

        // <8>
        if (asyncManager.hasConcurrentResult()) {
            Object result = asyncManager.getConcurrentResult();
            mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
            asyncManager.clearConcurrentResult();
            LogFormatUtils.traceDebug(logger, traceOn -> {
                String formatted = LogFormatUtils.formatValue(result, !traceOn);
                return "Resume with async result [" + formatted + "]";
            });
            invocableMethod = invocableMethod.wrapConcurrentResult(result);
        }

        // <9> 执行调用
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        // <10>
        if (asyncManager.isConcurrentHandlingStarted()) {
            return null;
        }

        // <11> 获得 ModelAndView 对象
        return getModelAndView(mavContainer, modelFactory, webRequest);
    }
    finally {
        // <12> 标记请求完成
        webRequest.requestCompleted();
    }
}

因为,Spring MVC 提供了大量的特性,所以 HandlerAdapter 又涉及许多组件。😈 我们主要先梳理好主流程,所以涉及的组件,还是先不详细解析。我们的目的是,看到怎么调用 HandlerMethod 方法的,即调用 Controller 的 @RequestMapping 注解的方法。

1、 创建ServletWebRequest对象,包含了request请求和response响应;
2、 调用getDataBinderFactory(HandlerMethodhandlerMethod)方法,创建WebDataBinderFactory对象,有关于数据绑定,暂时忽略;
3、 调用getModelFactory(HandlerMethodhandlerMethod,WebDataBinderFactorybinderFactory)方法,创建ModelFactory对象,有关于往Model对象设置数据,暂时忽略;
4、 【核心】调用createInvocableHandlerMethod(HandlerMethodhandlerMethod)方法,创建ServletInvocableHandlerMethod对象,然后设置其属性本文会对ServletInvocableHandlerMethod做简单的解析详细的解析在[《HandlerAdapter组件(二)之ServletInvocableHandlerMethod》][HandlerAdapter_ServletInvocableHandlerMethod]中;
5、 创建ModelAndViewContainer对象,并初始其相关属性;
6、 创建AsyncWebRequest异步请求对象,暂时忽略;
7、 创建WebAsyncManager异步请求管理器对象,暂时忽略;
8、 异步处理,并发结果相关,暂时忽略;
9、 【核心】调用ServletInvocableHandlerMethodinvokeAndHandle(ServletWebRequestwebRequest,ModelAndViewContainermavContainer,Object...providedArgs)方法,执行处理器,方法如下:;

// ServletInvocableHandlerMethod.java
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, 
                            Object... providedArgs) throws Exception {
    // <1> 执行调用
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    // <2> 设置响应状态码
    setResponseStatus(webRequest);

    // <3> 设置 ModelAndViewContainer 为请求已处理,返回,和 @ResponseStatus 注解相关
    if (returnValue == null) {
        if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
            disableContentCachingIfNecessary(webRequest);
            mavContainer.setRequestHandled(true);
            return;
        }
    } else if (StringUtils.hasText(getResponseStatusReason())) {
        mavContainer.setRequestHandled(true);
        return;
    }
    // <4> 设置 ModelAndViewContainer 为请求未处理
    mavContainer.setRequestHandled(false);
    Assert.state(this.returnValueHandlers != null, "No return value handlers");
    try {
        // <5> 处理返回值
        this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
    } catch (Exception ex) {
        if (logger.isTraceEnabled()) {
            logger.trace(formatErrorForReturnValue(returnValue), ex);
        }
        throw ex;
    }
}

// InvocableHandlerMethod.java
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {

    // <y> 解析参数
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    if (logger.isTraceEnabled()) {
        logger.trace("Arguments: " + Arrays.toString(args));
    }
    // 执行调用
    return doInvoke(args);
}

// InvocableHandlerMethod.java
@Nullable
protected Object doInvoke(Object... args) throws Exception {
    // <z1> 设置方法为可访问
    ReflectionUtils.makeAccessible(getBridgedMethod());
    try {
        // <z2> 执行调用
        return getBridgedMethod().invoke(getBean(), args);
    } catch (IllegalArgumentException ex) {
        assertTargetBean(getBridgedMethod(), getBean(), args);
        String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
        throw new IllegalStateException(formatInvokeError(text, args), ex);
    } catch (InvocationTargetException ex) {
        // Unwrap for HandlerExceptionResolvers ...
        Throwable targetException = ex.getTargetException();
        if (targetException instanceof RuntimeException) {
            throw (RuntimeException) targetException;
        }
        else if (targetException instanceof Error) {
            throw (Error) targetException;
        }
        else if (targetException instanceof Exception) {
            throw (Exception) targetException;
        }
        else {
            throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
        }
    }
}

可以大致过一下上面的执行逻辑,解析参数,通过反射执行方法,解析执行结果,详细解析在后续的《HandlerAdapter 组件(二)之 ServletInvocableHandlerMethod》open in new window文档中
10、 异步处理,并发结果相关,暂时忽略;
11、 调用getModelAndView(ModelAndViewContainermavContainer,ModelFactorymodelFactory,NativeWebRequestwebRequest)方法,获得ModelAndView对象,方法如下:;

@Nullable
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
        ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

    modelFactory.updateModel(webRequest, mavContainer);
    // 情况一,如果 mavContainer 已处理,则返回“空”的 ModelAndView 对象。
    if (mavContainer.isRequestHandled()) {
        return null;
    }
    // 情况二,如果 mavContainer 未处理,则基于 mavContainer 生成 ModelAndView 对象
    ModelMap model = mavContainer.getModel();
    // 创建 ModelAndView 对象,并设置相关属性
    ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
    if (!mavContainer.isViewReference()) {
        mav.setView((View) mavContainer.getView());
    }
    if (model instanceof RedirectAttributes) {
        Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        if (request != null) {
            RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
        }
    }
    return mav;
}

  • 情况一,如果 mavContainer 已处理,则返回“空”的 ModelAndView 对象,@ResponseBody 注解的结果处理则直接返回 null
  • 情况二,如果 mavContainer 未处理,则基于 mavContainer 生成 ModelAndView 对象

在后续的文档分析中会讲到,注意这里的 requestHandled 属性,到时候再回过头来理解😈
12、 标记请求完成,暂时忽略;

总结

Spring MVC 通过 HandlerMapping 组件会为请求找到合适的 HandlerExecutionChain 处理器执行链,包含处理器(handler)和拦截器们(interceptors)。其中处理器的实现有多种,例如通过实现 Controller 接口、HttpRequestHandler 接口,或者使用 @RequestMapping 注解将方法作为一个处理器等。这就导致 Spring MVC 无法直接执行这个处理器,所以这里需要一个处理器适配器,由它去执行处理器。

HandlerAdapter 处理器适配器对应的也有多种,那种适配器支持处理这种类型的处理器,则由该适配器去执行,如下:

  • HttpRequestHandlerAdapter:执行实现了 HttpRequestHandler 接口的处理器
  • SimpleControllerHandlerAdapter:执行实现了 Controller 接口的处理器
  • SimpleServletHandlerAdapter:执行实现了 Servlet 接口的处理器
  • RequestMappingHandlerAdapter:执行 HandlerMethod 类型的处理器,也就是通过 @RequestMapping 等注解标注的方法

这里我们重点看 RequestMappingHandlerAdapter 对象,因为这种方式是目前使用最普遍的,其他类型的 HandlerAdapter 处理器适配器做了解即可

本文讲述了 RequestMappingHandlerAdapter 处理执行器的整个流程,大致逻辑如下:

1、 通过ServletInvocableHandlerMethodHandlerMethod处理器的封装)对象去执行;
2、 需要通过HandlerMethodArgumentResolver对象进行参数解析;
3、 通过反射执行对应的Method方法对象;
4、 需要通过HandlerMethodReturnValueHandler对象对执行结果进行处理,设置到response响应中,生成对应的ModelAndView对象;

上面涉及到的三个组件分别在后续的文档中进行解析,先整体,后局部😈

参考文章:芋道源码《死磕 Spring MVC 源码分析》open in new window

版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址:open in new window