spring mvc 解析 @RequestMapping @RequestBody 过程

目录

 

解析@RequestMapping

 

解析@RequestBody


解析@RequestMapping

问题:如果让我们自己实现一个MVC,通过url能够路由到某个方法上,我们会怎么做?

答:我们会先维护一个URL 与 Controller和其具体执行方法之间的一个关系,然后在调用的时候找到对应的controller,执行对应的方法。

注册URL与方法之间的映射关系。

 


 

具体执行逻辑如下图

图片

 

代码时序图如下图

 

图片

 

时序图重点地方代码解析

  1. 需要部分校验工作基本上都是在 processCandidateBean(beanName)中做的,比方说校验controller上是否带有@Controoer注解,或者@RequestMapping注解,这个bean是否已经注册到上下文中等等。

  1. 核心执行功能如下:

图片

1. 满足条件方法执行`getMappingForMethod(Method,Class<?>)`,构造一个执行方法与url映射的对象,一般情况下这个对象就是 RequestMappingInfo

图片

需要注意的是,有时候我们Controller Bean 上面有@RequestMapping,有时候没有,所以这个地方还得解析 Controller Bean 上的@RequestMapping,如果有就将其合并起来

2. 将满足要求的对象放在一个Map中,其中泛型T 其实就是 RequestMappingInfo ,

3. 遍历刚才的Map,将其中的信息注册起来,其实就是将信息细化,放到各自的内存map中,这个注册的过程又会将RequestMappingInfo 转换成换成HandlerMethod,后期在DispartcherServlet中处理的都是HandlerMethod,如下图,红框中内容就是核心操作

图片

 

以上步骤基本将就是将url与方法的映射关系维护起来了,整体操作还是比较简单,方法调用也没有多复杂,就只用到了一个模板方法模式 基本实现都是在抽象类AbstractHandlerMethodMapping中都完成了的。

 


 

通过URL 调用@RequestMapping对应方法

下面两个时序图来分析spring mvc中执行@RequestMapping方法的全过程

图片

 

图片

时序图关键节点代码讲解

时序图中1处代码如下,getHandlerInternal获取到就是在系统启动时候放在配置类Map中的HandlerMethod,实现很简单,从原先配置过的Registry的全局Map中通过URL找到HandlerMethod

图片

2处代码获取的就是执行HandlerMethod的适配器,所有的操作都是通过适配器类操作的,

在这里留下一个问题:为什么spring这里需要创建一个适配器,不直接通过invoke的方式调用HandlerMethod 中的controller呢?

在3之后4之前都是处理环境,解析参数等等,真正执行的就是处了

图片

执行的逻辑就是先解析参数,然后通过动态代理的方式调用到代理对象就玩了

 以上就是解析@RequestMapping 以及调用@RequestMapping的整体过程,虽然还有很多细节性的东西还没有讲到,比如说跨域、异步、参数解析、类名解析、异常处理等,但是些都是让程序更健壮的地方。

 


 

解析@RequestBody

 

问题:同样,如果是让我们设计解析过程,我们会怎么做?

:首先我会校验,带有@RequestBody的参数是否必传,然后再将request中的参数转换成对应的参数类型,然后传参执行

实际情况: 其实基本差不多,但是实际实现的逻辑会更加健壮。有一点区别就是他会先解析参数,如果没有解析到参数,再来判断参数是否必传。

按照传统线上序列图

核心逻辑代码解析

图片

上面序列图核心逻辑代码已经用红框框标识出来了

1处:很重要将RequestMappingHandlerAdapter中的HandlerMethodArgumentResolverComposite设置到ServletInvocableHandlerMethod中去

有个问题:

问题:为什么需要用HandlerMethodArgumentResolverComposite 而不直接使用HandlerMethodArgumentResolver ?

在实际项目中传参的形式千变万化,怎么样能够做到最大限度的兼容呢?通过这个HandlerMethodArgumentResolverComposite 其实就是 HandlerMethodArgumentResolver的装饰类,来丰富功能

,将其所有的HandlerMethodArgumentResolver都放在其私有属性argumentResolvers这个集合中。

 

 

HandlerMethodArgumentResolver继承图

图片

那么在实际使用的时候,不同的场景就用其不同实现类来解析参数就可以了

 

找到真正解析@RequestBody的 参数解析器

在上面说到的装饰类中有一个私有getArgumentResolver(parameter) 来找到真正执行解析参数的  HandlerMethodArgumentResolver

 

图片

 

图片

不同的解析器解析逻辑是很不一样,

解析@RequestBody的参数解析器为

RequestResponseBodyMethodProcessor,代码如下,实质上还是交给其父类AbstractMessageConverterMethodArgumentResolver在处理,

 

图片

 

图片

 

图片

 

依据上面的逻辑,解析@RequestParam @PathVariable这两个注解的其实

也是HandlerMethodArgumentResolver的子类

解析 @PathVariable 的是 PathVariableMapMethodArgumentResolver

解析@RequestParam的是 RequestParamMethodArgumentResolver

 

以上就是解析@RequestMapping 以及 @RequestBody  @RequestParam @PathVariable的整体逻辑

 

配上 官方 SPRING MVC 文档

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值