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

查看:107
本文介绍了如何在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"<f:validateXxx>等).在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 接口:

Custom JSF Validator

An alternative is to use a custom JSF validator. Just implement the JSF Validator interface:

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

}

最后在视图中按如下方式使用它:

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天全站免登陆