Введение
Вы можете сделать это, но методы JSF ajax/action/listener семантически являются неправильным местом для проверки. На самом деле вы не хотите заходить так далеко в жизненном цикле JSF, если у вас неправильные входные значения в форме. Вы хотите, чтобы жизненный цикл JSF остановился после фазы проверки JSF.
Вы хотите использовать аннотацию JSR303 Bean Validation (@NotNull
и друзья) и/или валидатор ограничений, или вместо этого использовать JSF Validator
(required="true"
, <f:validateXxx>
и т. д.). Он будет правильно вызываться на этапе проверки JSF. Таким образом, при сбое проверки значения модели не обновляются и бизнес-действие не вызывается, и вы остаетесь на той же странице/представлении.
Поскольку не существует стандартной аннотации Bean Validation или JSF Validator для проверки того, является ли заданное входное значение уникальным в соответствии с базой данных, для этого вам потребуется создать собственный валидатор.
В обоих случаях я покажу, как создать собственный валидатор, который проверяет уникальность имени пользователя.
Пользовательская аннотация проверки JSR303 Bean
Сначала создайте пользовательскую аннотацию ограничения @Username
:
@Constraint(validatedBy = UsernameValidator.class)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface Username {
String message() default "Username already exists";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
С этим валидатором ограничения (примечание: @EJB
или @Inject
внутри ConstraintValidator
работает только с CDI 1.1, поэтому, если вы все еще используете CDI 1.0, вам нужно вручную получить его из JNDI):
public class UsernameValidator implements ConstraintValidator<Username, String> {
@EJB
private UserService service;
@Override
public void initialize(Username constraintAnnotation) {
// If not on CDI 1.1 yet, then you need to manually grab EJB from JNDI here.
}
Override
public boolean isValid(String username, ConstraintValidatorContext context) {
return !service.exist(username);
}
}
Наконец, используйте его в модели следующим образом:
@Username
private String username;
Пользовательский валидатор JSF
Альтернативой является использование пользовательского валидатора JSF. Просто реализуйте интерфейс JSF Validator
:
@ManagedBean
@RequestScoped
public class UsernameValidator implements Validator {
@EJB
private UserService userService;
@Override
public void validate(FacesContext context, UIComponent component, Object submittedAndConvertedValue) throws ValidatorException {
String username = (String) submittedAndConvertedValue;
if (username == null || username.isEmpty()) {
return; // Let required="true" or @NotNull handle it.
}
if (userService.exist(username)) {
throw new ValidatorException(new FacesMessage("Username already in use, choose another"));
}
}
}
Наконец, используйте его следующим образом:
<h:inputText id="username" ... validator="#{usernameValidator}" />
<h:message for="username" />
Обратите внимание, что обычно вы используете аннотацию @FacesValidator
для класса Validator
, но до предстоящей версии JSF 2.3 она не поддерживает @EJB
или @Inject
. См. также Как внедрить в @FacesValidator с помощью @EJB, @PersistenceContext, @Inject, @Autowired.
person
BalusC
schedule
05.05.2011