spring5源码篇(12)——spring-mvc请求流程

这篇具有很好参考价值的文章主要介绍了spring5源码篇(12)——spring-mvc请求流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

spring-framework 版本:v5.3.19

一、请求流程

总体流程在 DispatchServelt#doDispatch 方法
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java

1、处理器映射器

首先会获取根据url去映射对应的处理器(即接口执行方法)
看到对应的 getHandler 方法
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
为方便阅读,进入debug。可以看到springmvc默认为我们注册了三个handlerMapping。

springMvc中的各个组件如处理器映射器,处理器适配器,视图解析器等是如何注入到容器的,先暂时不看,第二部分在看(问题1)。

1.1、 RequestMappingHandlerMapping

而其中我们最常用的一个就是RequestMappingHandlerMapping,所以这里只看这个类的 getHandler 方法(其实也是其抽象父类的方法)。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java

1.2、获取对应的映射方法

getHandlerInternal 方法入手,看看是如何把一个请求映射到对应的方法的。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
这里首先会从 mappingRegister 中去找可以根据url直接得到的映射(即没有替换符),如果找不到再去所有注册的映射中找,然后返回一个最匹配的映射对应的处理器。

mappingRegister 可以简单的理解成 Map<url,handler>。实际上,为提供效率一共维护了3个map
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
这些map是如何初始化的,第二部分再讲(问题2)。

至于是如何匹配这些映射的,从 addMatchingMappings 入手
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
这里其实就是把匹配逻辑抽象成一个个condition,如果满足所有 condition 说明这是一个可用的处理器。注意,仅是可用而已,并不一定会用这个处理器。因为可能同时会匹配到多个可用的处理器,但是最终只会返回最匹配的那一个。

1.3、添加拦截器

在前面的总体流程中注释到,获取处理器的时候,返回的是一个处理器链。因为可能会配置有拦截器,而拦截器的添加从 getHandlerExecutionChain 入手。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
可以看到,就只是遍历当前 handlerMapping 所添加的所有拦截器,若匹配,则将该拦截器添加到处理器链中而已。至于 handlerMapping 的拦截器是如何添加的,第二部分再讲(问题3)。

2、获取合适的处理器适配器

spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
Spring MVC可能会有多种类型的处理器,例如控制器(Controller)、RESTful控制器等。处理器适配器负责选择并调用合适的处理器来处理请求。这一步就是去获取一个合适的处理器适配器,其实就是一个简单遍历获取,在spring mvc 默认提供的几种适配器中,最常用的还是 RequestMappingHandlerAdapter

3、通过处理器适配器执行处理器方法

3.1、拦截器的前置后置

在正式看处理器之前,顺便提一嘴拦截器的执行。
在执行实际业务方法之前会先执行处理器链中拦截器前置方法。同理,执行完业务方法后会执行处理器链中拦截器的后置方法。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
拦截器的执行就是一个遍历,就不上代码了。

3.2、处理器的执行

ha.handle 入手
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
不管是哪种适配器,最终都会依次通过 参数解析器、处理器、结果处理器 将方法返回值封装成 ModelAndView 对象。

3.2.1 参数解析器解析参数和执行处理器方法

从 invokeForRequest 入手
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
处理器方法的执行就是反射实现的,没啥好看的。主要看参数解析器是如何解析参数的。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
InvocableHandlerMethod 中维护了名为 resolvers 的 HandlerMethodArgumentResolverComposite 对象(多个参数解析器的封装),并且这个变量的值是处理器适配器传过来的。至于处理器适配器的参数解析器是哪来的,先暂时不看,后面第二部分再看(问题4)。这里只需知道参数解析器是在这里解析的以及值是处理器适配器传过来的就可以了。

3.2.2 结果处理器处理结果

从 returnValueHandlers.handleReturnValue 入手
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
**跟参数解析器维护的复合对象一样,也维护了一个名为 returnValueHandlers 的 HandlerMethodReturnValueHandlerComposite 复合对象,并且这个变量的值也是处理器适配器传过来的。**至于处理器适配器的结果处理器是哪来的,也先暂时不看。

一般来说参数解析器的命名为 xxxMethodArgumentResolver 而结果处理器的命名为 xxxMethodReturnValueHandler。但是如果即是参数解析器又是结果处理器的命名就会xxxMethodProcessor。而我们常用的 RequestResponseBodyMethodProcessor 就是这种类型。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java

