我在弄清楚如何正确处理JSF中会话的自动销毁时遇到了麻烦。当然,此时,会话被容器失效,导致@PreDestroy方法也在会话作用域的bean上被调用。
在一些会话作用域bean的PreDestroy中,我们取消了一些侦听器的注册,如下所示:
@PreDestroy
public void destroy() {
getWS().removeLanguageChangeListener(this);
}
然而,getWS()方法实际上试图获取对另一个会话作用域bean的引用,但是失败了,因为FacesContext.getCurrentInstance()
返回null。根据Ryan Lubke的说法,后者似乎是正常的JSF行为:
我们在这里严格遵守规范。我不确定这样假设是否安全FacesContext将在所有的@PreDestroy情况下可用。考虑会话作用域的bean。该会话可能会超时由于不活动导致的容器。facecontext不能在。
对我来说很好,但是如何确保所有对象都被正确清除呢?它是坏的做法,以消除自我作为听众在PreDestroy?或者我们只需要为请求/视图作用域的bean做这个,因为它们比WS(来自getWS()
)的会话作用域的时间要短?
请注意,我在Tomcat7上得到了这个行为,但我希望这个问题在每个容器上都发生。
我认为会话bean是在servlet容器上的专用线程中清理的,因此在FacesContext(与JSF Request相关联)之外。您可以使用HttpSessionListener
来克服这个问题并清理会话资源。比如:
@WebListener
public class LifetimeHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(final HttpSessionEvent e) {
// create some instance here and save it in HttpSession map
HttpSession session = e.getSession();
session.setAttribute("some_key", someInstance);
// or elsewhere in JSF context:
// FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("some_key", someInstance);
}
@Override
public void sessionDestroyed(final HttpSessionEvent e) {
// get resources and cleanup them here
HttpSession session = e.getSession();
Object someInstance = session.getAttribute("some_key");
}
}
希望对大家有所帮助