为什么过期的@ViewScoped bean 在会话过期之前不会被销毁 [英] Why are expired @ViewScoped beans not destroyed until the session expires
问题描述
我在 GlassFish 4 和 Java 7 上使用 Mojarra 2.2.4.
I'm using Mojarra 2.2.4 on GlassFish 4 with Java 7.
我从 BalusC 对 的回答中了解到在JSF中@ViewScoped bean是如何以及何时被销毁的?,@ViewScoped bean应该在三种情况下被销毁:
As I understand from BalusC's answer to How and when is a @ViewScoped bean destroyed in JSF?, @ViewScoped beans should be destroyed in three cases:
- 具有非空结果的回传
- 会话过期
- 超过会话中的最大逻辑视图数
我的 bean 在前两种情况下被销毁,但在超过最大逻辑视图数时不会.我已经验证了当超过最大值时 bean 会过期(我得到一个 ViewExpiredException),但它们仍然没有销毁,直到会话本身过期.
My beans are being destroyed in the first two cases, but not when the maximum number of logical views is exceeded. I have verified that the beans do expire when the maximum is exceeded (I get a ViewExpiredException), but they are still not destroyed until the session itself expires.
出于内存消耗的原因,我希望在第三种情况下销毁 bean,特别是因为它们在过期后不可用.
For memory consumption reasons, I would like to have the beans destroyed in this third case, especially since they are not usable after expiration.
- 为什么 Bean 过期时没有销毁?
- 这是错误还是预期行为?
- 确保豆子被破坏的干净的解决方法是什么?
- 更新: OmniFaces ViewScoped 注释 会尽快销毁 bean它们会过期.
- Why are the beans not destroyed when they expire?
- Is this a bug or expected behavior?
- What would be a clean work-around to make sure the beans get destroyed?
- Update: OmniFaces ViewScoped annotation destroys beans as soon as they expire.
这是我的豆子:
@javax.inject.Named("sandboxController") @javax.faces.view.ViewScoped public class SandboxController implements Serializable { private static final Logger log = Logger.getLogger(SandboxController.class.getName()); @PostConstruct public void postConstruct() { log.log(Level.INFO, "Constructing SandboxController"); } @PreDestroy public void preDestroy() { log.log(Level.INFO, "Destroying SandboxController"); } public String getData() { return "abcdefg"; } }
和我的 sandbox.xhtml:
and my sandbox.xhtml:
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html"> <body> <h:form> <h:outputText value="#{sandboxController.data}"/> </h:form> </body> </html>
和我的 web.xml 的一部分:
and part of my web.xml:
<context-param> <param-name>com.sun.faces.numberOfLogicalViews</param-name> <param-value>3</param-value> </context-param> <context-param> <param-name>com.sun.faces.numberOfViewsInSession</param-name> <param-value>3</param-value> </context-param>
如果我刷新 sandbox.xhtml 50 次,我会在日志中得到 50 个
INFO: Constructing SandboxController
副本.无论刷新多少次,豆子都不会被破坏.VisualVM 确认这些 bean 仍然被 UIViewRoot 的 ViewMap 引用.在我的全尺寸 bean 中,它保持了相当多的状态,我很快得到一个 OutOfMemoryException.If I refresh the sandbox.xhtml 50 times, I get 50 copies of
INFO: Constructing SandboxController
in the log. The beans are not destroyed, regardless of how many times I refresh. VisualVM confirms that the beans are still referenced by the UIViewRoot's ViewMap. In my full-size bean, which maintains a fair bit of state, I quickly get an OutOfMemoryException.当我手动使会话过期时,我获得了 50 个
INFO: Destroying SandboxController
副本.When I manually expire the session, I get 50 copies of
INFO: Destroying SandboxController
.如果我向 sandbox.xhtml 添加一个提交按钮并在 4 个不同的选项卡中加载它,然后尝试提交第一个,我得到一个 ViewExpiredException,正如预期的那样,但 bean 仍然没有被销毁.
If I add a submit button to sandbox.xhtml and load it up in 4 different tabs, then try to submit the first one, I get a ViewExpiredException, as expected, but the bean is still not destroyed.
如果我改为使用 javax.faces.bean.ManagedBean 和 javax.faces.view.ViewScoped 注释,则行为是相同的.但是,OmniFaces 注释 org.omnifaces.cdi.ViewScoped 可以正常工作.
The behavior is the same if I instead use the javax.faces.bean.ManagedBean and javax.faces.view.ViewScoped annotations. However, the OmniFaces annotation org.omnifaces.cdi.ViewScoped works properly.
我的@ViewScoped bean 正在在会话到期时被销毁,这与 链接的 ViewScoped bean 导致内存泄漏
My @ViewScoped beans are being destroyed on session expiration, unlike problems described in related questions such as Linked ViewScoped beans lead to memory leaks
我不问为什么每个 bean 没有在后续刷新时立即销毁,如此处所质疑:JSF 2.1 ViewScopedBean @PreDestroy 方法未被调用.我想知道为什么即使它们过期了,不再有用,它们仍然没有被销毁,从而继续消耗内存.
I am not asking why each bean is not destroyed immediately on subsequent refresh as questioned here: JSF 2.1 ViewScopedBean @PreDestroy method is not called. I want to know why it is that even when they expire, and are no longer useful, they are still not destroyed, and thus continue consuming memory.
推荐答案
我能够通过使用 OmniFaces @ViewScoped 注释 (
org.omnifaces.cdi.ViewScoped
) 找到一个干净的解决方法而不是标准的@ViewScoped (javax.faces.view.ViewScoped
).I was able to find a clean work-around by using the OmniFaces @ViewScoped annotation (
org.omnifaces.cdi.ViewScoped
) instead of the standard @ViewScoped (javax.faces.view.ViewScoped
).OmniFaces ViewScoped 会在 bean 过期后立即正确销毁它们.
The OmniFaces ViewScoped correctly destroys the beans as soon as they expire.
请参阅此处了解更多详情:http://showcase.omnifaces.org/cdi/ViewScoped
See here for more details: http://showcase.omnifaces.org/cdi/ViewScoped
这篇关于为什么过期的@ViewScoped bean 在会话过期之前不会被销毁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!