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

是否可以访问字段值,其中字段名称在注释中描述,该注释注释了类中的另一个字段。

例如:

@Entity public class User { @NotBlank private String password; @Match(field = "password") private String passwordConfirmation; } 

注解:

 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = FieldMatchValidator.class) @Documented public @interface Match { String message() default "{}"; Class[] groups() default {}; Class[] payload() default {}; String field(); } 

现在,是否可以从ConstraintValidator实现类中的类User访问字段密码?


编辑:

我写了这样的话:

 public class MatchValidator implements ConstraintValidator { 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; } } 

现在的问题是如何获取User对象实例并比较字段值?

您需要编写一个类级别约束,在该约束中,您可以将完整的User实例传递给isValid调用,或者您可以使用类似@ScriptAssert的内容

目前,作为“正常”字段validation的一部分,无法访问根bean实例。 有一个BVAL问题 – BVAL-237 – 讨论了添加此function,但到目前为止它尚未成为Bean Validation规范的一部分。

注意,有很好的理由说明root bean无法访问atm。 对于validateValue情况,依赖于可访问的根bean的约束将失败。

@Hardy提示小费。 最后写了一些匹配(或多或少)预期结果的代码。

我会把它贴在这里,也许会帮助别人解决他的问题。

 @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[] payload() default {}; } 

 public class MatchValidator implements ConstraintValidator { @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; } } 

以及如何使用它? 像这样:

 @Entity @EnableMatchConstraint public class User { @NotBlank private String password; @Match(field = "password") private String passwordConfirmation; }