我在WildFly 8.1运行时使用JavaEE 7(JSF 2.2,Bean Validation 1.1 ...)和primefaces 5.1
我想根据按下的按钮使用不同的验证组。与少量约束相关联的保存按钮和与大量约束相关联的提交按钮。
bean验证组似乎是我需要的,但我对Web界面有一些问题。
根据验证模式,我不认为无效输入显示为红色:保存或提交
所以我做了3个接口:
public interface LifeCycleValidation {}
public interface Save extends LifeCycleValidation {}
public interface Submit extends Save {}
我使用BeanVal使用模型对象中的适当组
注释字段@Size(min=3, max = 300, groups = Save.class)
@NotNull(groups = Save.class)
private String title ;
@Size(min = 3, max = 5, groups = Submit.class)
private List<String> keywords ;
我在JSF托管bean中创建了一些方法
private final String formIdPrefix = "bookEditForm:" ;
public void save() {
save(Save.class) ;
}
public void submit() {
save(Submit.class) ;
}
private void save(Class<? extends LifeCycleValidation> groupClass) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory() ;
Validator validator = factory.getValidator();
Set<ConstraintViolation<Book>> violations = validator.validate(this, groupClass);
violations.stream()
.forEach(violation -> addErrorMessage(formIdPrefix+violation.getPropertyPath().toString(), violation.getMessage()));
if(violations.isEmpty()) {
// save
addInfoMessage("","sucess") ;
} else {
addErrorMessage("",violations.size()+" error(s)") ;
}
}
private void addErrorMessage(String id, String msg) {
addMessage(id,FacesMessage.SEVERITY_ERROR,"Error",msg) ;
}
private void addInfoMessage(String id, String msg) {
addMessage(id,FacesMessage.SEVERITY_INFO,"Info",msg) ;
}
private void addMessage(String clientId, FacesMessage.Severity severity, String summary, String detail) {
FacesMessage message = new FacesMessage(severity, summary, detail);
FacesContext.getCurrentInstance().addMessage(clientId, message);
}
如果输入的id对应于属性的路径但输入不是红色,则消息会正确显示
<h:form id="bookEditForm">
<p:messages showDetail="true" showSummary="true"/>
<p:panelGrid columns="3">
<p:outputLabel value="title" for="title"/>
<p:inputText value="#{book.title}" id="title"/>
<p:message showDetail="true" showSummary="true" for="title"/>
<p:outputLabel value="keywords" for="keywords"/>
<p:inputText value="#{book.keywords}" id="keywords" converter="converter.ListString"/>
<p:message showDetail="true" showSummary="true" for="keywords"/>
</p:panelGrid>
<p:commandButton value="save" action="#{book.save()}" update="@form"/>
<p:commandButton value="submit" action="#{book.submit()}" update="@form"/>
</h:form>
(在我的例子中,模型和控制器属于同一类,它只是一个测试)
我使用f:validateBean validationGroups尝试其他解决方案 所以我做了ValidationMode枚举:
public enum ValidationMode {
SAVE(Save.class), SUBMIT(Submit.class);
public final Class<? extends LifeCycleValidation> cl ;
private ValidationMode(Class<? extends LifeCycleValidation> cl) {
this.cl = cl ;
}
}
并将其放在JSF托管bean中:
private ValidationMode validationMode ;
public void setValidationMode(String validationModeTitle) {
this.validationMode = ValidationMode.valueOf(validationModeTitle);
}
public String getValidationGroups() {
if(validationMode==null) {
return ValidationMode.SAVE.cl.getCanonicalName() ;
}
return validationMode.cl.getCanonicalName() ;
}
并尝试在ther commandButton
的actionListener中设置适当的模式 <h:form id="bookEditForm">
<p:messages showDetail="true" showSummary="true"/>
<p:panelGrid columns="3">
<p:outputLabel value="title" for="title"/>
<p:inputText value="#{book.title}" id="title">
<f:validateBean validationGroups="#{book.validationGroups}"/>
</p:inputText>
<p:message showDetail="true" showSummary="true" for="title"/>
<p:outputLabel value="keywords" for="keywords"/>
<p:inputText value="#{book.keywords}" id="keywords" converter="converter.ListString">
<f:validateBean validationGroups="#{book.validationGroups}"/>
</p:inputText>
<p:message showDetail="true" showSummary="true" for="keywords"/>
</p:panelGrid>
<p:commandButton value="save" action="#{book.save()}" actionListener="#{book.setValidationMode('SAVE')}" update="@form"/>
<p:commandButton value="submit" action="#{book.submit()}" actionListener="#{book.setValidationMode('SUBMIT')}" update="@form"/>
</h:form>
但这不起作用
我想编写自己的jsf验证器,但我不知道如何根据正确的组实现验证器验证字段
答案 0 :(得分:0)
我终于找到了一些东西,当一个onmouseover发生时触发了setValidationMode,就像在操作之前设置了验证模式:save或submit被称为
<h:panelGroup layout="span">
<p:ajax event="mouseover" listener="#{book.setValidationMode('SAVE')}"/>
<p:commandButton value="save" action="#{book.save()}" update="@form"/>
</h:panelGroup>
<h:panelGroup layout="span">
<p:ajax event="mouseover" listener="#{book.setValidationMode('SUBMIT')}"/>
<p:commandButton value="submit" action="#{book.submit()}" update="@form"/>
</h:panelGroup>
所以你在控制器中无所事事
private ValidationMode validationMode = ValidationMode.SAVE ;
public void setValidationMode(String validationModeTitle) {
this.validationMode = ValidationMode.valueOf(validationModeTitle);
}
public String getValidationGroups() {
return validationMode.cl.getCanonicalName() ;
}
public void save() {
// save
addInfoMessage("","saved") ;
}
public void submit() {
// submit
addInfoMessage("","submited") ;
}
修改
这是干净完整的MVC解决方案,其中进度条以奖金计算:
观点:
<h:form id="bookEditForm">
<p:progressBar value="#{bookBean.progress}" labelTemplate="{value}%" id="progress"/>
<p:messages showDetail="true" showSummary="true"/>
<p:panelGrid columns="3">
<p:outputLabel value="title" for="title"/>
<p:inputText value="#{bookBean.book.title}" id="title">
<f:validateBean validationGroups="#{bookBean.validationGroups}"/>
</p:inputText>
<p:message showDetail="true" showSummary="true" for="title"/>
<p:outputLabel value="keywords" for="keywords"/>
<p:inputText value="#{bookBean.book.keywords}" id="keywords" converter="converter.ListString">
<f:validateBean validationGroups="#{bookBean.validationGroups}"/>
</p:inputText>
<p:message showDetail="true" showSummary="true" for="keywords"/>
</p:panelGrid>
<h:panelGroup layout="span">
<p:ajax event="mouseover" listener="#{bookBean.setValidationMode('SAVE')}"/>
<p:commandButton value="save" action="#{bookBean.save()}" update="@form"/>
</h:panelGroup>
<h:panelGroup layout="span">
<p:ajax event="mouseover" listener="#{bookBean.setValidationMode('SUBMIT')}"/>
<p:commandButton value="submit" action="#{bookBean.submit()}" update="@form"/>
</h:panelGroup>
</h:form>
控制器:
@Named
@ViewScoped
public class BookBean implements Serializable {
private ValidationMode validationMode = ValidationMode.SAVE;
private Book book ;
public BookView() {
book = new Book() ;
}
public void setValidationMode(String validationModeTitle) {
this.validationMode = ValidationMode.valueOf(validationModeTitle);
}
public String getValidationGroups() {
return validationMode.cl.getCanonicalName() ;
}
public Book getBook() {
return book;
}
public void save() {
// save...
addMessage("",FacesMessage.SEVERITY_INFO,"Success","Infos saved") ;
}
public void submit() {
//submit...
addMessage("",FacesMessage.SEVERITY_INFO,"Success","Infos submitted") ;
}
private void addMessage(String clientId, FacesMessage.Severity severity, String summary, String detail) {
FacesMessage message = new FacesMessage(severity, summary, detail);
FacesContext.getCurrentInstance().addMessage(clientId, message);
}
public int getProgress() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory() ;
Validator validator = factory.getValidator();
int nbConstraints = validator.getConstraintsForClass(Book.class).getConstrainedProperties().size() ;
int nbViolations = validator.validate(book, Submit.class).size();
return 100 - (nbViolations*100) / (nbConstraints) ;
}
}
模特:
public class Book implements Serializable {
@NotNull(groups = Save.class)
@Size(min=1, max = 140, groups = Save.class)
private String title ;
@NotNull(groups = Submit.class)
@Size(min = 3, max = 5, groups = Submit.class)
private List<String> keywords ;
// getters and setters
}
ValidationMode,LifeCycleValidation,Save and Submit与问题中的相同
OmniFaces似乎有一个很好的解决方案: http://showcase.omnifaces.org/validators/validateBean 可能很有趣......