不调用JSF 2.1 ViewScopedBean @PreDestroy方法

时间:2011-07-17 20:00:06

标签: jsf-2 tomcat7 myfaces

我在视图Scoped Bean中有一个带有@PreDestroy注释的方法,另一个带有@PostConstruct注释的方法。

每次导航到使用此视图范围bean的页面时,都会正确调用@PostConstruct方法。

但是,当我<h:link/>导航到新页面(不使用此视图范围bean)时,永远不会调用@PreDestroy方法。

我不是在谈论changing manually the url or the end of the session,只是导航案例。

我缺少什么?

提前致谢

2 个答案:

答案 0 :(得分:15)

这是设计的。只有当POST操作导致导航不是对同一视图的回发时(即操作方法没有返回nullvoid),它才会立即停止,但是值得一提的{{ 1}},即使只是空的。)

String生成一个GET链接,该链接不会调用任何POST操作。由于在卸载视图时无法通过(XML)HTTP请求通知服务器端,因此无法通知JSF销毁与视图关联的视图范围bean。在这种情况下,视图范围bean将仅在会话到期或会话中的最大逻辑视图超出(默认值为15)且关联视图按顺序排列时销毁。

如果确实希望通过navigaiton操作来降低视图范围内的bean,那么最好的办法就是通过<h:link>将其作为POST请求,然后通过返回来发出重定向带<h:commandLink>参数的导航结果。但这毕竟不是SEO友好,因为机器人不会索引POST链接。

我毕竟不关心仍在会议中的观点。如果您打算进行一些清理或记录,我会寻找其他方法,具体取决于具体的功能要求。

理论中,HTML DOM ?faces-redirect=true事件是可能的,但这是一个非标准事件,并且未指定浏览器行为,即发送ajax请求时会发生什么在那次活动中。它有时会到来,但有时也不会。 更新:在练习中,这已经在OmniFaces @ViewScoped中实现,因为OmniFaces 2.2在synchronous XHR的帮助下,并且在主要浏览器中运行良好。从版本2.3开始,它甚至在物理上破坏了相关的JSF服务器端视图状态。

答案 1 :(得分:2)

我准备了一个小型NetBeans项目,演示何时在不同的导航案例中发布与JSF2.2 CDI兼容的@ViewScoped bean(javax.faces.view.ViewScoped)进行垃圾收集(适用于Mojarra 2.2.9,Glassfish4,NetBeans8)。 0.2,JDK1.7),可用于download here此处省略了代码,请参阅下载。

处理导航案例并通过此图片汇总结果:

Image showing index page using @ViewSCoped bean with JSF navigation cases to a done landing page

要监视@ViewScoped bean,请使用针对Glassfish的VisualVM(或迷你项目上的内置NetBeans探查器)并过滤包名称'webel.com.jsf'上的Sampler内存堆直方图类视图。下图显示了一个荒谬的66个实例 webel.com.jsf.Jsf22ViewBean经过大量试验h:link,浏览器URL GET和浏览器RELOAD GET后,这些实例不会被垃圾收集(可以使用VisualVM执行GC按钮测试):

enter image description here

相比之下,使用h:commandButton和action方法,将index.xhtml(使用@ViewScoped bean一次用于简单的EL变量读取)导航到done.xhtml(根本不使用bean)表达式或操作字符串导致@ViewScoped bean被释放用于垃圾收集(总是有一个从WeldClientProxy到@ViewScoped bean的引用,当你使用h:commandButton来回导航时,WeldClientProxy从一个可释放的bean移动到下一个)。