Spring Boot 中集成的 Jakarta Validation 注解集

1,082 阅读3分钟

在 Spring Boot 中,Jakarta Validation(原 Hibernate Validator)用于数据验证,主要通过一组 注解 来约束 Java Bean 的字段。Spring Boot 默认集成了 Jakarta Validation,并提供了 Spring Validation 的支持,使其能与 @Valid@Validated 结合使用。


  1. 常见 Jakarta Validation 注解

Jakarta Validation 提供了一些常见的 约束注解,主要分为:

  • 通用约束(字符串、数字等)
  • 集合约束(List、Map)
  • 对象级约束(级联验证)
注解作用示例
@NotNull不能为空@NotNull private String name;
@NotBlank不能为空,且不能是空白字符(仅字符串)@NotBlank private String username;
@NotEmpty不能为空,适用于集合、字符串@NotEmpty private List items;
@Size(min, max)字符串或集合长度范围@Size(min = 3, max = 10) private String name;
@Pattern(regexp)必须符合正则表达式@Pattern(regexp = "^[a-zA-Z0-9]+$") private String code;
@Email必须是合法的邮箱格式@Email private String email;
@Min(value)最小值约束(数字)@Min(18) private int age;
@Max(value)最大值约束(数字)@Max(100) private int age;
@Positive必须为正数@Positive private int count;
@Negative必须为负数@Negative private int loss;
@PositiveOrZero必须是正数或 0@PositiveOrZero private int balance;
@NegativeOrZero必须是负数或 0@NegativeOrZero private int debt;
@Future必须是未来的日期@Future private LocalDateTime eventTime;
@FutureOrPresent必须是未来或当前日期@FutureOrPresent private LocalDate startDate;
@Past必须是过去的日期@Past private LocalDate birthday;
@PastOrPresent必须是过去或当前日期@PastOrPresent private LocalDate lastModified;

  1. 进阶验证

(1) 级联验证 ( @Valid )

如果一个类包含另一个 对象类型 的字段,并且该对象也有验证注解,必须使用 @Valid 才能触发子对象的验证。

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
class Address {
    @NotBlank
    private String city;
}
@Data
class User {
    @NotBlank
    private String name;
    @Valid // 触发 Address 内的验证
    private Address address;
}

(2) 自定义校验

如果内置注解无法满足需求,可以自定义注解:

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.lang.annotation.*;
@Documented
@Constraint(validatedBy = MyConstraintValidator.class)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyConstraint {
    String message() default "不符合自定义规则";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

然后实现 ConstraintValidator

public class MyConstraintValidator implements ConstraintValidator<MyConstraint, String> {
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && value.startsWith("ABC");
    }
}

使用:

@MyConstraint
private String customField;

  1. 在 Spring Boot 中使用

(1) Controller 层参数校验

使用 @Valid@Validated 进行参数验证:

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
    @PostMapping
    public String createUser(@Valid @RequestBody User user) {
        return "User created: " + user.getName();
    }
}
@Data
class User {
    @NotBlank(message = "用户名不能为空")
    private String name;
}

(2) 处理验证异常

Spring Boot 会自动抛出 MethodArgumentNotValidException,可以自定义全局异常处理:

import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Map<String, String> handleValidationException(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error ->
            errors.put(error.getField(), error.getDefaultMessage()));
        return errors;
    }
}

  1. 结论
  • Jakarta Validation 提供了一组标准的数据约束注解,适用于 StringNumberDate 等数据类型。
  • Spring Boot 中,可以通过 @Valid@Validated 结合使用这些注解。
  • 级联验证需要 @Valid,否则不会对子对象进行校验。
  • 可以自定义校验规则,满足特殊业务需求。
  • 可以使用全局异常处理来返回更友好的错误信息。

这样就能更好地在 Spring Boot 项目中使用 Jakarta Validation 进行数据校验了!🚀