java 约束注释中的变量字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2469473/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 21:19:50  来源:igfitidea点击:

Variable field in a constraint annotation

javavalidationannotationsconstraints

提问by Javi

I need to create a custom constraint annotation which can access the value of another field of my 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".

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

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:

在我的 bean 中,我想要这样的东西:

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

谢谢

采纳答案by GaryF

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 i.e. a class-level constraint.

最简单的做法是退后一步:您编写的约束/验证器在字段级别工作,但您要强制执行的是跨字段依赖项,即类级别约束。

Rewrite your constraint and validator to work at the class level (i.e. 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、比较并适当地返回。

回答by larsrc

Check out this previous question, has multiple solutions for cross-field validation: Cross field validation with Hibernate Validator (JSR 303)

查看上一个问题,有多种跨领域验证解决方案:Cross field validation with Hibernate Validator (JSR 303)

回答by M. Jessup

As the compiler said annotations must be constant (i.e. 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.

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