Можно ли передать атрибут validatedBy в аннотацию в качестве параметра? - PullRequest
2 голосов
/ 13 января 2020

Я жестко закодировал значение validatedBy следующим образом.

@Constraint(validatedBy = ReminderValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValidator{
    String message() default "{error.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Вместо жесткого кодирования значения validatedBy в моем интерфейсе аннотаций я хочу передать его как параметр, похожий на следующий.

@MyValidator(validatedBy = "ReminderValidator.class")
public class Reminder {
...
}

Это позволит мне создать только 1 аннотацию для всех проверок классов. Я просто предоставлю разные классы валидатора аннотации для валидации разных классов. Можно ли сделать что-то подобное?

Ответы [ 2 ]

2 голосов
/ 13 января 2020

Вы можете добавить несколько валидаторов в аннотацию @Constraint, и она выберет подходящие в зависимости от типа объекта.

@Constraint(validatedBy = { ReminderValidator.class, PendingValidator.class } )
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValidator{
    String message() default "{error.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

И

@MyValidator()
public class Reminder {
    ...
}

@MyValidator()
public class Pending {
    ...
}

Примеры валидаторов

public class ReminderValidator implements ConstraintValidator<MyValidator, Reminder> {
...

public class PendingValidator implements ConstraintValidator<MyValidator, Pending> {
...
1 голос
/ 13 января 2020

Дайте мне знать, если это приемлемое решение для вас -

@Constraint(validatedBy = CommonValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValidator{
    // this decides what actual validator we will use
    String validator();
    String message() default "{error.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Теперь в CommonValidator мы можем определить фактический валидатор на основе значения validator.


Пример проверки c:

public class SomeValidator {
    public static boolean isValid(Object field, ConstraintValidatorContext context) {
        // your actual validation code
    }
}

Аналогично вы можете определить и другие ваши валидаторы.


Вот как вы можете использовать данные c валидатор в фактическом валидаторе:

public class CommonValidator implements ConstraintValidator<MyValidator, Object> {

    private String validator;

    @Override
    public void initialize(MyValidator myValidator) {
        this.validator = myValidator.validator();
        // do other inits as per your requirement
    }

    @Override
    public boolean isValid(Object field, ConstraintValidatorContext context) {
        ValidatorFactory.getValidator("someValidator").isValid(field, context)
        // return other validators like above
        return false;
    }
}

наконец, вы можете использовать свою аннотацию вот так -

@MyValidator(validator = "someValidator")
private Object object;

Объект может быть любым другим классом, который вы должны обработать это в отдельном стати c валидатор.

FYI - это всего лишь идея, фактическая реализация может отличаться в зависимости от вашего варианта использования.

...