在会话超时时删除JSF托管bean

时间:2015-05-18 08:59:10

标签: jsf session

我在如何正确处理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上遇到此行为,但我预计每个容器都会出现此问题。

1 个答案:

答案 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");
}
}

希望这对你有所帮助