如何在 actionListener 或 action 方法中执行 JSF 验证? [英] How to perform JSF validation in actionListener or action method?

查看:28
本文介绍了如何在 actionListener 或 action 方法中执行 JSF 验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 Bean 验证在我的应用程序中运行良好.现在我想检查一个新用户是否没有选择已经选择的用户名.

I have Bean validation working nicely in my application. Now I want to check that a new user does not choose a username that has already been chosen.

在 actionlistener 中,我有检查数据库的代码,但是如果用户选择了一个已经存在的用户名,我如何强制用户返回到他们所在的页面?

In the actionlistener I have the code that checks the database but how do I force the user to be sent back to the page they were on if they choose an already existing username?

推荐答案

简介

可以这样做,但是 JSF ajax/action/listener 方法在语义上是进行验证的错误 地方.如果表单中有错误的输入值,您实际上不想在 JSF 生命周期中走得太远.您希望 JSF 生命周期在 JSF 验证阶段后停止.

Introduction

You can do it, but JSF ajax/action/listener methods are semantically the wrong place to do validation. You actually don't want to get that far in JSF lifecycle if you've wrong input values in the form. You want the JSF lifecycle to stop after JSF validations phase.

您想使用 JSR303 Bean 验证注释(@NotNull 和朋友)和/或约束验证器,或使用 JSF Validator(required="true" 等) 代替.它将在 JSF 验证阶段正确调用.这样,当验证失败时,模型值不会更新,业务操作不会被调用,您将停留在同一页面/视图中.

You want to use a JSR303 Bean Validation annotation (@NotNull and friends) and/or constraint validator, or use a JSF Validator (required="true", <f:validateXxx>, etc) for that instead. It will be properly invoked during JSF validations phase. This way, when validation fails, the model values aren't updated and the business action isn't invoked and you stay in the same page/view.

由于没有用于检查给定输入值是否根据数据库唯一的标准 Bean 验证注释或 JSF 验证器,因此您需要为此自行开发自定义验证器.

As there isn't a standard Bean Validation annotation or JSF Validator for the purpose of checking if a given input value is unique according the database, you'd need to homegrow a custom validator for that.

我将针对这两种方式展示如何创建一个自定义验证器来检查用户名的唯一性.

I'll for both ways show how to create a custom validator which checks the uniqueness of the username.

首先创建一个自定义的@Username 约束注解:

First create a custom @Username constraint annotation:

@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 {};
}

使用此约束验证器(注意:ConstraintValidator 中的 @EJB@Inject 仅从 CDI 1.1 开始起作用;所以如果您是仍然在 CDI 1.0 上,那么您需要从 JNDI 手动获取它):

With this constraint validator (note: @EJB or @Inject inside a ConstraintValidator works only since CDI 1.1; so if you're still on CDI 1.0 then you'd need to manually grab it from 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);
    }

}

最后在模型中使用如下:

Finally use it as follows in model:

@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"));
        }
    }

}

最后在view中使用如下:

Finally use it as follows in view:

<h:inputText id="username" ... validator="#{usernameValidator}" />
<h:message for="username" />

请注意,您通常会在 Validator 类上使用 @FacesValidator 批注,但在即将推出的 JSF 2.3 之前,它不支持 @EJB@Inject.另请参阅如何使用@EJB 注入@FacesValidator,@PersistenceContext、@Inject、@Autowired.

Note that you'd normally use a @FacesValidator annotation on the Validator class, but until the upcoming JSF 2.3, it doesn't support @EJB or @Inject. See also How to inject in @FacesValidator with @EJB, @PersistenceContext, @Inject, @Autowired.

这篇关于如何在 actionListener 或 action 方法中执行 JSF 验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