在会话到期之前调用方法

我的webapp有登录用户。 暂停时间。 在会话到期之前,我想执行一个方法来清理一些锁。

我已经实现了一个sessionListener但是一旦我到达public void sessionDestroyed(HttpSessionEvent event) ,会话就已经消失了,我需要一些来自它的数据,所以我想执行一个方法(需要会话活动并且能够访问FacesConfig.getCurrentInstance() )在会话实际到期之前。

我怎样才能做到这一点? 有任何想法吗? 这是我的会话监听器:

 public class MySessionListener implements HttpSessionListener { private static final Logger log = LoggerFactory.getLogger(MySessionListener.class); public MySessionListener() { } public void sessionCreated(HttpSessionEvent event) { log.debug("Current Session created : " + event.getSession().getId()+ " at "+ new Date()); } public void sessionDestroyed(HttpSessionEvent event) { // get the destroying session... HttpSession session = event.getSession(); prepareLogoutInfoAndLogoutActiveUser(session); log.debug("Current Session destroyed :" + session.getId()+ " Logging out user..."); /* * nobody can reach user data after this point because * session is invalidated already. * So, get the user data from session and save its * logout information before losing it. * User's redirection to the timeout page will be * handled by the SessionTimeoutFilter. */ // Only if needed } /** * Clean your logout operations. */ public void prepareLogoutInfoAndLogoutActiveUser(HttpSession httpSession) { UserBean user = FacesContext.getCurrentInstance().getApplication().evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{user}", UserBean.class); LockBean lock = FacesContext.getCurrentInstance().getApplication().evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{lock}", LockBean.class); lock.unlock(user.getUsername()); log.info("Unlocked examination for user: "+user.getUsername()); } } 

但是我在FacesContext.getCurrentInstance().getApplication()得到NullPointerException ,因为getCurrentInstance为null或getApplication返回null

您可以通过实现HttpSessionBindingListener来实现这一点,您需要通过调用registerSession来注册一个持有锁的会话(字符串“sessionBindingListener”可能不会被更改)。 在会话超时之后和会话销毁之前 ,容器将回调valueUnbound()方法。

 public class ObjectLock implements Serializable,HttpSessionBindingListener { public void valueBound(HttpSessionBindingEvent event) { log.info("valueBound:" + event.getName() + " session:" + event.getSession().getId() ); } public void registerSession() { FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put( "sessionBindingListener", this ); log.info( "registered sessionBindingListener" ); } public void valueUnbound(HttpSessionBindingEvent event) { log.info("valueUnBound:" + event.getName() + " session:" + event.getSession().getId() ); // add you unlock code here: clearLocksForSession( event.getSession().getId() ); } } 

一个更优雅的解决方案

只需将@PreDestroy注释添加到Session-Bean即可! 如果Session将被销毁,它将事先在所有SessionBeans上调用PreDestroy,在那里你可以注销一切!

尽管目前这种方法不适用于许多ApplicationServers,但似乎是JSF规范中不明确的部分。 因此,必须使用已接受的答案(HttpSessionBindingListener),直到@PreDestroy在所有服务器上按预期工作。