我必须使用自定义验证器还是有注释?
这两种方式都可以。
在自定义 JSF 验证器的情况下,您只需要了解 EJB 不能注入到 @FacesValidator 中。您基本上有 3 个选择:
- manually obtain it from JNDI
- or, make it a
@ManagedBean instead of @FacesValidator
- or, install OmniFaces which adds transparent support for
@EJB and @Inject in @FacesValidator
最终,假设您采用@ManagedBean 方法,您最终会是这样:
@ManagedBean
@RequestScoped
public class UsernameValidator implements Validator {
@EJB
private UserService service;
public void validate(FacesContext context, UIComponent component, Object submittedValue) throws ValidatorException {
if (submittedValue == null) {
return; // Let required="true" handle.
}
String username = (String) submittedValue;
if (service.exist(username) {
throw new ValidatorException(new FacesMessage("Username already in use, choose another"));
}
}
}
具体用法如下:
<h:inputText ... validator="#{usernameValidator}" />
在 JSR303 bean 验证的情况下,您需要创建 custom @Constraint annotation 和 custom ConstraintValidator。您需要确保您至少使用 CDI 1.1,否则您无法在 ConstraintValidator 中注入 EJB,您需要通过 initialize() 方法从 JNDI 手动获取它。您无法通过将其设为托管 bean 来解决它,甚至 OmniFaces 对此也没有任何魔力。
例如
@Constraint(validatedBy = UsernameValidator.class)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface Username {
String message() default "Username already in use, choose another";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
与
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;