简体   繁体   English

约束注释中的变量字段

[英]Variable field in a constraint annotation

I need to create a custom constraint annotation which can access the value of another field of my bean. 我需要创建一个自定义约束注释,它可以访问我的bean的另一个字段的值。 I'll use this annotation to validate the field because it depends on the value of the other but the way I define it the compiler says "The value for annotation attribute" of my field "must be a constant expression". 我将使用这个注释来验证该字段,因为它取决于另一个的值,但是我定义它的方式编译器说“我的字段的注释属性的值”必须是一个常量表达式。

I've defined it in this way: 我用这种方式定义了它:

@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
    }

}

and in my bean I want something like this: 在我的豆子里我想要这样的东西:

public class MyBean{

     private String field1;

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

Is there any way to define the annotation so the field value can be a variable? 有没有办法定义注释,所以字段值可以是变量?

Thanks 谢谢

The easiest thing to do is take one step back: the constraint/validator you have written works on a field-level, but what you want to enforce is a cross-field dependency ie a class-level constraint. 最简单的做法是退后一步:您编写的约束/验证器在字段级别上工作,但您要强制执行的是跨字段依赖性,即类级别约束。

Rewrite your constraint and validator to work at the class level (ie the annotation will go on the class, not on the field). 重写你的约束和验证器以在类级别工作(即注释将在类上,而不是在字段上)。 That way you'll get access to the entire class. 这样你就可以访问整个班级。 In your isValid(..) method, simply do a get on both the fields, compare, and return appropriately. 在isValid(..)方法中,只需在两个字段上执行get,比较并适当返回。

As the compiler said annotations must be constant (ie you can determine the value at compile time.) Now If I'm guessing correctly it looks like you are using this annotation to denote that the values of those fields should be equal when run through the equals field validator. 正如编译器所说注释必须是常量的(即你可以在编译时确定值。)现在,如果我猜对了,看起来你正在使用这个注释来表示这些字段的值在运行时应该相等等于字段验证器。 One approach you could take is using reflection. 您可以采取的一种方法是使用反射。 Instead of trying to annotate with the value, annotate with the field name instead 而不是尝试使用值进行注释,而是使用字段名称进行注释

public class MyBean{

     private String field1;

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

Then in your validator you can read the name of the field and use reflection to access it 然后在验证器中,您可以读取字段的名称并使用反射来访问它

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

Depending on what you are trying to do you may need to add in logic based on the field type, but still the same general principle. 根据您的尝试,您可能需要根据字段类型添加逻辑,但仍然是相同的一般原则。

看看上一个问题,有多个跨领域验证解决方案: 使用Hibernate Validator进行交叉字段验证(JSR 303)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM