我想用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验证器实现解决方案的正确方法是什么?
答案 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;
}
...
}
正如我从您发布的代码中看到的那样,您误解了&#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" />
这样:
validator="usernameValidator"
而不使用EL表达式validator="#{usernameValidator}"
)但是,验证器/转换器的最佳做法是“专业化”#34;它们应该执行单一的验证逻辑。
如果您需要验证组件值,即日期,必须为非空且大于01/01/1970,那么您需要两个专业验证员。