Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Validation 如何在actionListener或action方法中执行JSF验证?_Validation_Jsf_Bean Validation - Fatal编程技术网

Validation 如何在actionListener或action方法中执行JSF验证?

Validation 如何在actionListener或action方法中执行JSF验证?,validation,jsf,bean-validation,Validation,Jsf,Bean Validation,我的应用程序中的Bean验证工作得很好。现在我想检查新用户是否没有选择已经选择的用户名 在actionlistener中,我有检查数据库的代码,但是如果用户选择了一个已经存在的用户名,我如何强制用户返回到他们所在的页面?为此,最好使用action方法而不是actionlistener。然后,如果用户名存在,您可以从此方法返回null(重新加载触发该操作的页面)。下面是一个例子: 在facelet中: <h:commandButton action="#{testBean.doAction}

我的应用程序中的Bean验证工作得很好。现在我想检查新用户是否没有选择已经选择的用户名


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

为此,最好使用action方法而不是actionlistener。然后,如果用户名存在,您可以从此方法返回
null
(重新加载触发该操作的页面)。下面是一个例子:

在facelet中:

<h:commandButton action="#{testBean.doAction}" value="and... Action"/>

您可以在faces-config.xml文件中定义导航案例。这将允许您根据bean的返回值将用户重定向到给定页面

在下面的示例中,根据“myMethod()”的返回值,suer被重定向到两个页面中的一个


/index.xhtml
#{myBean.myMethod()}
真的
/correct.xhtml
#{myBean.myMethod()}
假的
/error.xhtml
简介 您可以这样做,但是JSF ajax/action/listener方法在语义上是错误的。如果表单中有错误的输入值,实际上您不想在JSF生命周期中走那么远。您希望JSF生命周期在JSF验证阶段之后停止

您希望使用JSR303 Bean验证注释(
@NotNull
和friends)和/或约束验证器,或者使用JSF
验证器(
required=“true”
,等等)来代替。它将在JSF验证阶段被正确调用。这样,当验证失败时,模型值不会更新,业务操作也不会被调用,您将保持在相同的页面/视图中

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

对于这两种方法,我都将演示如何创建一个检查用户名唯一性的自定义验证器

自定义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 {};
}
最后在模型中使用它,如下所示:

@Username
private String username;
自定义JSF验证器 另一种方法是使用自定义JSF验证器。只需实现JSF接口:

@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
注释,但在即将推出的JSF2.3之前,它不支持
@EJB
@Inject
。另请参见。

是的,您可以。您可以在action listener方法中执行验证,如果自定义验证失败,则添加faces消息,然后在返回之前调用
FacesContext.validationFailed()


这个解决方案的唯一问题是,它发生在JSF验证和bean验证之后。即,在验证阶段之后。如果您有多个操作侦听器,比如listener1和listener2:如果您在listener1中的自定义验证失败,它将继续执行listener2。但毕竟,AJAX响应中会出现validationFailed。

如果您想向最终用户提供反馈:

xhtml:

    <p:commandButton value="Go" process="@this" action="#{myBean.checkEntity()}" oncomplete="if(args.validationFailed){PF('widgetOldInfoNotice').show();}"/>

    <p:confirmDialog id="dialogOldInfoNotice" header="NOTICE" severity="alert" widgetVar="widgetOldInfoNotice">
    -- feedback message--
<p:button value="Ok" onclick="PF('widgetOldInfoNotice').hide();"/>
    </p:confirmDialog>

我认为你不应该首先重定向到另一个页面,除非用户名是有效的。谢谢BalusC。这个验证器是在bean验证进行检查之前还是之后调用,或者没有指定顺序?JSF验证在bean验证之前执行。但是如果该值为
null
或空,那么除了
required
之外的JSF验证将不会执行。因此,如果您的
@NotNull
没有
required=“true”
,那么它将首先执行。但是如果它不是空的,并且您有一个例如
@模式
,那么JSF验证器将首先被调用。但是我能不能不仅仅使用普通的jsf验证器,而且只使用bean验证来验证属性?如果它是有效的,那么我可以检查数据库。我尝试了Validator类的validateProperty方法,但我无法让它正常工作,因为它要求组和其他我不理解的语义。如果这是在actionListener中完成的,则需要确保action方法检查
facesContext.isValidationFailed()
继续。这里的问题是向最终用户提供正确的反馈。
@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" />
    <p:commandButton value="Go" process="@this" action="#{myBean.checkEntity()}" oncomplete="if(args.validationFailed){PF('widgetOldInfoNotice').show();}"/>

    <p:confirmDialog id="dialogOldInfoNotice" header="NOTICE" severity="alert" widgetVar="widgetOldInfoNotice">
    -- feedback message--
<p:button value="Ok" onclick="PF('widgetOldInfoNotice').hide();"/>
    </p:confirmDialog>
public String checkEntity() {
    if (!dao.whateverActionToValidateEntity(selectedEntity)) {
        FacesContext context = FacesContext.getCurrentInstance();
        context.validationFailed();
        return "";
    }
    return "myPage.xhtml";
}