Проверка на основе пользовательских условий Spring - PullRequest
0 голосов
/ 01 июня 2018

Я хочу создать проверку на основе условий в валидаторе Spring.У меня есть один UserDTO класс, в котором есть два класса DTO с аннотацией @Valid.

Если я передам isPrimary true, тогда он должен проверять только primaryDTO bean и игнорировать secendoryDTO проверки.

public class UserDTO {
    @Valid
    private PrimaryDTO primaryDTO;
    @Valid
    private SecendoryDTO secendoryDTO;
    private boolean isPrimary;
}

public class PrimaryDTO {
    @NotEmpty(message = "Please enter email.")
    @Email(message = "Please enter a valid email.")
    private String email;
}

public class SecendoryDTO {
    @NotEmpty(message = "Please enter phone.")
    private String phone;
}

Пожалуйста, руководство.

Спасибо

1 Ответ

0 голосов
/ 01 июня 2018

Если ваша проверка зависит от нескольких полей (например, isPrimary и либо primaryDTO, либо secondaryDTO), тогда единственное решение - написать пользовательский валидатор на уровне класса (UserDTO), который будет реализовывать условную валидациюсам.

Например, создайте аннотацию:

@Documented
@Retention(RUNTIME)
@Target({ANNOTATION_TYPE, TYPE})
@Constraint(validatedBy = SecondaryValidator.class)
public @interface ValidSecondary {
    String message() default "Invalid secondary";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

и создайте валидатор, который проверяет поле secondaryDTO только тогда, когда isPrimary() равно false:

@Component
public class SecondaryValidator implements ConstraintValidator<ValidSecondary, UserDTO> {
    private Validator validator;

    public SecondaryValidator(Validator validator) {
        this.validator = validator;
    }

    @Override
    public boolean isValid(UserDTO userDTO, ConstraintValidatorContext constraintValidatorContext) {
        if (userDTO.isPrimary()) {
            return true;
        } else {
            return validator.validate(userDTO.getSecondaryDTO()).isEmpty();
        }
    }
}

После этого вы можете удалить аннотацию @Valid из поля secondaryDTO и добавить аннотацию @ValidSecondary поверх вашей UserDTO:

@ValidSecondary // Add this
public class UserDTO {
    @Valid
    private PrimaryDTO primaryDTO;
    private SecondaryDTO secondaryDTO; // No more @Valid
    private boolean primary;
}

Однако в этом случаеВы потеряете любое сообщение о нарушении ограничений из SecondaryDTO, если вы хотите иметь какой-то механизм сквозного прохождения, вы можете добавить нарушения в constraintValidatorContext в методе isValid(), например:

Set<ConstraintViolation<SecondaryDTO>> violations = validator.validate(userDTO.getSecondaryDTO());
violations.forEach(violation -> constraintValidatorContext
    .buildConstraintViolationWithTemplate(violation.getMessage())
    .addConstraintViolation());
...