使用postman传list参数,使用@RequestBody接收list对象接收不到,对象的属性值都是null

探讨使用Lombok时,因属性命名不规范导致POST请求的List参数无法正确解析的问题及解决方案,强调代码规范的重要性。

controller层是这样写的,因为之前接收list值的时候也是这样去写的,所以这部分代码应该是对的
在这里插入图片描述
这个是我的实体,使用了lombok来写get和set方法。
在这里插入图片描述

然后使用postman传一个list参数,
在这里插入图片描述
程序中拿到的对象值都是null。
在这里插入图片描述
其实这个也怪自己,不懂lombok就随便使用,也慢慢明白了网上为什么那么多人说不推荐使用lombok,因为你都不知道人家的get和set方法是怎么写的,出了问题当然不知道错在那里。

而拿不到参数的原因就出现在这里,set方法不对,导致序列化的时候,值设置不进去。大家可以看我的对象中的属性值没有按照正常的规范去写的,有的属性开头是大写。

对这就是关键所在,lombok生成的内容是这样的
在这里插入图片描述
发现this哪里去了?我个人理解是这样的,开头大写的他可能当成静态变量了,直接给赋值了。

这种情况怎么办?
解决办法1:
改回来呗,规范写法,属性开头字母小写。
解决办法2:
如果你真的就想开头大写的,我就任性,就想这么写这么办?只能手动生成一下set方法,然后在set方法上写如下注解,这样就可以设置值了。

@JsonProperty(value = "StrTalker")

经过这次后发现,自己以后要规范写代码,看看lombok吧,不懂就用,出了问题就得难受一天。

如果解决了你的问题。
点个赞吧。

<think>我们正在讨论的是在Spring MVC中接收POST请求的多级对象参数时,应该使用内部类还是静态嵌套类(静态内部类)来定义这些对象。 关键点在于:Spring MVC在反序列化JSON到Java对象时(通过@RequestBody),需要有无参构造函数和getter/setter方法。 无论是内部类还是静态嵌套类,只要满足这些条件,Spring MVC都可以正常反序列化。 但是,内部类(非静态嵌套类)会隐式持有外部类的引用,这可能导致以下问题: 1. 序列化/反序列化问题:如果内部类需要被序列化(例如通过RPC输),则外部类也必须实现Serializable,并且内部类与外部类的隐式引用关系可能导致不必要的序列化或循环引用。 2. 内存泄漏:内部类实例会持有外部类实例的引用,如果内部类对象被长生命周期对象引用,即使外部类实例已经不再需要,也无法被回收。 3. 创建限制:非静态内部类的实例必须先有外部类实例才能创建。在Spring MVC中,当我们使用@RequestBody时,Spring会通过反射创建对象实例。对于非静态内部类,如果没有外部类实例,则无法创建内部类实例(除非在外部类实例中创建),因此Spring无法直接通过反射创建非静态内部类的实例。 而静态嵌套类(static nested class)不会持有外部类的引用,它就像是一个独立的类,只是被嵌套在另一个类中。因此: 1. 静态嵌套类可以独立实例化,不需要外部类实例。 2. 没有隐式引用,因此不会导致上述问题。 因此,在Spring MVC中,当我们使用@RequestBody接收多级对象参数时,应该使用静态嵌套类(静态内部类)来定义这些嵌套对象。 另外,关于Lombok的使用问题(引用[1]提到的问题),无论是内部类还是静态嵌套类,我们都需要确保为每个属性提供getter和setter方法。使用Lombok时,只需要在类上添加@Data或@Getter/@Setter注解即可。但要注意:如果使用内部类,Lombok生成的getter/setter方法可能会因为内部类的特殊作用域而出现问题(虽然一般不会,但内部类的使用限制可能会带来其他问题)。因此,从避免问题的角度,使用静态嵌套类更稳妥。 总结:在POST请求中接收多级对象参数时,建议使用静态嵌套类(静态内部类)来定义嵌套对象。 参考引用[1]中的问题,他们遇到了使用@RequestBody接收list对象时属性为null的情况,其中一个原因可能是没有正确的getter/setter(可能是由于Lombok使用不当)。因此,我们除了选择静态嵌套类外,还要确保提供了正确的getter/setter方法。 示例代码: 假设有一个多级对象,包含一个用户信息(User)和一个地址列表(Address),其中Address是嵌套对象。 正确做法(使用静态嵌套类): ```java public class UserDTO { private String name; private List<AddressDTO> addresses; // 使用静态嵌套类 @Data public static class AddressDTO { private String city; private String street; } // 省略UserDTO的getter/setter(同样可以使用Lombok) } ``` 在Controller中: ```java @PostMapping("/saveUser") public ResponseEntity<?> saveUser(@RequestBody UserDTO userDTO) { // 处理userDTO return ResponseEntity.ok().build(); } ``` 这样,Spring MVC就可以正确地反序列化多级对象。 为什么不用内部类(非静态)? 如果我们把AddressDTO定义为非静态内部类,那么我们需要这样创建AddressDTO对象: ```java UserDTO user = new UserDTO(); UserDTO.AddressDTO address = user.new AddressDTO(); // 必须通过外部类实例来创建 ``` 但是Spring在反序列化时无法通过反射来创建非静态内部类的实例(因为它需要一个外部类实例的引用),所以会导致反序列化失败。 因此,结论:在Spring MVC中接收多级对象参数时,必须使用静态嵌套类(静态内部类)来定义嵌套对象。 相关问题: 1. 如何避免Spring MVC中@RequestBody反序列化失败? 2. 在Spring MVC中,如何处理嵌套对象的验证? 3. 静态嵌套类和内部类在序列化时有哪些区别? </think>在处理 POST 请求中的多级对象参数时,**推荐使用静态内部类(static nested class)** 来定义接收参数对象结构。以下是详细分析和理由: ### 📌 核心建议与原因 1. **静态内部类更适合参数绑定** - 静态内部类**不依赖外部类实例**,可独立实例化(通过 `new Outer.StaticInner()`),Spring MVC 能直接通过反射创建对象实例完成参数绑定[^4] - 内部类(非静态)需先创建外部类实例(`new Outer().new Inner()`),这在参数绑定场景中会导致**反序列化失败**(如引用[1]中出现的属性值null 问题) 2. **避免 Lombok 序列化问题** - 如引用[1]所示,Lombok 自动生成的 getter/setter 有时不符合 JSON 反序列化要求(如属性名大小写不匹配)[^1] - 静态内部类可**显式定义 getter/setter**,避免依赖 Lombok 的隐式行为: ```java public class RequestDTO { public static class Address { // 静态内部类 private String city; // 显式定义 getter/setter public String getCity() { return city; } public void setCity(String city) { this.city = city; } } } ``` 3. **与 HTTP 参数输机制兼容** - POST 请求参数通过 `@RequestBody` 绑定(如引用[2][4]),JSON 结构需与 Java 对象严格匹配[^4] - 多级对象在 JSON 中表现为嵌套结构,静态内部类能清晰映射: ```json { "user": { "name": "Alice", "address": { // 对应静态内部类 Address "city": "Beijing" } } } ``` ### 🔍 关键区别对比 | **特性** | **静态内部类** | **内部类** | |------------------------|-----------------------------------|-----------------------------------| | 实例化方式 | `new Outer.StaticInner()` | `outer.new Inner()` | | 外部类依赖 | ❌ 独立存在 | ✅ 需外部类实例 | | Spring 参数绑定支持 | ✅ 直接支持 | ❌ 无法直接绑定(需额外处理) | | JSON 反序列化 | ✅ 完整支持 | ⚠️ 需自定义适配器 | | 内存开销 | 较小(无外部类引用) | 较大(隐含 `this$0` 引用) | | Lombok 兼容性风险 | 低(可显式定义 getter/setter) | 高(依赖自动生成,易出错)[^1] | ### 🛠 实践示例 ```java // 控制器层 @PostMapping("/submit") public ResponseEntity<?> submitOrder(@RequestBody OrderRequest request) { // 处理多级对象 System.out.println(request.getUser().getAddress().getCity()); return ResponseEntity.ok().build(); } // 使用静态内部类定义多级对象 public class OrderRequest { private User user; // 静态内部类层级1 public static class User { private String name; private Address address; // 嵌套静态内部类 // getter/setter } // 静态内部类层级2 public static class Address { private String city; // getter/setter } // 主对象 getter/setter } ``` ### ⚠️ 注意事项 1. **避免循环嵌套** - 多级对象不宜超过 3 层(如 `OrderRequest.User.Address`),过度嵌套会导致 JSON 结构复杂化 2. **验证参数完整性** - 使用 `@Valid` 注解校验嵌套对象: ```java public ResponseEntity<?> submitOrder(@Valid @RequestBody OrderRequest request) ``` 3. **Content-Type 设置** - POST 请求需明确指定 `Content-Type: application/json`(Postman 中需手动配置) > 💡 经验提示:如引用[1]所示,当出现属性值null 时,首要检查: > ① JSON 字段名与 Java 属性名是否匹配(大小写敏感) > ② 是否缺少无参构造器(静态内部类默认提供) > ③ Lombok 生成的 getter/setter 是否符合预期[^1] ### 📚 结论 在接收 POST 多级对象参数时,**优先选择静态内部类**,因其: 1. **兼容 Spring MVC 参数绑定机制** 2. **规避内部类的实例化依赖问题** 3. **降低 Lombok 导致的序列化风险** 4. **简化 JSON 到对象的映射过程** 静态内部类是多级对象输场景中最可靠的设计选择,能有效避免引用[1][4]中出现的参数绑定异常。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值