使用Spring的@RequestBody注解,无法映射首字母大写属性的踩坑记录

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Spring的@RequestBody注解,无法映射首字母大写属性的踩坑记录相关的知识,希望对你有一定的参考价值。

参考技术A 使用@RequestBody注解,进行json反序列化映射的时候,若实体类属性为首字母大写,将无法映射成功。

Spring的@RequestBody注解,进行参数映射时使用的是set方法,若有两个参数,以java命名规范命名应为name与sex,但若命名为Name、Sex,虽然生成的set方法依然是setName()、setSex(),但Spring框架缺没办法区分属性是name还是Name,按照命名规则来会给name赋值,产生错误。

属性加上@JsonProperty("XXX")注解来指定映射的参数名

重磅来袭:Spring之RequestBody的使用姿势小结

参考技术A

SpringMVC中处理请求参数有好几种不同的方式,如我们常见的下面几种

对上面几种方式有兴趣的可以看一下这篇博文: SpringMVC之请求参数的获取方式

除了上面的几种方式之外,还有一种 @RequestBody 的使用方式,本文则主要介绍这种传参的使用姿势和相关注意事项

借助Spring框架,使用@RequestBody并没有什么难度,很简单的就可以写一个使用case出来,如下

看上面的实现,和我们通常的写法并无差别,无非是将以前的 @RequsetParam 注解换成 @RequsetBody 注解,而且这个注解内部只有一个filed,比RequsetParam还少

看到上面的实现,估计也可以猜出,这个注解对于后端而言,写没啥问题,关键是如何用(具体来讲是如何给前端用)

上面写完了,接下来的重点就是如何使用了,在使用之前,有必要了解下 RequestBody 这个注解出现的原有以及应用场景(换句话说它和RequestParam有什么区别,为什么要单独地搞一个这个东西出来)

RequestBody

a. content-type定义

在进入下一步之前,有必要说一下Content-Type这个http请求头的作用了,下面一段来自其他博文,原文链接见最后

常见媒体格式如下:

以application开头的媒体格式类型:

b. content-type 实例说明

上面算是基本定义和取值,下面结合实例对典型的几种方式进行说明

对于前端使用而言,form表单的enctype属性为编码方式,常用有两种:
application/x-www-form-urlencoded和multipart/form-data,默认为application/x-www-form-urlencoded。

Get请求

发起Get请求时,浏览器用
application/x-www-form-urlencoded方式,将表单数据转换成一个字符串(key1=value1&key2=value2...)拼接到url上,这就是我们常见的url带请求参数的情况

Post表单

发起post请求时,如果没有传文件,浏览器也是将form表单的数据封装成k=v的结果丢到http body中,拿开源中国的博客提交的表单为例,一个典型的post表单,上传的数据拼装在form data中,为kv结构

如果有传文件的场景,Content-Type类型会升级为multipart/form-data,这一块不详细展开,后面有机会再说

Post json串

post表单除了前面一种方式之外,还有一种也是我们常见的,就是将所有的表单数据放在一个大的json串中,然后丢给后端,这里也有一个在线的实例,某电商平台的商品发表,截图如下

注意看上面的Request Payload,是一个大的json串,和前面差别明显

c. RequestBody请求

根据RequestBody的定义,要想访问前面定义的那个接口,使用传统的表单传递方式是不行的,curl命令测试如下

后端对应的输出如下(抛了一个异常,表示@RequestBody注解修饰rest接口,不支持 Content type \'
application/x-www-form-urlencoded;charset=UTF-8\'

因此使用姿势需要显示添加请求头,传参也改变一下

返回结果如下

a. content-type显示指定

根据前面的说明,可以知道 @RequestBody 这个注解的使用,使得REST接口接收的不再content-type为
application/x-www-form-urlencoded的请求, 反而需要显示指定为application/json

b. 请求方法

RequestBody支持GET方法么?前面都是采用post提交参数,如果改成GET会怎样?

curl测试方式

对应的后端debug截图如下,发现使用GET方式,并没有问题,依然可以获取到参数

换成大名鼎鼎的POSTMAN来测试

使用post方法请求时,截图如下,主要就是修改header的content-type,然后在body中添加json串格式的请求

然而改成get之后,body都直接灰掉了,也就是它不支持在get请求时,提交Body数据

url请求方式

接下来直接换成url的请求方式,看是否直接支持get请求

浏览器中输入时,服务器400, 换成curl方式请求,抛的是缺少RequestBody的异常,也就是说,将json串拼接到url中貌似不行(也有可能是我的使用姿势不对。。。)

小结

c. 参数获取

这个主要就是后端编写接口时,获取RequestBody参数的问题了,通过测试,发现在HttpServletRequest参数中,居然拿不到提交的RequestBody参数,演示如下

请求url为

对应的debug截图如下,url参数可以拿到,RequestBody参数没有

首先声明,下面的这段分析,没有看源码,纯属于个人推断,如有问题,对被误导的朋友表示歉意,也希望对此有了解的朋友,多多批评指正

对上面的猜测做一个小小的验证,改成直接从HttpServletRequest的Reader流中获取请求body参数

验证如下

其实到这里,有个有意思的地方已经引起了我的好奇,那就是在Spring容器中HttpServletRequest这个东西,是怎么运转的,后面有机会再聊,此处不展开...

</article>
最后,我还整理了一份面试宝典,有需要的私信小助理【666】

以上是关于使用Spring的@RequestBody注解,无法映射首字母大写属性的踩坑记录的主要内容,如果未能解决你的问题,请参考以下文章

自定义spring参数注解 - 打破@RequestBody单体限制

Spring中的注解 @RequestBody和@ResponseBody的使用和区别

使用Spring的@RequestBody注解,无法映射首字母大写属性的踩坑记录

Kotlin Spring Boot Webflux 使用 @Valid 注解验证 @RequestBody

Spring中的@RequestBody和@ResponseBody注解

180730-Spring之RequestBody的使用姿势小结