【问题标题】:@ViewScoped calls @PostConstruct on every postback request@ViewScoped 在每个回发请求上调用 @PostConstruct
【发布时间】:2011-07-29 08:20:54
【问题描述】:

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

understood 认为 @ViewScoped@RequestScoped 长,并且不应该在每次请求时都重新构建它。仅在通过 GET 重新加载完整页面后。

【问题讨论】:

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


    【解决方案1】:

    换句话说,您的@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 (issue 1496) 中的错误引起的。另见Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF

      这已在 Mojarra 版本 2.1.18 中修复。如果您无法升级到较新的版本,解决方法是在web.xml 中禁用部分状态保存,另见JSTL in JSF2 Facelets... makes sense?

       <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 属性,或者应该寻求替代方案。另见How does the 'binding' attribute work in JSF? When and how should it be used?

    2. 您使用的是 Mojarra 2.2.0,只有该版本在维护 2.2.1 中已修复的视图范围方面存在(但未知)错误,另请参见 issue 2916。解决方案是升级到新版本。

    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

      您需要确保您拥有以下任一构造并且不要混合使用它们,另请参阅@ViewScoped bean recreated on every postback request when using JSF 2.2

       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. 视图(意外地?)通过&lt;f:view transient="true"&gt; 标记为瞬态。这基本上开启了“无状态 JSF”,这是自 Mojarra 2.1.19 以来的新功能。因此,JSF 视图根本不会保存在 JSF 状态中,逻辑结果是所有引用的视图范围 bean 不能再与 JSF 视图相关联。另见What is the usefulness of statelessness in JSF?

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

    6. Web 应用程序的运行时类路径被多个不同版本的 JSF API 或 impl 相关类污染。这会导致 JSF 视图状态的标识符/标记出现损坏/不匹配。您需要确保 webapp 的 /WEB-INF/lib 中没有多个 JSF API JAR 文件。如果您使用 Maven,请确保将服务器提供的库标记为 &lt;scope&gt;provided&lt;/scope&gt;。另请参阅our JSF wiki page 中的“安装 JSF”部分以及此相关问题的答案:How to properly install and configure JSF libraries via Maven?

    7. 当您使用 PrimeFaces &lt;p:dialog&gt; 时,请确保 &lt;p:dialog&gt; 有自己的 &lt;h:form&gt;,并且它没有嵌套在另一个 &lt;h:form&gt; 中。另见p:fileUpload inside p:dialog losing @ViewScoped values

    8. 当您将 PrimeFaces FileUploadFilter 与 PrettyFaces 结合使用时,请确保 FileUploadFilter 也在 PrettyFaces 重写/转发的请求上运行。另见ViewScoped bean rebuilt when FileUploadListener called using PrettyFacesHow to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null / throws an error / not usable

    9. 当您使用 PrettyFaces 时,将 CSS/JS/图像资源重定向到与 @ViewScoped bean 绑定的 JSF 页面的错误配置的重写规则也会产生误导行为。另见CDI ViewScope & PrettyFaces: Multiple calls to @PostConstruct (JSF 2.2)

    【讨论】:

    • 你的正确。我在我的页面上使用 c:foreach 的网站添加了一个功能。难怪我之前没有注意到。问题是 ui:repeat 在我的情况下不起作用。 primefaces.prime.com.tr/forum/viewtopic.php?f=3&t=59 部分状态保存是否适用于 c:for each?
    • 很遗憾,不,禁用部分状态保存并不能解决 JSTL 标签的问题。然而,这种特殊情况很棘手。从理论上讲,您可以使用一个完整的组件来解决这个问题,例如&lt;p:tabs&gt; 接受集合而不是 &lt;ui:repeat&gt;&lt;p:tab&gt;。我相信这曾经是作为 PrimeFaces 的功能请求发布的,不确定 Cagatay 对它做了什么。
    • PARTIAL_STATE_SAVING 改变了我的生活
    • @Danijel:只使用rendered 属性?另见stackoverflow.com/a/4870557stackoverflow.com/a/15947948。或者,只需升级到 Mojarra 2.1.18 或更高版本。从那以后它就被修复了。
    • 谢谢。使用 ...非空 bean.list}">
    猜你喜欢
    • 2011-02-20
    • 2014-10-17
    • 2015-12-03
    • 2014-03-21
    • 2013-12-13
    • 2011-02-17
    • 1970-01-01
    相关资源
    最近更新 更多