问题环境
Spring 中首字母小写,第二个字母大写造成的参数问题
在进行前后端的联调时,有时候会出现,前端明明传了值,后端接口却接收不到的情况,这种情况常常让人很苦恼。已排除以下情况:
- 参数名称错误
- 接收json/form/body类型问题
都没发现什么问题。
问题关键代码
Controller 代码
@PostMapping(value = "/test")
public void test(@RequestBody UserVO userVO) {
System.out.println("用户代码:" + userVO.getUCode());
System.out.println("用户名称:" + userVO.getUName());
}
数据对象UserVO
@Data
public class UserVO {
/**
* 用户代码
*/
private Long uCode;
/**
* 用户名称
*/
private String uName;
}
Postman 工具调试
Postman参数信息

控制台打印结果
用户代码:null
用户名称:null
原因分析
com.fasterxml.jackson.databind.util.BeanUtil
类中的legacyManglePropertyName
方法中

方法解析:
- 根据入参offset去除get或者get,然后就剩下UName或者LoginType了
- 然后从第一个字母开始解析,如果第一个字母是大写的,于是就将它转成小写,然后找下一个,如果还是大写,就继续转成小写,直到找到一个小写字母后,就把之后的字母(不管大小写)一起拼接进来。
所以:
- uName 会被得到 uname
- uCode 会被得到 ucode
然后根据得到的属性名去找get/set方法,想要找到setUname/setUcode的方法没找到。
没找到原因是:
然后我们这里的VO对象使用的是@Data注解生成的get/set方法,生成的方法参考:

可以看到lombok插件这边生成的get/set方法名为
- getUCode
- setUCode
- getUName
- setUName
两个框架得到的不一样。导致了以上问题。
解决办法
改字段影响范围大情况
Jackson官方手段
- 在单字母+单词驼峰的字段上添加Jackson的注解
@JsonProperty
- 或者手写get/set方法
取巧手段 - 字段private改为public
字段第一个字母小写第二个字母大写的属性,另一个解决办法就是把private改为public
@Data
public class UserVO {
/**
* 用户代码
*/
public Long uCode;
/**
* 用户名称
*/
public String uName;
}
原理:
在Jackson获取对象字段时候会调用 com.fasterxml.jackson.databind.introspectPOJOPropertiesCollector.collectAll()
方法

上图部分会删除私有属性,也就是private
标记的属性,所以这里改为public
能解决。
改字段字段影响范围小情况(推荐)
直接改表字段名吧
避免单字母+单词驼峰设计,例如:
uNameuCodeuId
改为:
- uname
- ucode
- uid
或者其他
注意
自然情况下(未加处理):对象里面的字段设计为uName
样式,传递参数需要以uname
方式传递,且返回对象的属性名也是uname
,非Java对象里面的uName
参考文档
- Change lombok's property capitalization code. `Field xName` -> `getxName()`. · Issue #2693 · projectlombok/lombok · GitHub
- spring中,为什么前端明明传了值,后端却接收不到_后端接收不到前端的数据-CSDN博客
- 这个字段我明明传了呀,为什么收不到 - Spring 中首字母小写,第二个字母大写造成的参数问题 - 技术角落 - 博客园
https://www.syntaxspace.com/article/2504111709123599.html
评论