zoukankan      html  css  js  c++  java
  • 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() 方法中,我们可以找到各种各样常见的返回值是如何处理的。

  • 相关阅读:
    2.舵机
    1.呼吸灯
    Python学习笔记——Matplot库
    计算机仿真技术学习笔记(一)
    48、从堆和栈上建立对象哪个快?(考察堆和栈的分配效率比较)
    47、抖动你知道是什么吗?它也叫颠簸现象
    46、交换空间与虚拟内存的关系
    44、程序从堆中动态分配内存时,虚拟内存上怎么操作的
    43、一般情况下在Linux/windows平台下栈空间的大小
    42、一个由C/C++编译的程序占用的内存分为哪几个部分?
  • 原文地址:https://www.cnblogs.com/kendoziyu/p/springMvc-RequestMapping-HandlerAdapter.html
Copyright © 2011-2022 走看看