如何用自定义校验器验证@RequestBody的关联属性(最简方案)
Spring Boot 实现请求体跨字段校验(start < end)
最简单且有效的方式是利用Spring Validation的类级自定义校验注解,因为要校验的是两个字段之间的关系,类级校验是最直接的方案,无需额外复杂配置。
步骤1:自定义校验注解
创建一个类级别的校验注解,用于标记需要校验的请求体类:
import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.*; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = StartBeforeEndValidator.class) public @interface StartBeforeEnd { // 校验失败时的提示信息 String message() default "开始时间戳必须早于结束时间戳"; // 分组校验相关,默认空即可 Class<?>[] groups() default {}; // 负载相关,默认空即可 Class<? extends Payload>[] payload() default {}; }
步骤2:实现校验器逻辑
编写注解对应的校验器,实现ConstraintValidator接口,处理具体的校验逻辑:
import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; public class StartBeforeEndValidator implements ConstraintValidator<StartBeforeEnd, EventRequestBody> { @Override public boolean isValid(EventRequestBody requestBody, ConstraintValidatorContext context) { // 由于start和end已通过@NotNull确保非空,这里直接比较即可 return requestBody.getStart() < requestBody.getEnd(); } }
步骤3:在请求体类上添加注解
给EventRequestBody类加上自定义注解,并确保字段有getter方法(校验器需要通过getter获取字段值):
@StartBeforeEnd class EventRequestBody { @NotNull private Long start; // 时间戳 @NotNull private Long end; // 时间戳 // 必须添加getter方法,否则校验器无法获取字段值 public Long getStart() { return start; } public void setStart(Long start) { this.start = start; } public Long getEnd() { return end; } public void setEnd(Long end) { this.end = end; } }
说明
- 控制器代码无需修改,原来的
@Valid注解会自动触发这个类级校验,校验失败时会抛出MethodArgumentNotValidException,和其他内置校验的异常处理逻辑一致。 - 如果使用Spring Boot 2.x及更早版本(依赖
javax.validation而不是jakarta.validation),只需将代码中的jakarta包路径替换为javax即可。
内容的提问来源于stack exchange,提问作者heikorm
相关产品推荐
相关产品推荐

