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

  • 相关阅读:
    011 Go语言基础之map
    009 Go语言基础之切片
    计算机组成原理 — GPU 图形处理器
    js 实现各浏览器全屏
    js 实现各浏览器全屏
    IIS-真正解决ASP.NET每一个页面首次访问超级慢的问题
    IIS-真正解决ASP.NET每一个页面首次访问超级慢的问题
    首次启动速度慢的问题记录IIS性能优化
    首次启动速度慢的问题记录IIS性能优化
    C#-执行cmd命令,获取结果
  • 原文地址:https://www.cnblogs.com/kendoziyu/p/springMvc-RequestMapping-HandlerAdapter.html
Copyright © 2020-2023  润新知