在注释上使用 validator.getConstraintsForClass 与使用包含注释的 getConstraintsForProperty 会产生不同的结果

Using validator.getConstraintsForClass on an annotation gives different result than using getConstraintsForProperty containing the annotation

提问人:bobbyrne01 提问时间:11/6/2023 最后编辑:bobbyrne01 更新时间:11/10/2023 访问量:58

问:

我有许多 Java Annotation 类。

我们的想法是,我的项目的开发人员/消费者将在他们的 POJO 内的字段上使用这些注释来描述每个字段。

这些批注之间的示例关系:@CustomString -> @CustomPassword

为什么当我尝试获取使用约束时,它不包含里面指定的值,即@CustomPasswordvalidator.getConstraintsForClassminCustomPassword10

我想使用:

@OverridesAttribute(constraint = CustomString.class, name = "min")
int min() default 10;

重写该值,因为我希望开发人员能够创建自己的注释类,这些类位于其之上,并可能提供自己的重写。CustomPassword

@CustomString集合和约束:@Sizeminmax

import java.lang.annotation.*;
import javax.validation.Constraint;
import javax.validation.OverridesAttribute;
import javax.validation.Payload;
import javax.validation.constraints.Size;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Size
@Constraint(validatedBy = {})
public @interface CustomString {

  @OverridesAttribute(constraint = Size.class, name = "min")
  int min() default 0;

  @OverridesAttribute(constraint = Size.class, name = "max")
  int max() default Integer.MAX_VALUE;

  Class<?>[] groups() default {};

  Class<? extends Payload>[] payload() default {};

  String message() default "{org.example.annotation.base.string}";
}

@CustomPassword它包含对 的引用,并尝试覆盖 from :@CustomStringmin@CustomString

import org.ecample.annotation.base.CustomString;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.OverridesAttribute;
import javax.validation.Payload;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

@CustomString
@Constraint(validatedBy = {})
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface CustomPassword {

  @OverridesAttribute(constraint = CustomString.class, name = "min")
  int min() default 10;

  Class<?>[] groups() default {};

  Class<? extends Payload>[] payload() default {};

  String message() default "{org.example.annotation.extended.password}";
}

为什么当我运行时:

Class<?> klass = CustomPassword.class;
Validator validator =
        Validation.byDefaultProvider()
            .configure()
            .messageInterpolator(new ParameterMessageInterpolator())
            .buildValidatorFactory().getValidator();
BeanDescriptor beanDescriptor = validator.getConstraintsForClass(klass);

里面还是有一个的,难道不应该被里面覆盖并设置为吗?constraintDescriptorsBeanDescriptormin0minCustomPassword10

((BeanDescriptorImpl)beanDescriptor).constraintDescriptors.iterator().next().annotationDescriptor

@c.c.c.m.t.a.b.CustomString(groups=[Ljava.lang.Class;@3d9f0a5, max=2147483647, message={org.example.annotation.base.string}, min=0, payload=[Ljava.lang.Class;@1953bc95)
Java 验证 注释约束 Bean-Validation

评论

0赞 Anish B. 11/9/2023
你能通过 github 提供一个最小的代码库示例吗?

答:

2赞 mark_o 11/10/2023 #1

问题在于,您正在尝试查看约束注释本身的 Bean 描述符。旨在提供 Bean 的元数据。如果您尝试以下操作:Validator#getConstraintsForClass(..)

public class ConstrainedBean {
    @CustomPassword
    public String password;
}
//...

BeanDescriptor beanDescriptor = validator.getConstraintsForClass( ConstrainedBean.class );

此 Bean 描述符将包含一个受约束的属性,您将能够获得预期的导航,首先到达 ,然后再到达 。10constraintDescriptor#composingConstraintsCustomStringSize

当你传递 时,你会得到一个元数据,就好像你要验证一个实例一样,在这一点上,验证器认为是一个类级约束,并且不考虑任何一个 from,因为 bean 不会覆盖任何约束属性。CustomPassword.classCustomPassword.classCustomStringOverridesAttributeCustomPassword