全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 6 分钟 ✍️ juanwangdev

Spring MVC JSR-303 Bean Validation

JSR-303是Java标准的Bean Validation规范,定义了一套统一的校验注解和API。

JSR-303与Hibernate Validator关系

规范/实现说明
JSR-303Java Bean Validation 1.0规范
JSR-349Bean Validation 1.1规范
JSR-380Bean Validation 2.0规范
Hibernate ValidatorJSR规范的参考实现

JSR-303标准注解

注解类型说明
@Null任意必须为null
@NotNull任意不能为null
@AssertTrueboolean必须为true
@AssertFalseboolean必须为false
@Min数字最小值
@Max数字最大值
@DecimalMin数字最小值(字符串表示)
@DecimalMax数字最大值(字符串表示)
@Size字符串/集合大小范围
@Digits数字位数限制
@Past日期必须是过去时间
@Future日期必须是未来时间
@Pattern字符串正则匹配

JSR-380新增注解(Bean Validation 2.0)

注解说明
@NotEmpty不能为空(字符串、集合、数组)
@NotBlank不能为空白字符串
@Email邦箱格式
@Positive必须为正数
@PositiveOrZero正数或零
@Negative必须为负数
@NegativeOrZero负数或零
@PastOrPresent过去或当前时间
@FutureOrPresent未来或当前时间

基本校验示例

Java
@Data
public class UserDTO {

    @NotNull(message = "ID不能为空")
    private Long id;

    @NotBlank(message = "用户名不能为空")
    @Size(min = 3, max = 20, message = "用户名长度3-20字符")
    private String username;

    @Email(message = "邮箱格式不正确")
    private String email;

    @Min(value = 18, message = "年龄必须大于18")
    @Max(value = 100, message = "年龄不能超过100")
    private Integer age;

    @Digits(integer = 10, fraction = 2, message = "金额格式不正确")
    private BigDecimal amount;

    @Past(message = "生日必须是过去的日期")
    private Date birthday;

    @Pattern(regexp = "^[A-Za-z0-9]+$", message = "只能包含字母和数字")
    private String code;
}

Controller校验流程

Java
@RestController
@RequestMapping("/api/user")
public class UserController {

    @PostMapping
    public User create(@Valid @RequestBody UserDTO dto) {
        // 校验失败自动抛出MethodArgumentNotValidException
        return userService.create(dto);
    }

    @PostMapping("/with-binding")
    public User createWithBinding(
            @Valid @RequestBody UserDTO dto,
            BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            List<FieldError> errors = bindingResult.getFieldErrors();
            for (FieldError error : errors) {
                System.out.println(error.getField() + ": " + error.getDefaultMessage());
            }
            throw new ValidationException("参数校验失败");
        }

        return userService.create(dto);
    }
}

级联校验

Java
@Data
public class OrderDTO {

    @NotNull
    private Long id;

    @Valid    // 触发级联校验
    @NotNull
    private AddressDTO address;

    @Valid
    @Size(min = 1, max = 10)
    private List<ProductDTO> products;
}

@Data
public class AddressDTO {

    @NotBlank
    private String city;

    @NotBlank
    private String street;
}

校验分组

Java
// 定义校验分组
public interface CreateGroup {}
public interface UpdateGroup {}

@Data
public class UserDTO {

    @NotNull(groups = UpdateGroup.class, message = "更新时ID必填")
    private Long id;

    @NotBlank(groups = {CreateGroup.class, UpdateGroup.class}, message = "用户名必填")
    private String username;

    @NotBlank(groups = CreateGroup.class, message = "创建时密码必填")
    private String password;
}

@RestController
public class UserController {

    @PostMapping
    public User create(@Validated(CreateGroup.class) @RequestBody UserDTO dto) {
        // 只校验CreateGroup分组的注解
        return userService.create(dto);
    }

    @PutMapping
    public User update(@Validated(UpdateGroup.class) @RequestBody UserDTO dto) {
        // 只校验UpdateGroup分组的注解
        return userService.update(dto);
    }
}

Validator接口使用

Java
@Service
public class ValidationService {

    @Autowired
    private Validator validator;

    public void validate(Object object) {
        Set<ConstraintViolation<Object>> violations = validator.validate(object);

        if (!violations.isEmpty()) {
            StringBuilder sb = new StringBuilder();
            for (ConstraintViolation<Object> violation : violations) {
                sb.append(violation.getPropertyPath())
                  .append(": ")
                  .append(violation.getMessage())
                  .append("; ");
            }
            throw new ValidationException(sb.toString());
        }
    }

    public void validate(Object object, Class<?>... groups) {
        Set<ConstraintViolation<Object>> violations =
            validator.validate(object, groups);
        // 处理校验结果...
    }
}

ConstraintViolation信息

Java
Set<ConstraintViolation<UserDTO>> violations = validator.validate(dto);

for (ConstraintViolation<UserDTO> violation : violations) {
    // 获取校验信息
    String message = violation.getMessage();                  // 错误消息
    String propertyPath = violation.getPropertyPath().toString(); // 属性路径
    Object invalidValue = violation.getInvalidValue();       // 无效值
    Class<?> annotationType = violation.getConstraintDescriptor()
        .getAnnotation().annotationType();                    // 校验注解类型
}

自定义校验注解

Java
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdCardValidator.class)
public @interface IdCard {
    String message() default "身份证号格式不正确";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

public class IdCardValidator implements ConstraintValidator<IdCard, String> {

    @Override
    public void initialize(IdCard constraintAnnotation) {
        // 初始化配置
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }
        // 身份证号校验逻辑
        return value.matches("\\d{17}[\\dXx]");
    }
}

Payload传递元信息

Java
public class ErrorLevel implements Payload {
    private final String level;
    public ErrorLevel(String level) { this.level = level; }
    public String getLevel() { return level; }
}

@Data
public class UserDTO {
    @NotNull(message = "ID必填", payload = ErrorLevel.ERROR.class)
    private Long id;

    @NotBlank(message = "用户名必填", payload = ErrorLevel.WARN.class)
    private String username;
}

Spring MVC配置

Java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Bean
    public LocalValidatorFactoryBean validator() {
        LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
        factoryBean.setProviderClass(HibernateValidator.class);
        return factoryBean;
    }

    @Override
    public Validator getValidator() {
        return validator();
    }
}

要点总结

  • JSR-303是Java标准的Bean Validation规范
  • Hibernate Validator是JSR规范的参考实现
  • 标准注解包括@NotNull、@Size、@Min、@Max、@Pattern等
  • Bean Validation 2.0新增@NotBlank、@Email、@Positive等
  • @Valid触发级联校验,@Validated支持分组校验
  • 可通过ConstraintValidator自定义校验注解

📝 发现内容有误?点击此处直接编辑

← 上一篇 Spring MVC Hibernate Validator
下一篇 → Spring MVC 分组校验
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库