3.2.3 消息转化器

首先并不是所有的参数解析器或者结果处理器都会用到消息转化器。,但至少我们最常用的 **RequestResponseBodyMethodProcessor 无论是解析参数还是处理结果,都会用到消息转化器。**对应的方法分别是 readWithMessageConverters,writeWithMessageConverters。并且write是直接写到 http 的response,这也意味着 @ResponseBody 不需要通过视图解析器解析渲染视图。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java

在 RequestResponseBodyMethodProcessor 中无论是read还是write,都会去遍历参数解析器/结果处理器中维护的消息转化器列表。至于 参数解析器/结果处理器的消息转化器列表是哪里来的,也先暂时不看,后面在看(问题5)。

4、视图解析器

试想这么一个接口,没有 @ResponseBody 并且返回值是一个字符串。

如果有 @ResponseBody 注解,ModelAndView为null,无需解析渲染视图。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
在我们配置如下的视图解析器时会访问到servlet容器下的mv.html页面。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
从字符串到返回的具体页面,这正是视图解析器所做的事情。

关于视图解析器,从 processDispatchResult 入手
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
解析:如果 ModelAndView 有视图名(在上面的例子中视图名就是方法返回的字符串)就会调用视图解析器去解析视图名得到一个视图 View 对象,反之就从 ModelAndView 中直接获取 View 对象。总之,不管怎样,这里一定要有 View 对象,没有就报错。
渲染:然后再调用上一步得到的 View 对象 render 方法并将 ModelAndView 里的 Model 数据传入,从而将数据渲染带视图上(如:jsp)。最后将渲染后的结果返回至前端。


至此一个完整的请求流程就看完了。为更形象记忆 spring mvc 各组件之间的关系,这里附上一张网图
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java

二、请求流程中的一些问题

1、各种组件如处理器映射器,处理器适配器,视图解析器等是如何注入到spring容器的?

答:@EnableWebMvc注解(相当于xml配置: <mvc:annotation-driven/>)。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
@EnableWebMvc 引入了 DelegatingWebMvcConfiguration,而这个类中就默认注入了 spring mvc 的各种组件。
比如:
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java

2、RequestMappingInfoHandlerMapping 处理器映射器中维护的映射map (即MapingRegister) 是如何初始化的?

答:在 RequestMappingInfoHandlerMapping bean生命周期的 afterPropertiesSet。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java

3、处理器映射器中的拦截器是如何添加的?

答:以 RequestMappingInfoHandlerMapping 为例,在 DelegatingWebMvcConfiguration 注入处理器映射器的时就同时会去set拦截器。
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
其中 getInterceptors 代码如下
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
说白了就是 getInterceptors 方法,会依次调用所有的 WebMvcConfigurer.addInteceptors 方法将自定义配置的拦截器添加到处理器映射器中的 InterceptorRegistry。之后处理器映射器在映射处理器时,将其中匹配的拦截器添加到处理链,进而实现拦截器的效果。

正是因为自动注入的原理,所以我们平时配置spring mvc时只需注入一个实现 WebMvcConfigurer 接口的类。

但其实截至目前为止添加的还只是一个原始版本的拦截器,真正使用的拦截器是适配后的版本。
适配的时机是在处理器映射器生命周期的 setApplicationContext 方法。(最后会调用到 initApplicationContext)
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java

4、处理器适配器的参数解析器和结果处理器是如何来的?

答:在 RequestMappingHandlerAdapter bean生命周期的 afterPropertiesSet。

spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
具体添加了哪些参数解析器,结果处理器就不细看了,太多了…

5、参数解析器/结果处理器中的消息转化器是如何来的?

答:来自处理器适配器,而处理器适配器的消息转化器来自 WebMvcConfigurer 配置或者默认配置。

如下图:
(参数解析器/结果处理器中的消息转化器来自处理器适配器)
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java
(适配器的来自 WebMvcConfigurer 配置或者默认配置)
spring5源码篇(12)——spring-mvc请求流程,Spring,spring,mvc,java

至于this.configurers.configureMessageConverters(converters);
首先configurers在前面第三个问题已经看过了,就是自动注入的 WebMvcConfigurer 总和。所以这句总的来说就是依次调用所有的 WebMvcConfigurer.configureMessageConverters 方法将自定义配置的消息添加到处理器适配器中。文章来源地址https://www.toymoban.com/news/detail-618983.html

