简体   繁体   English

如何访问注释属性中描述的字段

[英]How to access a field which is described in annotation property

Is it possible to access a field value, where field name is described in annotation which annotate another field in class.是否可以访问字段值,其中字段名称在注释中描述,注释对类中的另一个字段进行注释。

For example:例如:

@Entity
public class User {

    @NotBlank
    private String password;

    @Match(field = "password")
    private String passwordConfirmation;
}

Annotation:注解:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FieldMatchValidator.class)
@Documented
public @interface Match {

    String message() default "{}";

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

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

    String field();
}

Now, is it possible to access field password from class User in ConstraintValidator implementaion class?现在,是否可以从 ConstraintValidator 实现类中的 User 类访问字段密码?


Edit:编辑:

I wrote something like this:我写了这样的东西:

public class MatchValidator implements ConstraintValidator<Match, Object> {

private String mainField;
private String secondField;
private Class clazz;

@Override
public void initialize(final Match match) {
    clazz = User.class;

    final Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
        if (field.isAnnotationPresent(Match.class)) {
            mainField = field.getName();
        }
    }

    secondField = match.field();
}

@Override
public boolean isValid(final Object value, final ConstraintValidatorContext constraintValidatorContext) {
    try {
        Object o; //Now how to get the User entity instance?

        final Object firstObj = BeanUtils.getProperty(o, mainField);
        final Object secondObj = BeanUtils.getProperty(o, secondField);

        return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
    } catch (final Exception ignore) {
        ignore.printStackTrace();
    }
    return true;
}
}

Now the question is how can I get the User object instance and compare fields values?现在的问题是如何获取 User 对象实例并比较字段值?

You either need to write a class level constraint in which you get the full User instance passed into the isValid call or you can use something like @ScriptAssert . 您需要编写一个类级别约束,在该约束中,您可以将完整的User实例传递给isValid调用,或者您可以使用类似@ScriptAssert的内容

At the moment it is not possible to access the root bean instance as part of a "normal" field validation. 目前,作为“正常”字段验证的一部分,无法访问根bean实例。 There is a BVAL issue - BVAL-237 - which discusses to add this functionality, but so far it is not yet part of the Bean Validation specification. 有一个BVAL问题 - BVAL-237 - 讨论了添加此功能,但到目前为止它尚未成为Bean Validation规范的一部分。

Note, there are good reasons why the root bean is not accessible atm. 注意,有很好的理由为什么根bean不能访问atm。 Constraints which rely on the root bean being accessible will fail for the validateValue case. 对于validateValue情况,依赖于可访问的根bean的约束将失败。

@Hardy Thenks for tip. @Hardy寻找小费。 Finally wrote some code which matches (more or less) expected result. 最后写了一些匹配(或多或少)预期结果的代码。

I'll paste it here, maybe will help someone to solve his problem. 我会把它贴在这里,也许会帮助别人解决他的问题。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Match {

    String field();

    String message() default "";
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MatchValidator.class)
@Documented
public @interface EnableMatchConstraint {

    String message() default "Fields must match!";

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

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

public class MatchValidator implements  ConstraintValidator<EnableMatchConstraint, Object> {

    @Override
    public void initialize(final EnableMatchConstraint constraint) {}

    @Override
    public boolean isValid(final Object o, final ConstraintValidatorContext context) {
        boolean result = true;
        try {
            String mainField, secondField, message;
            Object firstObj, secondObj;

            final Class<?> clazz = o.getClass();
            final Field[] fields = clazz.getDeclaredFields();

            for (Field field : fields) {
                if (field.isAnnotationPresent(Match.class)) {
                    mainField = field.getName();
                    secondField = field.getAnnotation(Match.class).field();
                    message = field.getAnnotation(Match.class).message();

                    if (message == null || "".equals(message))
                        message = "Fields " + mainField + " and " + secondField + " must match!";

                    firstObj = BeanUtils.getProperty(o, mainField);
                    secondObj = BeanUtils.getProperty(o, secondField);

                    result = firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
                    if (!result) {
                        context.disableDefaultConstraintViolation();
                        context.buildConstraintViolationWithTemplate(message).addPropertyNode(mainField).addConstraintViolation();
                        break;
                    }
                }
            }
        } catch (final Exception e) {
            // ignore
            //e.printStackTrace();
        }
        return result;
    }
}

And how to use it...? 以及如何使用它? Like this: 像这样:

@Entity
@EnableMatchConstraint
public class User {

    @NotBlank
    private String password;

    @Match(field = "password")
    private String passwordConfirmation;
}

Hack around... Hack because these internal Hibernate implementations won't work when they migrate to Java modules. Hack around... Hack 因为这些内部 Hibernate 实现在迁移到 Java 模块时将不起作用。


        @Override
        public boolean isValid(final Serializable value, final ConstraintValidatorContext context) {
            final var contextImpl = (ConstraintValidatorContextImpl) context;
            //noinspection unchecked
            final var descriptorImpl = (ConstraintDescriptorImpl<Exists>) contextImpl.getConstraintDescriptor();
            final var existsAnnotation = descriptorImpl.getAnnotationDescriptor().getAnnotation();
            // Removed b/c irrelevant
        }

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

相关问题 注释处理 - 如何访问(和修改)字段的内容 - annotation processing - how to access (and modify) the contents of a field Hibernate Annotations - 哪个更好,字段或属性访问? - Hibernate Annotations - Which is better, field or property access? 如何为字段编写自定义注释,为该字段创建自定义设置器? - How to write custom annotation for field which will create custom setter for that field? 如何从属性文件定义注释的字段值 - How to define field value of an annotation from property file 如何为可以是两种尺寸之一的字段应用尺寸注释 - How to apply size annotation for a field which can be either of two sizes 哪个注释字段调用方法 - which annotation field call the method 访问注释处理器中的常量字段 - Access constant field in annotation processor 在 Spring MongoDB 实体中使用@Access(AccessType.PROPERTY)注解时设置字段名 - Set field name when using @Access(AccessType.PROPERTY) annotation in Spring MongoDB Entity 如何通过注释为字段添加getter,从而将Groovy脚本内部的访问权限提供给字段 - How to give access inside Groovy script to a field by adding getter for a field through an annotation 从字段上的自定义批注访问值 - Access value from a custom annotation on a field
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM