如果发生jsf验证错误,是否可以执行某些操作(某些清理)?
使用xhtml中的标记验证字段,例如'required =“true”','f:validateRegex pattern =“\ d *”','f:validator validatorId =“someValidator”'。
我需要将托管bean的一些属性字段设置为null(当页面上有任何失败时)。
但是如果验证失败,则JSF进入渲染响应阶段并且不调用托管bean方法。
在这种情况下,也不会调用监听器(使用f:actionListener标签)。
现在我正在考虑使用像@AssertTrue,@ Size等bean注释验证来替换xhtml验证。
然后在一些验证方法中,可以进行清理:
@ManagedBean
class SomeBean {
...
@AssertTrue
public void isClenup() {
cleanup();
}
...
}
但对我来说这似乎不是一个好的解决方案。
另外我注意到用@AssertTrue注释的几个方法是以未定义的顺序调用的。因此,从xhtml验证切换到bean注释验证变得不那么容易了
是否可以定义一些使用@AssertTrue注释的调用方法的顺序?
答案 0 :(得分:4)
实际上我有一个非常普通的任务:有一个带搜索功能的页面
在没有错误的搜索成功时,应显示结果,但如果发生验证错误(在下次搜索期间),则不应显示先前的结果(但它是可见的,这是一个问题)。
我的计划如下:使用facesContext.isValidationFailed()检查initialize()方法中的验证失败,如果为true,则隐藏(删除)以前的搜索结果:
public void initialize() {
FacesContext context = FacesContext.getCurrentInstance();
boolean validationFailed = context.isValidationFailed();
if(validationFailed) {
clearPreviousSearchResult();
}
}
但后来我发现使用bean注释的验证(如@AssertTrue)没有设置facesContext.validationFailed();! 即在此之后
@AssertTrue(message = "Some error message")
public boolean isValidateSomeField() {
return validate(getSomeFieldValue());
}
当失败发生时你得到context.isValidationFailed()== false(尽管我预期为真)
(xhtml验证或验证器或f:验证器按预期设置facesContext.validationFailed())
因此有必要手动设置上下文失败:
@AssertTrue(message = "Some error message")
public boolean isValidateSomeField() {
if(!validate(getSomeFieldValue())) {
FacesContext.getCurrentInstance().validationFailed();
return false;
}
return true;
}
但是由于How to check in after phase of Validations phase if validation has failed?我意识到问题可以更容易解决!只是用几行来包装:
<h:panelGroup rendered="#{!facesContext.validationFailed}">
...block not to show if validation errors occur...
</h:panelGroup>
无需使用注释bean验证和一些initialize()方法!
答案 1 :(得分:3)
如果在JSF验证阶段抛出验证异常,则所有提交的表单值都不会应用于模型。此外,将不会调用在Invoke Application JSF阶段期间执行的任何调用事件。但是您会注意到Render仍然会出现,并且任何需要渲染或更新的组件仍然会这样做。
理论上,如果任何提交的内容无效,这应足以回滚大多数用户提交的内容,但是有一些边缘情况需要进行额外的清理。但是,我建议您首先仔细评估导致您满足这一需求的设计决策,因为有可能有更好的方法来满足您的业务需求,而不必诉诸于此。
话虽如此,我会执行一个Pre Render事件,该事件将在每次回发时执行并检查某些验证并执行必要的业务和表示逻辑。
<f:event listener="#{managedBean.initialize()}" type="preRenderView" />