到了这里,关于spring5源码篇(12)——spring-mvc请求流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring、Spring-MVC、Mybatis、Mybatis-generator整合核心配置文件记录

    Spring、Spring-MVC、Mybatis、Mybatis-generator整合核心配置xml文件记录 spring-mybatis.xml

    2024年01月22日
    浏览(44)
  • Spring-MVC使用JSR303及拦截器,增强网络隐私安全

    目录 一、JSR303 ( 1 )  是什么 ( 2 )  作用 ( 3 )  常用注解 ( 4 )  入门使用 二、拦截器 2.1  是什么 2.2  拦截器与过滤器的区别 2.3  应用场景 2.4 基础使用 2.5 用户登录权限控制 给我们带来的收获 JSR 303是Java规范请求(Java Specification Request)的一部分, 它定义了一套标准的Jav

    2024年02月09日
    浏览(34)
  • Spring MVC是什么?详解它的组件、请求流程及注解

    作者: Insist-- 个人主页: insist--个人主页 作者会持续更新网络知识和python基础知识,期待你的关注 前言 本文将讲解Spring MVC是什么,它的优缺点与九大组件,以及它的请求流程与常用的注解。 目录 一、Spring MVC是什么? 二、Spring MVC的优缺点 1、优点 2、缺点 三、Spring MVC的九

    2024年02月12日
    浏览(33)
  • spring-mvc系列:详解@RequestMapping注解(value、method、params、header等)

    目录 一、@RequestMapping注解的功能 二、@RequestMapping注解的位置 三、@RequestMapping注解的value属性 四、@RequestMapping注解的method属性 五、@RequestMapping注解的params属性 六、@RequestMapping注解的header属性 七、SpringMVC支持ant分格的路径 八、SpringMVC支持路径中的占位符 从注解名称上我们可

    2024年02月14日
    浏览(32)
  • Spring-mvc的参数传递与常用注解的解答及页面的跳转方式---综合案例

    目录 一.slf4j--日志 二.常用注解        2.1.@RequestMapping       2.2.@RequestParam       2.3.@RequestBody       2.4.@PathVariable 三.参数的传递 3.1 基础类型 3.2 复杂类型 3.3 @RequestParam 3.4  @PathVariable 3.5 @RequestBody 3.6 增删改查  四.返回值            4.1 void 返回值   4.2 String

    2024年02月09日
    浏览(43)
  • spring5源码篇(9)——mybatis-spring整合原理

    spring-framework 版本:v5.3.19 spring和mybatis的整合无非主要就是以下几个方面: 1、SqlSessionFactory怎么注入? 2、Mapper代理怎么注入? 3、为什么要接管mybatis事务? 在mybatis-spring中,定义了一个新的factoryBean——SqlSessionFactoryBean,我们将其注入到spring容器即可。 其实也不难猜到,这

    2024年02月03日
    浏览(28)
  • 【Spring】Spring MVC请求响应

    访问不同的路径, 就是发送不同的请求。在发送请求时, 可能会带⼀些参数, 所以学习Spring的请求, 主要是学习如何传递参数到后端以及后端如何接收。 传递参数,我们通过postman测试。 正常传递: 可以看到, 后端程序正确拿到了name参数的值。 Spring MVC 会根据⽅法的参数名, 找

    2024年02月08日
    浏览(36)
  • 12 扩展Spring MVC

    ✔         页面跳转功能:访问localhost:8081/jiang会自动跳转到另一个页面。         首先,在config包下创建一个名为MyMvcConfig的配置类:          类上加入@Configuration注解,类实现WebMvcConfiger接口,实现里面的视图跳转方法addViewConrollers:         注意:在转发的地址中,不

    2024年02月15日
    浏览(25)
  • Spring MVC:请求转发与请求重定向

    转发( forward ) ,指服务器接收请求后,从一个资源跳转到另一个资源中。请求转发是一次请求,不会改变浏览器的请求地址。 简单示例: 1.通过 String 类型的返回值实现转发

    2024年02月08日
    浏览(33)
  • spring mvc 请求与响应

    我是南城余!阿里云开发者平台专家博士证书获得者! 欢迎关注我的博客!一同成长! 一名从事运维开发的worker,记录分享学习。 专注于AI,运维开发,windows Linux 系统领域的分享! 知识库链接: 请求与响应 · 语雀 1. 请求映射路径 get请求是路径传参,而post请求是body传参

    2024年01月25日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包