How to access a field which is described in annotation property

前端 未结 2 1314
隐瞒了意图╮
隐瞒了意图╮ 2021-01-06 08:50

Is it possible to access a field value, where field name is described in annotation which annotate another field in class.

For example:

@Entity
publi         


        
相关标签:
2条回答
  • 2021-01-06 09:28

    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.

    At the moment it is not possible to access the root bean instance as part of a "normal" field validation. 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.

    Note, there are good reasons why the root bean is not accessible atm. Constraints which rely on the root bean being accessible will fail for the validateValue case.

    0 讨论(0)
  • 2021-01-06 09:49

    @Hardy Thenks for tip. 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;
    }
    
    0 讨论(0)
提交回复
热议问题