本次来研究一下前端传递的请求是怎么封装到后台中的,根据后台请求方法的参数不同,对应的封装逻辑也不同,本次以@RequestBody为例开始研究

1.后台接收参数的方式

我们希望将前端传递的参数封装到TestObj类的name和age字段中,在后续使用中直接使用参数传递的对象即可

  1. @RequestMapping("/hello")
  2. public String hello(@RequestBody TestObj obj) {
  3. return "hello world " + obj.getName() + " " + obj.getAge() ;
  4. }
  1. @Data
  2. public class TestObj {
  3. private String name;
  4. private String age;
  5. }

2.前端传递参数的方式

直接在浏览器地址栏中输入地址访问,发现返回了错误页面,因为浏览器地址栏只能发get请求,因此可以知道该注解只支持封装post请求传递的参数
image.png
接着使用postman发送post请求,同时参数的传递方式为json串,此时发现可以正常访问并返回数据
image.png
使用普通form表单的方式提交数据,发现返回了415,并不支持此种类型的参数传递,因此可以知道RequestBody只支持post方式的json串数据传递
image.png

3.参数封装的原理

3.1 哪些类负责解析参数

那么SpringMvc到底是怎么进行参数封装的呢,为什么只能封装json串呢,在之前的代码中可以知道,实际运行时会调用RquestMapping适配器的invokeHandlerMethod方法执行业务方法调用,在调用前会设置参数解析器,这些参数解析器就是负责参数封装的
image.png
这里默认有26种参数解析器,意味着可以解析这么多种注解标注的参数,从名字大概可以看出RequestResponseBodyMethodProcessor解析器负责解析RequestBody注解标注的参数
image.png
由supportsParameter方法可知该解析器支持解析参数上标有ResponseBody注解的参数
image.png

3.2 通过转换器获取参数信息

resolveArgument方法负责参数的解析过程,它内部主要由获取参数、绑定参数组成,获取参数时通过readWithMessageConverters方法完成的
image.png
读取参数值的核心逻辑在AbstractMessageConverterMethodArgumentResolver类的readWithMessageConverters方法中实现
image.png
首先它获取了contentType,然后遍历10个默认的消息转换器,看哪个转换器可以读取请求中的参数值,而判断的方法就是对应的转换是否可以读取contentType类型的数据,最终发现只有MappingJackson2HttpMessageConverter支持该类型
image.png
最后判断值不为空就将读取的值返回去
image.png

3.2 参数绑定

当参数解析完成后会创建WebDataBinder,调用createBinder绑定数据
image.png
在绑定的过程中会给绑定器设置124个默认的转换器,它基本包含了所有常用的类型之间转换的方式,SpringMvc使用这些转换器就可以将参数正确的转换为java对象
image.png