未调用JSF 2.1 ViewScopedBean @PreDestroy方法 [英] JSF 2.1 ViewScopedBean @PreDestroy method is not called

查看:137
本文介绍了未调用JSF 2.1 ViewScopedBean @PreDestroy方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在视图Scoped Bean中有一个方法,该方法带有@PreDestroy批注,另一个具有@PostConstruct批注.

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

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

我不是在谈论手动更改网址或会话结束 ,只是一个导航盒.

我想念什么?

预先感谢

解决方案

这是设计使然.仅当POST操作导致导航不是回到同一视图的导航时(即,该操作方法未返回nullvoid,而是一个完全有价值的String)导航键会立即被销毁,即使在以下情况下也是如此:只是空的.)

<h:link>生成一个GET链接,该链接不会调用任何POST操作.由于无法在视图卸载时通过(XML)HTTP请求可靠地通知服务器端,因此无法通知JSF销毁与视图关联的视图作用域Bean.在这种情况下,只有当会话期满或会话中的最大逻辑视图数超过默认值(默认为15个)并且关联的视图是顺序中的第一个视图时,才会破坏视图作用域的bean.

如果您真的想通过导航操作销毁视图作用域的bean,那么最好的选择是由<h:commandLink>使其成为POST请求,并通过返回导航结果来发出重定向使用?faces-redirect=true参数.但这毕竟不是SEO友好的,因为漫游器不会索引POST链接.

我毕竟不关心该视图是否仍在会话中.如果您打算进行一些清理或记录日志,我会根据具体的功能要求寻找其他方法.

理论中,HTML DOM onbeforeunload事件是可能的,但这是非标准事件,并且在此期间发送ajax请求时浏览器的行为未指定事件.它有时会到达,但有时也不会.

更新:在实践中,已在 JSF:Mojarra与.OmniFaces @ViewScoped:调用了@PreDestroy,但是无法对bean进行垃圾收集

I have a method in a view Scoped Bean with the @PreDestroy annotation and another one with the @PostConstruct annotation.

The @PostConstruct method is properly called every time I navigate to the page that uses this view scoped bean.

However, when I navigate to a new page (which doesn't use this view scope bean) by <h:link/>, the @PreDestroy method is never called.

I am not talking about changing manually the url or the end of the session, just of a navigation case.

What I am missing?

Thanks in advance

解决方案

This is by design. It will only be destoyed immediately when a POST action results in a navigation which isn't a postback to the same view (i.e. the action method didn't return null or void, but a fullworthy String, even when just empty).

The <h:link> generates a GET link which doesn't invoke any POST action. As it's not reliably possible to notify the server side by a (XML)HTTP request when the view is unloaded, JSF can't be notified to destroy the view scoped bean associated with the view. In such case, the view scoped bean will then only be destroyed when the session expires or when the max logical views in session has exceeded (the default is 15) and the associated view is the first in order.

If you really want to destoy the view scoped bean by a navigaiton action, then your best bet is to make it a POST request by <h:commandLink> instead and issue a redirect by returning the navigation outcome with ?faces-redirect=true parameter. But this is after all not SEO friendly as bots won't index POST links.

I would after all not care about the view still being in the session. If you intend to do some cleanup or logging, I'd look for alternative ways, depending on the concrete functional requirement.

In theory it would be possible by HTML DOM onbeforeunload event, but this is a non-standard event and the browser behaviour is unspecified as to what happens when you send an ajax request during that event. It will sometimes arrive, but sometimes also not.

Update: in practice, this has been implemented in OmniFaces @ViewScoped since OmniFaces 2.2. Initially with help of synchronous XHR and since OmniFaces 2.6 with help of beacon. It's working quite well in major browsers. Since OmniFaces 2.3 it even immediately destroys the associated JSF server side view state, and since OmniFaces 2.6 it even immediately destroys the physical beans, hereby further reducing unnecessary memory usage. See also among others JSF: Mojarra vs. OmniFaces @ViewScoped: @PreDestroy called but bean can't be garbage collected

这篇关于未调用JSF 2.1 ViewScopedBean @PreDestroy方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