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

发布于 2024-10-30 06:31:17 字数 327 浏览 0 评论 0 原文

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

了解 @ViewScoped 更长比 @RequestScoped 并且不应该在每个请求上重建它。仅在通过 GET 重新加载完整页面后。

This doesn't seem right. I was doing some cleanup of my code and I just noticed this. Every ajax request is firing the constructor and @PostConstruct of my @ViewScoped bean. Even a simple database pagination is firing it.

I understood that @ViewScoped is longer than @RequestScoped and that it shouldn't be reconstructed on every request. Only after a complete page reload by GET.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁与争疯 2024-11-06 06:31:17

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

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

  1. 您使用的是 Mojarra 2.1.17 或更早版本,并且视图包含 EL 表达式,该表达式将视图作用域 bean 属性绑定到标记属性,该标记属性在 查看构建时间。例如 JSTL 等或 JSF 等。这是由 Mojarra 中的错误引起(问题 1496)。另请参阅 为什么 @PostConstruct 回调会触发每次即使bean是@ViewScoped? JSF

    此问题已在 Mojarra 2.1.18 版本中修复。如果您无法升级到较新的版本,解决方法是在 web.xml 中禁用部分状态保存,另请参阅JSF2 Facelets 中的 JSTL...有意义吗?

     <上下文参数>
         <参数名称>javax.faces.PARTIAL_STATE_SAVING
         <参数值> false
     
    

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

     <上下文参数>
         <参数名称>javax.faces.FULL_STATE_SAVING_VIEW_IDS
         /foo.xhtml;/bar.xhtml;/folder/baz.xhtml;
     
    

    值得一提的是,将 JSF 组件的 idbinding 属性的值绑定到视图作用域 bean 属性是一种不好的做法。这些确实应该绑定到请求范围的 bean 属性,或者应该寻找替代方案。另请参阅 JSF 中的“绑定”属性如何工作?何时以及如何使用它?

  2. 您使用的是 Mojarra 2.2.0,只有该版本在维护视图范围方面存在(尚不清楚)错误,该错误已在 2.2.1 中修复,另请参阅问题 2916。解决方案是升级到较新的版本。

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

    您需要确保具有以下任一构造并且不要混合它们,另请参阅使用 JSF 2.2 时,在每个回发请求上重新创建 @ViewScoped bean

     import javax.faces.bean.ManagedBean;
     导入 javax.faces.bean.ViewScoped;
    
     @ManagedBean
     @ViewScoped
     公共类 CorrectJSFViewScopedBean 实现可序列化 {
    
     import javax.inject.Named;
     导入 javax.faces.view.ViewScoped;
    
     @命名
     @ViewScoped
     公共类 CorrectCDIViewScopedBean 实现可序列化 {
    
  4. 该视图(不小心?)通过 标记为瞬态。这基本上开启了“无状态 JSF”,这是自 Mojarra 2.1.19 以来的新功能。因此,JSF 视图根本不会保存在 JSF 状态中,逻辑结果是所有引用的视图作用域 bean 不能再与 JSF 视图关联。另请参阅 JSF 中无状态性有什么用处?< /p>

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

  6. Web 应用程序的运行时类路径被多个不同版本的 JSF API 或 impl 相关类污染。这会导致 JSF 视图状态的标识符/标记损坏/不匹配。您需要确保 web 应用程序的 /WEB-INF/lib 中没有多个 JSF API JAR 文件。如果您使用 Maven,请仔细确保将服务器提供的库标记为 provided。另请参阅我们的 JSF wiki 页面中的“安装 JSF”部分以及此相关问题的答案:如何通过 Maven 正确安装和配置 JSF 库? .

  7. 当您使用 PrimeFaces 时,请确保 有自己的 并且它没有嵌套在另一个 中。另请参阅p:fileUpload 在 p:dialog 内丢失 @ViewScoped 值

  8. 当您将 PrimeFaces FileUploadFilter 与 PrettyFaces 结合使用时,请确保 FileUploadFilter 也在 PrettyFaces 重写/转发的请求上运行。另请参阅 使用 PrettyFaces 调用 FileUploadListener 时重建 ViewScoped bean 和 < a href="https://stackoverflow.com/questions/8875818/how-to-use-primefaces-pfileupload-listener-method-is-never-invoked-or-uploaded">如何使用 PrimeFaces p:fileUpload?监听器方法永远不会被调用或 UploadedFile 为空/抛出错误/不可用。

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

In other words, your @ViewScoped bean behaves like a @RequestScoped bean. It's been recreated from scratch on every postback request. There are many possible causes for this, most of which boils down that the associated JSF view is not available anymore in the JSF state which in turn is by default associated with the HTTP session.

Provided that you can assure that the HTTP session itself is not the root cause of the problem, i.e. when @SessionScoped works absolutely fine, then walk through the below list of possible causes. Otherwise, if the HTTP session itself is also trashed and recreated on every single request, then you need to take a step back and look at session cookie and server configuration. Any cause related to a broken HTTP session is at least beyond the context of JSF.

  1. You're using Mojarra 2.1.17 or older, and the view contains EL expressions which bind a view scoped bean property to a tag attribute which is evaluated during view build time. Examples are JSTL <c:if>, <c:forEach>, etc or JSF <ui:include>, <x:someComponent id="#{...}", <x:someComponent binding="#{...}">, etc. This is caused by a bug in Mojarra (issue 1496). See also Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF

    This is already fixed in Mojarra version 2.1.18. If you can't upgrade to a newer version, the workaround is to disable partial state saving as below in web.xml, see also JSTL in JSF2 Facelets... makes sense?

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

    Or when you want to target a specific set of JSF views only:

     <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>
    

    Important to mention is that binding the value of JSF component's id or binding attribute to a view scoped bean property is a bad practice. Those should really be bound to a request scoped bean property, or an alternative should be sought. See also How does the 'binding' attribute work in JSF? When and how should it be used?

  2. You're using Mojarra 2.2.0, only that version has a (yet unknown) bug in maintaining the view scope which is already fixed in 2.2.1, see also issue 2916. Solution is to upgrade to a newer version.

  3. The @ViewScoped annotation is imported from the wrong package. JSF offers two @ViewScoped annotations, one from javax.faces.bean package for JSF managed beans annotated with @ManagedBean, and another one from javax.faces.view package for CDI managed beans annotated with @Named. When the bean scope annotation does not match the bean management annotation, then the actual bean scope will become the bean management framework's default scope, which is @RequestScoped in JSF managed beans and @Dependent in CDI managed beans.

    You need to ensure that you have either of the following constructs and don't mix them, see also @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. The view is (accidentally?) marked transient via <f:view transient="true">. This basically turns on "stateless JSF", which is new since Mojarra 2.1.19. Hereby the JSF view simply won't be saved in the JSF state at all and logical consequence is that all referenced view scoped beans can't be associated with the JSF view anymore. See also What is the usefulness of statelessness in JSF?

  5. The web application is configured with com.sun.faces.enableRestoreView11Compatibility context param set to true in an incorrect attempt to "avoid" ViewExpiredException. With this context param, the ViewExpiredException will never be thrown, but the view (and all associated view scoped beans) will just be recreated from scratch. However, if that happens on every request, then this approach actually hides another problem: the views expire way too soon. This indicates a possible problem in maintaining the JSF view states and/or the HTTP session. How to solve/configure that properly, head to javax.faces.application.ViewExpiredException: View could not be restored.

  6. The web application's runtime classpath is polluted with multiple different versioned JSF API or impl related classes. This causes a corruption/mismatch in the identifiers/markers for the JSF view state. You need to make sure you don't have multiple JSF API JAR files in webapp's /WEB-INF/lib. In case you're using Maven, make carefully sure that you mark server-provided libraries as <scope>provided</scope>. See also "Installing JSF" section in our JSF wiki page and the answer to this related question: How to properly install and configure JSF libraries via Maven?.

  7. When you're using PrimeFaces <p:dialog>, then make sure that the <p:dialog> has its own <h:form> and that it is not nested in another <h:form>. See also p:fileUpload inside p:dialog losing @ViewScoped values.

  8. When you're combining PrimeFaces FileUploadFilter with PrettyFaces, then make sure that the FileUploadFilter also runs on PrettyFaces-rewritten/forwarded requests. See also ViewScoped bean rebuilt when FileUploadListener called using PrettyFaces and How to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null / throws an error / not usable.

  9. When you're using PrettyFaces, a badly configured rewrite rule which redirects CSS/JS/image resources to a JSF page tied to a @ViewScoped bean will also give misleading behavior. See also CDI ViewScope & PrettyFaces: Multiple calls to @PostConstruct (JSF 2.2).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文