@Builder
什么场景适合使用 Builder 注解
Bean 中属性较多时,采用建造者模式较好
解释了@Builder 和@Entity 一起使用时,为什么有时会提示必须要有无参构造https://www.jianshu.com/p/18a5cdffe992
踩坑:@Builder 不会生成无参构造以及 getter、setter,在 spring 底层中经常会使用动态代理(依赖于 Getter/Setter)给 Bean 赋值,如果一个 bean 仅仅使用了@Builder 而没有提供 get/set,则会遇到一些问题
例如:在以下代码中,使用 ResultBody 作为请求的响应体,
@RestControllerAdvice
public class ControllerExceptionAdvice {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResultBody handleInvalidRequestException(Exception ex) {
return ResultBody.error(HttpStatus.BAD_REQUEST.toString(), ex.getLocalizedMessage());
}
}
但如果 ResultBody 并没有声明 getter/setter
@Builder
@AllArgsConstructor
@Getter // 此处若不添加 getter 方法,则不能通过 cglib 动态代理为属性赋值,则无法正常返回相应体
public class ResultBody {
private String code;
private String message;
private Object body;
public static ResultBody success(Object body) {
return ResultBody.builder().body(body).code(HttpStatus.OK.toString()).message("success").build();
}
public static ResultBody error(String code, String message) {
return ResultBody.builder().code(code).message(message).build();
}
}
结果就是并不能按照 ResultBody 结构返回,如果加上@Data 或者@Getter 则正常
@Valid/@Validated
请求对象中包含 Map 且 map 中包含对象时如果使用@Valid - 如下在 Map 声明时给需要校验的对象 User 加上@Valid,在 User 对象中给需要校验的属性添加校验即可
@PostMapping(path = "/userMap")
public @ResponseBody ResultBody getUserMapRes(@RequestBody @Valid BaseUserRequest request) {
var userResponse = userService.getUserMap(request);
return ResultBody.builder().code(HttpStatus.OK.toString()).message("successfully get user maps").body(userResponse).build();
}
@JsonIgnoreProperties
@Data
public class BaseUserRequest {
@JsonProperty
@NotNull
Map<Integer, @Valid User> integerUserMap;
}
@Entity
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
@Email
private String email;
}
网友评论