@Builder注释导致@RequestBody的前端json反序列化失败,HTTP400

项目里发生了一个bug,就是前端请求一个接口时候,报了HTTP 400 Bad Request

通常来说这个问题是前后端的参数没对齐,比如前端传了个String,但后端对应的是Integer。

所以我就排查了半天,结果没发现啥错误,有点懵。

最后发现问题出在Controller层里,@RequestBody SubmitParam。

而SubmitParam中的某一个参数,我给加上了@Data和@Builder,注释,这个@Builder注释可好,直接给我干400了,其实去掉@Builder或者加上@AllArgsConstructor和@NoArgsConstructor都可以解决这个问题。

这是为什么呢,因为@Builder算是Lombok里很常用的注释了,可以简化我们构建对象,避免大量set的语句。当你在一个类上使用@Builder注解时,Lombok会自动生成一个静态内部类Builder,将目标类的参数都复制到Builder类里,用于创建该类的实例,提供一种流畅的链式方式来构建对象。

举个例子

import lombok.Builder;

@Builder
public class Person {
    private String name;
    private int age;
    private String address;
}

// 在其他地方的代码中
Person person = Person.builder()
                      .name("John")
                      .age(30)
                      .address("123 Main St")
                      .build();

坑就在@Builder注释在目标类中创建一个私有构造函数,参数为 Builder类型。在Builder类中提供设置各个参数的方法,并返回当前对象。最后在 Builder类中提供一个 build方法,用来创建目标类的实例,并将各个参数赋值给目标类。

然而!!!!@RequestBody在接受前端传来的json反序列化为Java对象时候,会默认调用无参构造的,@Builder会给默认的无参构造器顶掉,这就会导致@RequestBody没法替我们反序列化了,就会导致400 Bad Request。

另外需要注意:

(1)如果你在类上使用了 @Builder 注解,那么你需要手动添加一个无参构造函数,否则有些序列化框架需要通过 newInstance 构造对象时会报错。

(2)如果你在类上使用了 @Builder 注解,那么你不能再在构造函数或方法上使用 @Builder 注解,否则会导致重复生成构造器类。

(3)如果你想给某个属性设置一个默认值,那么你需要在属性上使用 @Builder.Default 注解,否则默认值会被忽略。

(4)如果你想让子类继承父类的属性,那么你需要在子类的全参构造函数上使用 @Builder 注解,并且在父类上使用 @AllArgsConstructor 注解,否则子类的构造器类不会包含父类的属性。

相关推荐
xlsw_3 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹3 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭4 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫4 小时前
泛型(2)
java
超爱吃士力架4 小时前
邀请逻辑
java·linux·后端
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石4 小时前
12/21java基础
java
李小白665 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp5 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶5 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb