[英]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.