作者:_______王晓 | 来源:互联网 | 2024-12-04 17:07
本文深入探讨了@RequestBody注解的使用场景及核心逻辑,包括其与@RequestParam的区别和结合使用的方法。文章前半部分介绍了基础知识,后半部分则详细分析了源码和重要结论。
提示:强烈建议阅读本文关于@RequestBody核心逻辑的源码分析及六个关键结论!前半部分内容为基础知识,可根据需要跳过。
声明:本文基于Spring Boot框架进行讲解。
基础知识概览:
@RequestBody主要用于接收前端通过POST方法发送的JSON数据(请求体中的数据)。GET请求由于没有请求体,因此不能使用@RequestBody接收数据。在同一接收方法中,@RequestBody和@RequestParam可以同时使用,但@RequestBody只能出现一次,而@RequestParam可以多次出现。
注意:每个请求仅有一个RequestBody,但可以有多个RequestParam。当同时使用@RequestParam和@RequestBody时,RequestParam可以接收普通元素、数组、集合、对象等。如果参数位于请求体中,需用@RequestBody接收;若不在请求体中,则用@RequestParam接收或省略注解。
如果参数前有@RequestParam注解,前端必须提供相应的名称(无论是否有值),否则请求将返回400错误。若未使用@RequestParam注解,前端可以提供也可以不提供相应名称,存在时自动匹配,不存在时请求仍可成功。
当后端参数为对象且使用@RequestBody修饰时,前端传递的JSON数据需满足以下条件:
- 后端将HTTP输入流中的数据映射到目标类时,依据JSON中的键匹配实体类属性。如果键值对符合或可转换为目标类型,将调用setter方法赋值。
- JSON中的值为空字符串时,后端对应属性为String类型则接收空字符串,为Integer、Double等数值类型则接收null。
- JSON中的值为null时,后端接收到的也是null。
- 若某参数无值,应确保JSON中不包含该字段,或确保其值为null或空字符串。
示例详解:
首先展示两个用于示例的实体类:User和Team。
@RequestBody直接接收前端传来的JSON数据示例:
后端Controller代码示例:
使用Postman进行测试:
@RequestBody接收简单对象示例:
后端Controller代码示例:
使用Postman进行测试:
@RequestBody接收复杂对象示例:
后端Controller代码示例:
使用Postman进行测试:
@RequestBody与@RequestParam同时使用示例:
后端Controller代码示例:
使用Postman进行测试:
@RequestBody接收请求体中的JSON数据,不加注解接收URL中的数据并组装为对象示例:
后端Controller代码示例:
使用Postman进行测试:
注意:如果后端方法参数前有@RequestParam注解,前端必须提供相应的字段,否则会报400错误;若无此注解,前端可选提供字段。
@RequestBody与前端JSON数据的匹配规则:
声明:根据不同的Content-Type,Spring MVC会选择不同的HttpMessageConverter实现进行数据转换。本文讨论的是前端以application/json类型传递JSON数据,后端使用@RequestBody接收的情况。
解析JSON数据的大致流程为:HTTP请求体信息被封装进UTF8StreamJsonParser中,然后通过BeanDeserializer类中的deserializeFromObject方法进行解析。
核心逻辑分析示例:
假设前端传递的JSON字符串为{"name1":"邓沙利文","age":123,"mot":"我是一只小小小小鸟~"},后端模型只有name和age属性。以下是deserializeFromObject方法的核心逻辑示例:
小技巧:指定模型属性对应的JSON键:
这里简要介绍如何使用@JsonAlias和@JsonProperty注解来指定模型属性对应的JSON键。更多细节请参考相关文档。
Controller中的测试类示例:
模型属性示例:
使用Postman进行测试:
全面结论:
结论①:@JsonAlias注解允许JSON中的特定键转换为模型的特定属性,但模型转JSON时,键名保持与属性名一致。
结论②:@JsonProperty注解不仅允许JSON中的特定键转换为模型的特定属性,而且模型转JSON时,键名也会转换为指定的名称。
结论③:@JsonAlias注解依赖于setter和getter方法,而@JsonProperty注解不依赖。
结论④:在不使用上述注解的情况下,默认键名与属性名匹配时大小写敏感。
结论⑤:若JSON中有多个相同键,转换为模型时,最后一个键的值会被保留。
结论⑥:后端@RequestBody注解对应的类在将HTTP输入流中的数据映射到目标类时,会根据JSON中的键匹配实体类属性,并调用setter方法赋值。
如有不当之处,欢迎指正