@ViewScoped在每个回发请求上调用@PostConstruct

时间:2011-04-04 17:00:33

标签: jsf jsf-2 constructor view-scope postconstruct

这似乎不对。我正在清理我的代码,我只是注意到了这一点。每个ajax请求都会触发我的@PostConstruct bean的构造函数和@ViewScoped。即使是一个简单的数据库分页也会解雇它。

understood @ViewScoped超过@RequestScoped且不应在每次请求时重建。{{1}}只有在通过GET重新加载完整页面之后。

1 个答案:

答案 0 :(得分:50)

换句话说,您的@ViewScoped bean的行为类似于@RequestScoped bean。它在每次回发请求时都是从头开始重新创建的。造成这种情况的原因有很多种,其中大多数原因归结为JSF状态中的相关JSF视图不再可用,而JSF状态又默认与HTTP会话相关联。

如果您可以确保HTTP会话本身不是问题的根本原因,即当@SessionScoped工作正常时,请查看以下可能原因列表。否则,如果HTTP会话本身也在每个请求上被删除并重新创建,那么您需要退后一步并查看会话cookie和服务器配置。与HTTP会话损坏相关的任何原因至少超出了JSF的上下文。

  1. 您正在使用Mojarra 2.1.17或更早版本,该视图包含EL表达式,它将视图范围的bean属性绑定到在view build time期间评估的标记属性。示例包括JSTL <c:if><c:forEach>等,或JSF <ui:include><x:someComponent id="#{...}"<x:someComponent binding="#{...}">等。这是由Mojarra中的错误引起的({{3 }})。另请参阅issue 1492

    这已在Mojarra 2.1.18版中修复。如果您无法升级到较新版本,则解决方法是在web.xml中禁用部分状态保存,如下所示,另请参阅Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF

    <context-param>
        <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
        <param-value>false</param-value>
    </context-param>
    

    或者,当您只想定位一组特定的JSF视图时:

    <context-param>
        <param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
        <param-value>/foo.xhtml;/bar.xhtml;/folder/baz.xhtml</param-value>
    </context-param>
    

    重要的是,将JSF组件的idbinding属性的值绑定到视图范围的bean属性是一种不好的做法。这些应该真正绑定到请求范围的bean属性,或者应该寻求替代方案。另请参阅JSTL in JSF2 Facelets... makes sense?

  2. 您正在使用Mojarra 2.2.0,只有该版本在维护2.2.1中已修复的视图范围方面存在(但未知)错误,另请参阅How does the 'binding' attribute work in JSF? When and how should it be used?。解决方案是升级到更新版本。

  3. 从错误的包导入@ViewScoped注释。 JSF提供了两个@ViewScoped注释,一个来自javax.faces.bean包,用于使用@ManagedBean注释的JSF托管bean,另一个来自javax.faces.view包,用于注释@Named的CDI托管bean }。当bean范围注释与bean管理批注不匹配时,实际的bean范围将成为bean管理框架的默认范围,即JSF托管bean中的@RequestScoped和CDI托管bean中的@Dependent

    您需要确保拥有以下任一构造,并且不要混用它们,另请参阅issue 2912

    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.ViewScoped;
    
    @ManagedBean
    @ViewScoped
    public class CorrectJSFViewScopedBean implements Serializable {
    

    import javax.inject.Named;
    import javax.faces.view.ViewScoped;
    
    @Named
    @ViewScoped
    public class CorrectCDIViewScopedBean implements Serializable {
    
  4. 视图(意外?)标记为瞬态<f:view transient="true">。这基本上打开了“无状态JSF”,这是自Mojarra 2.1.19以来的新功能。因此,JSF视图根本不会保存在JSF状态中,并且逻辑结果是所有引用的视图范围bean都不能再与JSF视图关联。另请参阅@ViewScoped bean recreated on every postback request when using JSF 2.2

  5. 在错误尝试“避免”com.sun.faces.enableRestoreView11Compatibility的情况下,将true上下文参数设置为ViewExpiredException,将Web应用程序配置为ViewExpiredException。使用此上下文参数,将永远不会抛出/WEB-INF/lib,但是将从头开始重新创建视图(以及所有关联的视图范围bean)。但是,如果每次请求都发生这种情况,那么这种方法实际上隐藏了另一个问题:视图过早过期。这表明维护JSF视图状态和/或HTTP会话可能存在问题。如何正确地解决/配置,前往What is the usefulness of statelessness in JSF?

  6. Web应用程序的运行时类路径受到多个不同版本化的JSF API或impl相关类的污染。这会导致JSF视图状态的标识符/标记损坏/不匹配。您需要确保webapp的<scope>provided</scope>中没有多个JSF API JAR文件。如果您使用的是Maven,请仔细确保将服务器提供的库标记为<p:dialog>。另请参阅javax.faces.application.ViewExpiredException: View could not be restored中的“安装JSF”部分以及相关问题的答案:our JSF wiki page

  7. 当您使用PrimeFaces <p:dialog>时,请确保<h:form>拥有自己的<h:form>并且它不会嵌套在另一个FileUploadFilter中。另请参阅How to properly install and configure JSF libraries via Maven?

  8. 当您将PrimeFaces FileUploadFilter与PrettyFaces合并时,请确保@ViewScoped也可以在PrettyFaces重写/转发的请求上运行。另请参阅p:fileUpload inside p:dialog losing @ViewScoped valuesViewScoped bean rebuilt when FileUploadListener called using PrettyFaces

  9. 当您使用PrettyFaces时,一个配置错误的重写规则会将CSS / JS /图像资源重定向到绑定到{{1}} bean的JSF页面,这也会产生误导性行为。另请参阅How to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null / throws an error / not usable