SpringMVC之RequestMapping执行过程(HandlerAdapter篇)

Posted 剑道子羽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC之RequestMapping执行过程(HandlerAdapter篇)相关的知识,希望对你有一定的参考价值。

写在前面

如果想搞清楚 参数解析结果集处理 的逻辑,RequestMappingHandlerAdapter 是我们必须要弄明白的类。

下面以一段 Hello World 代码为例:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {
	
	@RequestMapping(value="/sayHello")
        @ResponseBody
	public String printHello(@RequestParam(defaultValue = "guest") String name) {
		return "hello, " + name;
	}
}

说得通俗一点,就是 printHello 执行之前,SpringMVC 框架干了点什么? printHello 返回值之后,SpringMVC 框架干了点什么? printHello 假如发生了异常,SpringMVC 框架又为我们看了点什么?

概述 RequestMappingHandlerAdapter

RequestMappingHandlerAdapter 有两个成员变量:

  • HandlerMethodArgumentResolverComposite 本身也是实现 HandlerMethodArgumentResolver 接口的,还包含一组 HandlerMethodArgumentResolver 接口实例,目的只是为了把适配器的遍历逻辑放在其中。

  • HandlerMethodReturnValueHandlerComposite 实现了 HandlerMethodReturnValueHandler 接口,同时还包含一组 HandlerMethodReturnValueHandler 接口实例,目的也是包装循环的代码。

初始化 RequestMappingHandlerAdapter

RequestMappingHandlerAdapter 又实现了 InitializingBean 接口,因此在 Spring 容器加载该 Bean 时,会触发 afterPropertiesSet() 方法。

Spring中的InitializingBean接口的使用 介绍了 Spring Bean 初始化的两个方法,一个是实现 InitializingBean,另一个是 init-method 。

那么复习一下,RequestMappingHandlerAdapter 加入到 Spring 容器中的时机是什么时候呢?

答:在 DispatcherServlet # initStrategies 中调用 initHandlerAdapters 初始化 处理器适配器。

想进一步了解该知识点的,可以参考这篇文章 详细解读 DispatcherServlet 初始化过程(带时序图)

初始化 RequestMappingHandlerAdapter Bean 的过程如图所示:

@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);
	}
        // @InitBinder 注解相关的参数解析器
	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 是 SpringMVC 实现 参数解析结果集处理 的核心类之一。

其中,解析参数的接口为 HandlerMethodArgumentResolver

处理结果集的接口为 HandlerMethodReturnValueHandler

RequestMappingHandlerAdapter 实现了 InitializingBean,因此初始化的过程在 afterPropertiesSet() 方法中。

getDefaultArgumentResolvers() 方法中,我们可以找到各种各样常见的参数是如何解析的。

getDefaultReturnValueHandlers() 方法中,我们可以找到各种各样常见的返回值是如何处理的。

以上是关于SpringMVC之RequestMapping执行过程(HandlerAdapter篇)的主要内容,如果未能解决你的问题,请参考以下文章

springmvc之@Controller@RequestMapping等注解解说

springmvc之RequestMapping注解既可以修饰类也可以修饰方法

SpringMVC之RequestMapping执行过程(HandlerAdapter篇)

springmvc注解之@RequestMapping注解

SpringMVC之使用requestMapping映射请求映射参数映射头

SpringMVC之Restful