写在前面
如果想搞清楚 参数解析 和 结果集处理 的逻辑,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() 方法中,我们可以找到各种各样常见的返回值是如何处理的。