SpringBoot参数校验之@Valid与@Validated的用法与场景
作者:漫天转悠
这篇文章主要介绍了SpringBoot参数校验的用法与场景,在实际开发中,参数校验是保证接口安全性和数据完整性的重要手段,Spring Boot提供了@Valid和@Validated两个核心注解来实现参数校验,但许多开发者对它们的区别和使用场景存在疑惑,需要的朋友可以参考下
在实际开发中,参数校验是保证接口安全性和数据完整性的重要手段。Spring Boot提供了@Valid和@Validated两个核心注解来实现参数校验,但许多开发者对它们的区别和使用场景存在疑惑。本文将深入解析二者的差异,并通过代码示例演示其具体应用场景。
一、核心注解对比
| 特性 | @Valid | @Validated |
|---|---|---|
| 标准来源 | JSR-303/JSR-349规范(Java标准) | Spring框架扩展 |
| 作用范围 | 方法参数、字段、嵌套对象 | 类、方法、参数 |
| 分组校验 | 不支持 | 支持 |
| 嵌套验证 | 需配合@Valid递归触发 | 需配合@Valid递归触发 |
| 使用场景 | 简单参数校验 | 复杂校验(分组、方法参数校验) |
二、@Valid的用法与场景
1. 基本使用
@Valid主要用于方法参数校验,尤其在Controller层对DTO对象进行验证。需配合JSR-303注解(如@NotNull、@Size)使用。
示例代码:
@PostMapping("/users")
public ResponseEntity<?> createUser(@RequestBody @Valid UserDTO userDTO) {
// 业务逻辑
return ResponseEntity.ok().build();
}
public class UserDTO {
@NotBlank(message = "用户名不能为空")
private String username;
@Size(min = 6, max = 20, message = "密码长度需在6-20位")
private String password;
}2. 嵌套验证
若DTO中包含其他对象字段,需在字段上添加@Valid触发递归校验。
public class OrderDTO {
@Valid // 触发嵌套校验
private UserDTO user;
@NotNull(message = "订单金额不能为空")
private BigDecimal amount;
}三、@Validated的进阶特性
1. 分组校验
场景说明:不同业务场景下,同一对象可能需要不同的校验规则。例如,用户注册时需要验证邮箱,而更新信息时不需要。
实现步骤:
定义分组接口:
public interface CreateGroup {} // 创建分组
public interface UpdateGroup {} // 更新分组在DTO中指定分组:
public class UserDTO {
@NotBlank(groups = CreateGroup.class, message = "邮箱不能为空")
private String email;
@NotBlank(message = "用户名不能为空")
private String username;
}在Controller中使用@Validated激活分组:
@PostMapping("/users")
public ResponseEntity<?> createUser(
@RequestBody @Validated(CreateGroup.class) UserDTO userDTO) {
// 仅校验CreateGroup分组的规则
return ResponseEntity.ok().build();
}2. 方法参数校验
@Validated可用于Service层的方法参数校验,需在类上添加@Validated注解。
@Service
@Validated // 启用方法参数校验
public class UserService {
public void updateUser(@NotBlank String username, @Min(1) Long userId) {
// 业务逻辑
}
}四、嵌套验证与分组校验结合
复杂场景:在分组校验中触发嵌套对象的验证。
public class OrderDTO {
@Validated(CreateGroup.class) // 指定分组
@Valid
private UserDTO user;
@NotNull(message = "金额必填")
private BigDecimal amount;
}
// Controller层
@PostMapping("/orders")
public ResponseEntity<?> createOrder(
@RequestBody @Validated(CreateGroup.class) OrderDTO orderDTO) {
// 同时校验OrderDTO和UserDTO中CreateGroup分组的规则
return ResponseEntity.ok().build();
}五、常见问题与注意事项
1. 异常处理
校验失败会抛出以下异常:
MethodArgumentNotValidException(@Valid触发)ConstraintViolationException(@Validated触发)
统一异常处理示例:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidationException(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage()));
return ResponseEntity.badRequest().body(errors);
}
}2. 依赖问题
确保项目中引入spring-boot-starter-validation:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>3. 注意事项
- Spring版本兼容性:低版本Spring需手动启用
@EnableWebMvc或@Validated支持。 - 分组接口设计:分组接口建议定义为空接口,仅作为标识。
六、总结与最佳实践
| 场景 | 推荐注解 |
|---|---|
| Controller层DTO参数校验 | @Valid |
| 分组校验 | @Validated + 分组接口 |
| Service层方法参数校验 | @Validated(类级别) |
| 嵌套对象递归校验 | @Valid + @Validated组合 |
最佳实践:
- Controller层:优先使用
@Valid进行简单校验。 - 复杂业务校验:使用
@Validated的分组功能。 - Service层参数校验:在类上添加
@Validated,配合JSR-303注解。
以上就是SpringBoot中@Valid与@Validated的用法与场景的详细内容,更多关于SpringBoot中@Valid与@Validated的资料请关注脚本之家其它相关文章!
