Принятый ответ не работает, как вы ожидаете. Конечно, композиция ограничений хороша, только если вы хотите перечислить ВСЕ ошибки в ВСЕЙ цепочке композиции. Это не работает, если вы хотите досрочно выйти из первой ошибки проверки.
В документах для @ReportAsSingleViolation
говорится, что отчеты об ошибках каждого отдельного ограничения композиции игнорируются.
Использование примера принятия
@ReportAsSingleViolation
@NotEmpty
@Pattern(regexp="^([A-Za-z0-9]{2,}(\\-[a-zA-Z0-9])?)$")
@Constraint(validatedBy = {})
public @interface UserName {
String message() default "invalid userName!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Это означает, что вы получите сообщение об ошибке по умолчанию для аннотации UserName
, которое является «invalid userName!» даже если @NotEmpty сначала выйдет из строя....
Я должен сказать, что я весьма шокирован тем, насколько плох этот дизайн разработчиками проверки java bean. Нет абсолютно никакого смысла составлять валидации, если вы возвращаете совершенно не относящееся к делу сообщение. Сначала он должен завершиться ошибкой И вернуть соответствующую ошибку для проверки, которая на самом деле не удалась!. В любом случае, без массивных уродливых хаков это сделать невозможно. Такая простая задача проверки превращается в кошмар. 0_о
Мое обходное решение - не сочинять валидации, просто создайте 1 валидацию и реализуйте все это самостоятельно. Это не СУХОЕ, но, по крайней мере, простое.
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PasswordValidator.class)
public @interface Password {
String message() default "{com.example.Password.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
public class PasswordValidator implements ConstraintValidator<Password, String> {
private Pattern twoDigitsPattern;
public void initialize(Password constraint) {
twoDigitsPattern = Pattern.compile("(.*[\\d]){2}");
}
public boolean isValid(String password, ConstraintValidatorContext context) {
context.disableDefaultConstraintViolation();
if (password == null) {
context.buildConstraintViolationWithTemplate("{javax.validation.constraints.NotNull.message}")
.addConstraintViolation();
return false;
}
if (password.length() < 5 || password.length() > 10) {
context.buildConstraintViolationWithTemplate("must be between 5 to 10 characters")
.addConstraintViolation();
return false;
}
if (!twoDigitsPattern.matcher(password).matches()) {
context.buildConstraintViolationWithTemplate("must contain 2 digits between [0-9]").addConstraintViolation();
return false;
}
return true;
}
}
person
reversebind
schedule
10.11.2017