我想f:validateWholeBean
用JSF 2.3 实施。我尝试使用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>
Run Code Online (Sandbox Code Playgroud)
自定义验证器
@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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用f:validateWholeBean
自定义JSF验证程序实现解决方案的正确方法是什么?
您不应实现“标准”验证器,而应实现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>
Run Code Online (Sandbox Code Playgroud)
与支持豆:
@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;
}
...
}
Run Code Online (Sandbox Code Playgroud)
从发布的代码中可以看到,您误解了“经典”验证器的使用,使其成为ManagedBean(带有CDI风格),但这不是 JSF验证器/转换器的“普通”用法。
我想您不是在使用验证器,而是在使用验证方法。
“经典”验证器应如下所示(请参见此处):
@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"));
}
}
}
Run Code Online (Sandbox Code Playgroud)
并应按以下方式使用:
<h:inputText value="#{someBean.username}" validator="usernameValidator" />
Run Code Online (Sandbox Code Playgroud)
所以:
validator="usernameValidator"
不使用EL表达式validator="#{usernameValidator}"
)但是,“验证器/转换器”被“专业化”是最佳实践:它们应该执行单个验证逻辑。
如果您需要验证必须为非空且大于01/01/1970 的组件值(即Date),则需要两个专门的验证器。