我在如何正确处理JSF中会话的自动销毁方面遇到了麻烦。当然,此时会话被容器无效,导致在会话范围的bean上调用@PreDestroy方法。
在某些会话范围内的bean的PreDestroy中,我们取消注册一些侦听器,如下所示:
@PreDestroy
public void destroy() {
getWS().removeLanguageChangeListener(this);
}
但是,getWS()方法实际上尝试获取对另一个会话范围bean的引用,但是失败,因为FacesContext.getCurrentInstance()
返回null。
根据Ryan Lubke的说法,后者似乎是正常的JSF行为:
我们在这里遵守规范。我不确定它是否安全 FacesContext将在所有@PreDestroy案例中可用。 考虑会话范围的bean。会议可以由时间超时 容器由于不活动。 FacesContext无法在 那个时候。
很好,但我应该如何确保所有物品都被正确清除?在PreDestroy中删除self作为监听器是不好的做法吗?
或者我们只需要为请求/视图作用域bean执行此操作,因为它们的生存时间比WS的会话范围(来自getWS()
)长得多吗?
请注意,我在Tomcat7上遇到此行为,但我预计每个容器都会出现此问题。
答案 0 :(得分:1)
我认为会话bean是在servlet容器上的专用线程中清理的,因此不在FacesContext(与JSF请求相关联)之外。您可以使用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");
}
}
希望这对你有所帮助