本文目录导读:

Bean Validation 使用指南
Bean Validation(JSR 380)是Java中用于验证Java Bean的标准规范,最常用的实现是Hibernate Validator。
添加依赖
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
或单独使用
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.2.0.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
常用注解
实体类验证注解
public class User {
@NotNull(message = "ID不能为空")
private Long id;
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 20, message = "用户名长度需要在2-20之间")
private String username;
@Email(message = "邮箱格式不正确")
private String email;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
@Min(value = 18, message = "年龄不能小于18岁")
@Max(value = 60, message = "年龄不能大于60岁")
private Integer age;
@Past(message = "生日必须是过去的时间")
private Date birthday;
@Future(message = "过期时间必须是未来的时间")
private Date expireDate;
@Positive(message = "价格必须为正数")
private BigDecimal price;
@NotBlank(message = "状态不能为空")
@Pattern(regexp = "ACTIVE|INACTIVE", message = "状态只能为ACTIVE或INACTIVE")
private String status;
// getters and setters
}
验证分组
// 定义分组接口
public interface CreateGroup {}
public interface UpdateGroup {}
// 使用分组
public class User {
@NotNull(groups = UpdateGroup.class, message = "更新时ID不能为空")
private Long id;
@NotBlank(groups = {CreateGroup.class, UpdateGroup.class},
message = "用户名不能为空")
private String username;
@Email(groups = CreateGroup.class, message = "邮箱格式不正确")
private String email;
}
使用方式
方式1:手动验证
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
User user = new User();
// 设置属性...
// 验证所有规则
Set<ConstraintViolation<User>> violations = validator.validate(user);
// 按组验证
Set<ConstraintViolation<User>> violations2 = validator.validate(user, CreateGroup.class);
// 处理验证结果
for (ConstraintViolation<User> violation : violations) {
System.out.println(violation.getMessage());
System.out.println(violation.getPropertyPath());
System.out.println(violation.getInvalidValue());
}
方式2:Spring Boot Controller验证
@RestController
public class UserController {
@PostMapping("/users")
public ResponseEntity<?> createUser(
@Valid @RequestBody User user,
BindingResult result) {
if (result.hasErrors()) {
Map<String, String> errors = new HashMap<>();
result.getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage()));
return ResponseEntity.badRequest().body(errors);
}
// 处理业务逻辑
return ResponseEntity.ok("创建成功");
}
// 简化方式:使用@Validated
@PostMapping("/users/v2")
public ResponseEntity<?> createUserV2(
@Validated(CreateGroup.class) @RequestBody User user) {
// 验证失败会自动抛出异常
return ResponseEntity.ok("创建成功");
}
}
方式3:@Validated注解
@Service
@Validated
public class UserService {
public User createUser(@Valid User user) {
// 验证失败会抛出 ConstraintViolationException
return userRepository.save(user);
}
}
自定义验证
创建自定义注解
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {PhoneValidator.class})
public @interface Phone {
String message() default "手机号格式不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
实现验证器
public class PhoneValidator implements ConstraintValidator<Phone, String> {
private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true; // 非空验证由@NotNull处理
}
return value.matches(PHONE_REGEX);
}
}
使用自定义注解
public class User {
@Phone(message = "手机号格式错误")
private String phone;
}
全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidationExceptions(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return ResponseEntity.badRequest().body(errors);
}
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<?> handleConstraintViolation(
ConstraintViolationException ex) {
Map<String, String> errors = new HashMap<>();
ex.getConstraintViolations().forEach(violation -> {
String fieldName = violation.getPropertyPath().toString();
String errorMessage = violation.getMessage();
errors.put(fieldName, errorMessage);
});
return ResponseEntity.badRequest().body(errors);
}
}
常用验证注解总结
| 注解 | 说明 |
|---|---|
| @NotNull | 值不能为null |
| @NotEmpty | 字符串、集合、Map、数组不能为空 |
| @NotBlank | 字符串不能为空且不能包含空白字符 |
| @Size | 限制字符串、集合、Map、数组的大小 |
| @Min/@Max | 数字最小值/最大值 |
| 邮箱格式 | |
| @Pattern | 正则表达式匹配 |
| @Past/@Future | 过去/未来时间 |
| @Positive/@Negative | 正数/负数 |
| @AssertTrue/@AssertFalse | boolean值检查 |
这样,你就可以在Java应用中使用Bean Validation进行数据验证了。