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

  • 相关阅读:
    为开源项目 go-gin-api 增加后台任务模块
    将多行数据以',' 进行分隔
    syslog中的“(CRON)信息(未安装MTA,丢弃输出)”错误,crontab定时任务失效
    为什么我不推荐大家去外包公司?
    Linux永久修改系统时间
    云数据库 Redis 暂时不支持外网访问
    Nginx中worker connections问题的解决方法 大量用户502
    入手
    nginx 之$proxy_host|$host|$http_host区别
    grpc-golang入门
  • 原文地址:https://www.cnblogs.com/kendoziyu/p/springMvc-RequestMapping-HandlerAdapter.html
Copyright © 2011-2022 走看看