Bean Validation怎么用?

wen python案例 2

本文目录导读:

Bean Validation怎么用?

  1. Bean Validation 使用指南
  2. 添加依赖
  3. 常用注解
  4. 验证分组
  5. 使用方式
  6. 自定义验证
  7. 全局异常处理
  8. 常用验证注解总结

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 数字最小值/最大值
@Email 邮箱格式
@Pattern 正则表达式匹配
@Past/@Future 过去/未来时间
@Positive/@Negative 正数/负数
@AssertTrue/@AssertFalse boolean值检查

这样,你就可以在Java应用中使用Bean Validation进行数据验证了。

抱歉,评论功能暂时关闭!