当前位置:网站首页>@RequestBody的使用[通俗易懂]
@RequestBody的使用[通俗易懂]
2022-08-10 13:44:00 【全栈程序员站长】
大家好,又见面了,我是你们的朋友全栈君。
提示:建议一定要看后面的@RequestBody的核心逻辑源码以及六个重要结论!本文前半部分的内容都是一些基 本知识常识,可选择性跳过。
声明:本文是基于SpringBoot,进行的演示说明。
基础知识介绍:
@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);而最常用的使用请求体传参的无疑是POST请求了,所以使用@RequestBody接收数据时,一般都用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。
注:一个请求,只有一个RequestBody;一个请求,可以有多个RequestParam。
注:当同时使用@RequestParam()和@RequestBody时,@RequestParam()指定的参数可以是普通元素、 数组、集合、对象等等(即:当,@RequestBody 与@RequestParam()可以同时使用时,原SpringMVC接收 参数的机制不变,只不过RequestBody 接收的是请求体里面的数据;而RequestParam接收的是key-value 里面的参数,所以它会被切面进行处理从而可以用普通元素、数组、集合、对象等接收)。 即:如果参数时放在请求体中,application/json传入后台的话,那么后台要用@RequestBody才能接收到; 如果不是放在请求体中的话,那么后台接收前台传过来的参数时,要用@RequestParam来接收,或 则形参前 什么也不写也能接收。
注:如果参数前写了@RequestParam(xxx),那么前端必须有对应的xxx名字才行(不管其是否有值,当然可以通 过设置该注解的required属性来调节是否必须传),如果没有xxx名的话,那么请求会出错,报400。
注:如果参数前不写@RequestParam(xxx)的话,那么就前端可以有可以没有对应的xxx名字才行,如果有xxx名 的话,那么就会自动匹配;没有的话,请求也能正确发送。 追注:这里与feign消费服务时不同;feign消费服务时,如果参数前什么也不写,那么会被默认是 @RequestBody的。
如果后端参数是一个对象,且该参数前是以@RequestBody修饰的,那么前端传递json参数时,必须满足以下要求:
- 后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值符合(或可转换为),这一条我会在下面详细分析,其他的都可简单略过,但是本文末的核心逻辑代码以及几个结论一定要看! 实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性。
- json字符串中,如果value为””的话,后端对应属性如果是String类型的,那么接受到的就是””,如果是后端属性的类型是Integer、Double等类型,那么接收到的就是null。
- json字符串中,如果value为null的话,后端对应收到的就是null。
- 如果某个参数没有value的话,在传json字符串给后端时,要么干脆就不把该字段写到json字符串中;要么写value时, 必须有值,null 或””都行。千万不能有类似”stature”:,这样的写法,如:
注:关于@RequestParam()的用法,这里就不再一一说明了,可详见 《程序员成长笔记(一)》中的相关章节。
示例详细说明:
先给出两个等下要用到的实体类
User实体类:
Team实体类:
@RequestBody直接以String接收前端传过来的json数据:
后端对应的Controller:
使用PostMan测试:
@RequestBody以简单对象接收前端传过来的json数据:
后端对应的Controller:
使用PostMan测试:
@RequestBody以复杂对象接收前端传过来的json数据:
后端对应的Controller:
使用PostMan测试:
@RequestBody与简单的@RequestParam()同时使用:
后端对应的Controller:
使用PostMan测试:
@RequestBody与复杂的@RequestParam()同时使用:
后端对应的Controller:
使用PostMan测试:
@RequestBody接收请求体中的json数据;不加注解接收URL中的数据并组装为对象:
后端对应的Controller:
使用PostMan测试:
注:如果在后端方法参数前,指定了@RequestParam()的话,那么前端必须要有对应字段才行(当然可以通过设置 该注解的required属性来调节是否必须传),否者会报错;如果参数前没有任何该注解,那么前端可以传,也可 以不传,如:
上图中,如果我们传参中没有指定token,那么请求能正常进去,但是token为null;如果在String token前指定了@RequestParam(“token”),那么前端必须要有token这个键时,请求才能正常进去,否者报400错误。
@RequestBody与前端传过来的json数据的匹配规则
声明:根据不同的Content-Type等情况,Spring-MVC会采取不同的HttpMessageConverter实现来进行信息转换解析。 下面介绍的是最常用的:前端以Content-Type 为application/json,传递json字符串数据;后端以@RequestBody 模型接收数据的情况。
解析json数据大体流程概述:Http传递请求体信息,最终会被封装进com.fasterxml.jackson.core.json.UTF8StreamJsonParser中(提示:Spring采用CharacterEncodingFilter设置了默认编码为UTF-8),然后在publicclass BeanDeserializer extends BeanDeserializerBase implements java.io.Serializable中,通过public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException方法进行解析。
核心逻辑分析示例:
假设前端传的json串是这样的: {“name1″:”邓沙利文”,”age”:123,”mot”:”我是一只小小小小鸟~”} 后端的模型只有name和age属性,以及对应的setter/getter方法;给出一般用到的deserializeFromObject(JsonParser p, DeserializationContext ctxt)方法的核心逻辑:
小技巧之指定模型中的属性对应什么key
这里简单介绍,更多的可参考:
publicclass BeanPropertyMap implements Iterable<SettableBeanProperty>,java.io.Serializable
给出Controller中的测试类:
给出模型中的属性(setter/getter方法没截出来):
使用postman测试一下,示例:
上图简单测试了一下,但是测得并不全面,这里就不带大家一起测试了,直接给出。
全面的结论:
结论①:@JsonAlias注解,实现:json转模型时,使json中的特定key能转化为特定的模型属性;但是模型转json时, 对应的转换后的key仍然与属性名一致,见:上图示例中的name字段的请求与响应。 以下图进一步说明:
此时,json字符串转换为模型时,json中key为Name或为name123或为name的都能识别。
结论②:@JsonProperty注解,实现:json转模型时,使json中的特定key能转化为指定的模型属性;同样的,模 型转json时,对应的转换后的key为指定的key,见:示例中的motto字段的请求与响应。 以下图进一步说明:
此时,json字符串转换为模型时,key为MOTTO的能识别,但key为motto的不能识别。
结论③:@JsonAlias注解需要依赖于setter、getter,而@JsonProperty注解不需要。
结论④:在不考虑上述两个注解的一般情况下,key与属性匹配时,默认大小写敏感。
结论⑤:有多个相同的key的json字符串中,转换为模型时,会以相同的几个key中,排在最后的那个key的值给模 型属性复制,因为setter会覆盖原来的值。见示例中的gender属性。
结论⑥:后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面 的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值 符合(或可转换为)实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性。
^_^ 如有不当之处,欢迎指正
^_^ 代码托管链接 https://github.com/JustryDeng…RequestBody...
^_^ 本文已经被收录进《程序员成长笔记(二)》,笔者JustryDeng
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/130013.html原文链接:https://javaforall.cn
边栏推荐
- the height of the landscape
- Import other custom namespaces in C#
- 2022-08-09:以下go语言代码输出什么?A:否,会 panic;B:是,能正确运行;C:不清楚,看投票结果。 package main import ( “fmt“ “syn
- Cloud Migration Practice of Redis
- Lithium battery technology
- 【MinIO】Using tools
- laravel throws the error to Dingding
- The recursive recursive Fighting_ silver study ah but level 4
- 1W word detailed thread local storage ThreadLocal
- 一汽奥迪:持续34年聚焦品质与体验 立足市场需求推进产品迭代
猜你喜欢
系统的安全和应用(不会点安全的东西你怎么睡得着?)
MySQL interview questions
借数据智能,亚马逊云科技助力企业打造品牌内生增长力
[JS Advanced] Creating sub-objects and replacing this_10 in ES5 standard specification
SenseTime self-developed robotic arm, the first product is an AI chess-playing robot: Guo Jingjing is also invited as an endorsement
How does IT Xiaobai learn PHP systematically
ABAP file operations involved in the Chinese character set of problems and solutions for trying to read
进程和计划任务管理
3DS MAX 批量导出文件脚本 MAXScript 带界面
MySQL面试题整理
随机推荐
Open Office XML 格式里如何描述多段具有不同字体设置的段落
Short read or OOM loading DB. Unrecoverable error, aborting now
八大排序总是忘?快来这里~
Short read or OOM loading DB. Unrecoverable error, aborting now
高数_证明_曲率公式
系统架构系列文章三--解决传统企业核心系统的性能问题
Code Casual Recording Notes_Dynamic Programming_70 Climbing Stairs
MySQL面试题整理
Pointer (preliminary solution of C language)
OTA自动化测试解决方案---整体方案介绍
Matrix Keyboard & Calculator Small Project Based on 51 (UcosII)
用低代码驱动IT现代化
【JS高级】ES5标准规范之创建子对象以及替换this_10
2012年下半年 系统架构设计师 下午试卷 II
AWS Security Fundamentals
Fragment-hide和show
C#实现访问OPC UA服务器
3DS MAX batch export file script MAXScript with interface
Interface Automation Testing Basics
The recursive recursive Fighting_ silver study ah but level 4