f:JSF 2.3中的validateWholeBean

时间:2016-04-29 13:50:06

标签: jsf jsf-2.3

我想用JSF 2.3实现f:validateWholeBean。 我试图用Mojarra 2.3.0-m05和Tomcat 8:

实现这个例子
<h:form>
    <h:panelGroup>
        <h:inputSecret id="passwd" value="#{bean.dataList['passwd']}">
            <f:ajax event="blur" render="passwdvalidator" />
        </h:inputSecret>
        <h:message id="passwdvalidator" for="passwd" />
    </h:panelGroup>

    <h:panelGroup>Confirm Password</h:panelGroup>
    <h:panelGroup>
        <h:inputSecret id="confurmpasswd" value="#{bean.dataList['passwd']}">
            <f:ajax event="blur" render="confurmpasswdvalidator" />
        </h:inputSecret>
        <h:message id="confurmpasswdvalidator" for="confurmpasswd" />
    </h:panelGroup>
    <h:commandButton action="#{bean.submit}">
        <f:ajax render="@form" execute="@form"></f:ajax>
    </h:commandButton>                          

    <f:validateWholeBean  value="#{contactBean}" validationGroups="validateBean.ContactGroup" />
</h:form>

自定义验证器

@Named
@ViewScoped
public class NewAccountValidator implements Validator, Serializable
{
    @Override
    public void validate(FacesContext fc, UIComponent uic, Object o) throws ValidatorException
    {
        // not used
    }

    public void validatePasswords(FacesContext context, UIComponent component, Object value)
    {
        String l;
        String s = value.toString().trim();

        if (s != null)
        {
            // compare passwords
        }
        else
        {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_INFO,
                s.isEmpty() ? "  This field cannot be empty!" : "  '" + s + "' is not a number!", null));
        }
    }
}

使用f:validateWholeBean和自定义JSF验证器实现解决方案的正确方法是什么?

1 个答案:

答案 0 :(得分:4)

你不应该实施&#34;标准&#34;验证器,但ConstraintValidator

您可以在Arjan Tijms Weblog找到一个示例:

<h:form>
    <h:inputText value="#{indexBean.foo}">
        <f:validateBean validationGroups="javax.validation.groups.Default,java.util.RandomAccess"/>
    </h:inputText>
    <h:inputText value="#{indexBean.bar}">
        <f:validateBean validationGroups="javax.validation.groups.Default,java.util.RandomAccess"/>
    </h:inputText>

    <f:validateWholeBean value="#{indexBean}" validationGroups="java.util.RandomAccess"/>

    <h:commandButton value="submit"/>
</h:form>

使用支持bean:

@Named
@RequestScoped
@ValidIndexBean(groups = java.util.RandomAccess.class)
public class IndexBean implements ConstraintValidator<ValidIndexBean, IndexBean> {

    @Constraint(validatedBy = IndexBean.class)
    @Documented
    @Target(TYPE)
    @Retention(RUNTIME)
    public @interface ValidIndexBean {
        String message() default "Invalid Bean";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }

    @Inject // @EJB
    private PersistenceService service;

    @NotNull
    private String foo;

    @NotNull
    private String bar;

    @Override
    public void initialize(ValidIndexBean constraintAnnotation) {
        //
    }

    @Override
    public boolean isValid(IndexBean other, ConstraintValidatorContext context) {
        // return other.getFoo().equals(other.getBar());

        return service.query("select count(p) from Person p where p.foo like ?1 and p.bar like ?2", other.getFoo(), other.getBar()) == 0;
    }

    ...
}

回答评论:

  • 这是一个普通的bean,所以是的,它可以是@ViewScoped。
  • 然后你应该创建多个验证器:使一个验证器执行多个逻辑是一种不好的做法。

无关:

正如我从您发布的代码中看到的那样,您误解了&#34; classic&#34;验证器,使其成为ManagedBean(CDI风格),但这是&#34; plain&#34;使用JSF验证器/转换器。

我认为你没有使用验证器,而是使用验证方法

A&#34;经典&#34;验证器应该看起来像(见here):

@FacesValidator("usernameValidator")
public class UsernameValidator implements Validator, Serializable
{
    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException
    {
        // you should use THIS method to validate a single Component's Value

        if(query("select count(*) from user where username = '?'", String.valueOf(value)) > 0)
        {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "invalid username"));
        }
    }
}

应该像:

一样使用
<h:inputText value="#{someBean.username}" validator="usernameValidator" />

这样:

  1. &#34;经典&#34;面部验证器用于验证一个组件的值
  2. 他们不应成为@ManagedBean或@Named
  3. 引用名称{validator="usernameValidator"而不使用EL表达式validator="#{usernameValidator}"
  4. 但是,验证器/转换器的最佳做法是“专业化”#34;它们应该执行单一的验证逻辑。

    如果您需要验证组件值,即日期,必须为非空大于01/01/1970,那么您需要两个专业验证员。