gpt4 book ai didi

validation - 注释约束后如何应用 JSF 验证器?

转载 作者:行者123 更新时间:2023-12-03 13:18:18 36 4
gpt4 key购买 nike

我的问题更多是关于性能而不是功能。我正在处理注册表单的电子邮件字段。为了进行验证,我在 User 实体中为电子邮件 format 使用注释,并使用 EmailExistValidator 在数据库中检查此电子邮件是否 < strong>已经使用过。

@Entity
@Table(name = "Users")
public class User {

@Column(name = "email")
@NotNull(message = "Email address required")
@Pattern(regexp = "([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)", message = "Invalid email address")
private String email;

// ... (other fields and getters/setters here)
}

验证器:

@FacesValidator(value = "emailExistValidator")
public class EmailExistValidator implements Validator {

private static final String EMAIL_ALREADY_EXISTS = "This email address is already used.";

@EJB
private UserDao userDao;

@Override
public void validate(FacesContext context, UIComponent component, Object value)
throws ValidatorException {
String email = (String) value;
try {
if (email != null && userDao.findByEmail(email) != null) {
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
EMAIL_ALREADY_EXISTS, null));
}
} catch (DaoException e) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(),
null);
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.addMessage(component.getClientId(facesContext), message);
}
}
}

根据我的测试,如果一封电子邮件没有验证正则表达式模式,验证器仍然会被应用。 我不喜欢在我已经知道这封电子邮件甚至无效的情况下执行数据库查询来检查电子邮件是否存在的想法。它真的会降低性能(在模糊上使用 ajax 时甚至更慢表单中的事件)。

我有一些猜测,但找不到明确的答案,所以我在这里问几个问题:

  1. 将验证器与注释约束混合在一起是不是一件坏事?

  2. 在验证过程中,是否检查每个约束,即使其中一个约束没有通过? (如果是,那么是将所有消息(针对每个约束)添加到组件的 FacesContext 中,还是仅添加第一条消息?)

  3. 如果问题 2 为"is",是否有任何方法可以在未验证一个约束时立即强制停止验证?

  4. 如果问题 2 为否或问题 3 为是,是否在某处指定了约束/验证器的应用顺序?这个订单可以定制吗?

如果这很重要,我正在为我的 Facelets 组件使用 PrimeFaces。

我知道我可以将所有内容放入验证器并随时停止,但此验证器仅用于注册表单。当用于登录时,我只会检查实体的注释约束,而不是“已经存在”的部分。此外,在我看来,注释和单约束验证器比多约束验证器的内容更具可读性。

最佳答案

JSF 验证按设计运行在 JSR303 bean 验证之前。因此,当 bean 验证失败时,技术上没有办法跳过 JSF 验证。如果它们以相反的方式运行,那么理论上你会简单地检查 UIInput#isValid()在 JSF 验证器中:

UIInput input = (UIInput) component;

if (!input.isValid()) {
return;
}

很遗憾,没有 API 提供的方法来控制 JSF-JSR303 验证顺序。最好的办法是将 JSF 验证器变成真正的 JSR303 bean 验证器,并将其分配给您声明在默认组之后运行的不同组。在 JSR303 中,约束在每个组的基础上进行验证。如果一个验证组失败,则不会执行任何后续验证组。

第一个create a custom JSR303 bean validation constraint annotation :

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueEmailValidator.class)
@Documented
public @interface UniqueEmail {
String message() default "{invalid.unique.email}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

然后 create a custom JSR303 bean validation constraint validator :

public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {

@Override
public void initialize(UniqueEmail annotation) {
// Grab EJB here via JNDI?
}

@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return userDao.findByEmail(value) == null;
}

}

不幸的是,ConstraintValidator 中的 @EJB/@Inject 在 Java EE 6/JSR303 Bean Validation 1.0 中不受原生支持。它仅在 Java EE 7/JSR303 Bean Validation 1.1 中受支持。然而,它们可以通过 JNDI 获得。

然后 create a custom validation group :

public interface ExpensiveChecks {}

最后在您的实体上使用它,通过 @GroupSequence 注释声明组顺序(默认组由当前类标识):

@Entity
@Table(name = "Users")
@GroupSequence({ User.class, ExpensiveChecks.class })
public class User {

@Column(name = "email")
@NotNull(message = "Email address required")
@Pattern(regexp = "([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)", message = "Invalid email address")
@UniqueEmail(groups = ExpensiveChecks.class, message = "This email address is already used")
private String email;

// ...
}

关于validation - 注释约束后如何应用 JSF 验证器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19802209/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com