Несколько Regex @Pattern для 1 поля?

Я попытался применить несколько аннотаций @Pattern к одному полю:

@Pattern(regexp = "(?=.*[0-9])", message = "Password must contain one digit.")
@Pattern(regexp = "(?=.*[a-z])", message = "Password must contain one lowercase letter.")
@Pattern(regexp = "(?=.*[A-Z])", message = "Password must contain one uppercase letter.")
@Pattern(regexp = "(?=\S+$)", message = "Password must contain no whitespace.")
private String password;

Однако я не могу этого сделать. Я хочу, чтобы отдельные сообщения были связаны с нарушением регулярного выражения в поле пароля. Возможно ли это?

Моей альтернативой является использование тегов JSF 2.0 f: validatorRegex.

Ответ 1

Вы можете использовать внутреннюю аннотацию @List @Pattern:

@Pattern.List({
    @Pattern(regexp = "(?=.*[0-9])", message = "Password must contain one digit."),
    @Pattern(regexp = "(?=.*[a-z])", message = "Password must contain one lowercase letter."),
    @Pattern(regexp = "(?=.*[A-Z])", message = "Password must contain one uppercase letter."),
    @Pattern(regexp = "(?=\\S+$)", message = "Password must contain no whitespace.")
})
private String password;

Ответ 2

Возможно, вы захотите изучить структуру ограничений. Вы создали бы одну аннотацию на ограничение паролей, составленную из аннотации @Pattern, а затем, наконец, построите одну написанную аннотацию, используя ранее определенные четыре. Для этого не требуется никакого дополнительного кода Java.

http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html_single/#validator-customconstraints-compound

В противном случае создайте (с сопровождающим java-кодом) пользовательскую аннотацию, называемую @PasswordValidator.

Мне нравятся составленные валидаторы, так как цель аннотаций валидации ясна с их целью, а не с множеством непересекающихся аннотаций.

Ответ 3

Я модифицировал ответ Gunnar и написал сложное ограничение, и теперь это выглядит корректно на 4 модульных тестах:

@NotNull
@Size(min=6, max=45)
@Pattern.List({
    @Pattern(regexp = "(?=.*[0-9]).+", message = "Password must contain one digit."),
    @Pattern(regexp = "(?=.*[a-z]).+", message = "Password must contain one lowercase letter."),
    @Pattern(regexp = "(?=.*[A-Z]).+", message = "Password must contain one uppercase letter."),
    @Pattern(regexp = "(?=.*[[email protected]#$%^&*+=?-_()/\"\\.,<>~`;:]).+", message ="Password must contain one special character."),
    @Pattern(regexp = "(?=\\S+$).+", message = "Password must contain no whitespace.")
})
@Constraint(validatedBy = {}) // constraints composition
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface StrongPassword {

     String message() default "Password doesn't match bean validation constraints.";
     Class<?>[] groups() default {};
     Class<? extends Payload>[] payload() default {};
}

Ответ 4

Решение Gunnar не будет работать для меня... '. +' в его регулярном выражении, кажется, отсутствует. Тем не менее, я использую шаблон Michal patternList, и он работает как прелесть для меня. (Игра 2.3.x/Ebean-ORM)

@Pattern.List({
        @Pattern(regexp = "(?=.*[0-9]).+", message = "Password must contain one digit."),
        @Pattern(regexp = "(?=.*[a-z]).+", message = "Password must contain one lowercase letter."),
        @Pattern(regexp = "(?=.*[A-Z]).+", message = "Password must contain one upper letter."),
        @Pattern(regexp = "(?=.*[[email protected]#$%^&*+=?-_()/\"\\.,<>~`;:]).+", message ="Password must contain one special character."),
        @Pattern(regexp = "(?=\\S+$).+", message = "Password must contain no whitespace.")
})
@Constraints.Required()
public String password1;