约束批注中的变量字段

2022-09-04 21:32:36

我需要创建一个自定义约束注释,该注释可以访问我的bean的另一个字段的值。我将使用此注释来验证字段,因为它取决于另一个字段的值,但是我定义它的方式,编译器说我的字段的“注释属性的值”必须是常量表达式”。

我是这样定义的:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=EqualsFieldValidator.class)
@Documented
public @interface EqualsField {
    public String field();

    String message() default "{com.myCom.annotations.EqualsField.message}";

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

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

public class EqualsFieldValidator implements ConstraintValidator<EqualsField, String>{

    private EqualsField equalsField;

    @Override
    public void initialize(EqualsField equalsField) {
        this.equalsField = equalsField;     
    }

    @Override
    public boolean isValid(String thisField, ConstraintValidatorContext arg1) {
        //my validation
    }

}

在我的豆子里,我想要这样的东西:

public class MyBean{

     private String field1;

     @EqualsField(field=field1)
     private String field2;
}

有没有办法定义注释,以便字段值可以是变量?

谢谢


答案 1

最简单的方法是退后一步:你编写的约束/验证器在字段级别上工作,但你想强制的是跨字段依赖关系,即类级约束。

重写约束和验证器以在类级别工作(即注释将在类上进行,而不是在字段上进行)。这样,您就可以访问整个班级。在您的 isValid(..) 方法中,只需对这两个字段执行 get,比较并相应地返回。


答案 2

正如编译器所说,注释必须是常量(即您可以在编译时确定值)。现在,如果我猜对了,看起来你正在使用此注释来表示在通过等于字段验证器运行时,这些字段的值应该是相等的。您可以采取的一种方法是使用反射。与其尝试使用值进行批注,不如使用字段名称进行批注

public class MyBean{

     private String field1;

     @EqualsField("field1")
     private String field2;
}

然后在验证器中,您可以读取字段的名称并使用反射来访问它

Object o = object.getClass().getDeclaredField(annotationValue).get(object);
o == object.(field with annotation) OR
o.equals(object.(field with annotation));

根据您要尝试执行的操作,您可能需要根据字段类型添加逻辑,但仍具有相同的一般原理。


推荐