4

如果发生 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 注释的调用方法的顺序?

4

2 回答 2

4

事实上,我的任务很普通:有一个带有搜索功能的页面。
如果搜索成功且没有错误,则应显示结果,但如果发生验证错误(在下一次搜索期间),则不应显示先前的结果(但它是可见的,这是一个问题)。

我的计划如下:使用 facesContext.isValidationFailed() 检查 initialize() 方法中的验证失败,如果为真,则隐藏(删除)以前的搜索结果:

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:validator 确实按预期设置 facesContext.validationFailed() )

因此有必要手动设置上下文失败:

@AssertTrue(message = "Some error message")
public boolean isValidateSomeField() {
    if(!validate(getSomeFieldValue())) {
        FacesContext.getCurrentInstance().validationFailed();
        return false;
    }
    return true;
}

但是由于如果验证失败,如何在验证阶段之后签入?我意识到问题可以更容易地解决!只是用几行包装:

<h:panelGroup rendered="#{!facesContext.validationFailed}">
    ...block not to show if validation errors occur...
</h:panelGroup>

并且不需要使用注解 bean 验证和一些 initialize() 方法!

于 2012-10-15T20:50:27.860 回答
3

如果在 JSF 验证阶段抛出了验证异常,那么所有提交的表单值都不会应用于模型。此外,不会调用在调用应用程序 JSF 阶段执行的调用事件。但是您确实注意到,渲染仍然会发生,并且任何需要渲染或更新的组件仍然会这样做。

理论上,如果这些提交中的任何一个无效,这应该足以回滚大多数用户提交,但是有一些边缘情况需要进行额外的清理。但是,我敦促您仔细评估最初导致您实现此需求的设计决策,因为可能有更好的方法来满足您的业务需求而不必求助于此。

话虽如此,我将执行一个 Pre Render 事件,该事件将在每次回发时执行并检查某些验证并执行必要的业务和表示逻辑。

<f:event listener="#{managedBean.initialize()}" type="preRenderView" />
于 2012-10-12T14:01:26.823 回答