Bean Validation 排序方法及自定义字符串验证注解技术咨询
如何对Bean Validation约束进行排序
首先,你已经找对方向啦!Bean Validation正是通过**分组(Groups)和组序列(Group Sequence)**来控制验证顺序的,你的自定义注解里已经用到了这两个特性,但可能还有一些细节可以优化,让排序更符合预期。
我来一步步拆解怎么实现精准的验证顺序:
1. 先确认分组接口的定义
你代码里用到的First.class和Second.class是标记接口,不需要任何方法实现,只需要简单定义就行:
// 第一阶段验证组:非空、长度检查 public interface First {} // 第二阶段验证组:格式正则检查 public interface Second {}
2. 调整自定义注解里的约束分组
你当前的@NotNull没有指定groups参数,它会默认归到Default组里,这样可能会打乱你想要的顺序。建议把所有需要按顺序执行的约束都明确分配到对应的分组里,比如:
@NotNull(groups = First.class) // 归到第一阶段 @Size(min = 2, max = 128, groups = First.class) // 归到第一阶段 @Pattern( regexp = "^(?!WP_([0-9])+$)[A-Z_][A-Z0-9_-]+", groups = Second.class // 归到第二阶段 ) @Target({FIELD, ANNOTATION_TYPE}) @Retention(RUNTIME) @Documented @Constraint(validatedBy = {}) // 指定组序列:先执行First组,通过后再执行Second组 @GroupSequence(value={First.class, Second.class}) public @interface ValidIntentName { String message() default "Intent name格式无效"; Class<?>[] groups() default {}; // 别忘了Bean Validation约束注解要求的payload参数(可选,但规范里需要) Class<? extends Payload>[] payload() default {}; }
3. 组序列的核心作用
@GroupSequence的关键在于顺序执行+失败终止:
- 先执行
First组里的所有约束(@NotNull和@Size),如果其中任何一个验证失败,Second组的@Pattern不会再执行,避免不必要的正则匹配开销。 - 同一组内的约束(比如
First里的@NotNull和@Size),Bean Validation不保证具体执行顺序。如果连这两个的顺序都要严格控制(比如先检查非空,再检查长度),可以把它们拆成更细的子分组:
这样就能确保先执行public interface FirstStep {} public interface SecondStep {} public interface First extends FirstStep, SecondStep {} // 调整自定义注解的组序列 @GroupSequence(value={FirstStep.class, SecondStep.class, Second.class}) public @interface ValidIntentName { @NotNull(groups = FirstStep.class) @Size(min = 2, max = 128, groups = SecondStep.class) @Pattern(regexp = "^(?!WP_([0-9])+$)[A-Z_][A-Z0-9_-]+", groups = Second.class) // 其他参数不变 String message() default "Intent name格式无效"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }@NotNull,再执行@Size,最后执行@Pattern。
4. 验证时的注意事项
当你使用这个注解时:
- 如果是Spring环境,用
@Validated注解触发验证(如果需要指定组,可以传@Validated({First.class, Second.class}),不过因为你已经在自定义注解上指定了组序列,直接用@Validated就行)。 - 如果手动用
Validator验证:Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Intent intent = new Intent(); intent.setName(""); // 空字符串 // 验证Default组(自定义注解的默认组会用@GroupSequence替代执行顺序) Set<ConstraintViolation<Intent>> violations = validator.validate(intent); // 这里会先检查First组:@NotNull通过(空字符串不是null),但@Size失败,Second组的@Pattern不会执行
这样就能完全按照你想要的顺序执行Bean Validation约束啦!
内容的提问来源于stack exchange,提问作者Yonoss
相关产品推荐
相关产品推荐

