在会话过期之前调用方法

2022-09-03 06:17:33

我的 Web 应用有登录用户。存在超时。在会话过期之前,我想执行一个方法来清理一些锁。

我已经实现了一个,但是一旦我到达会话已经消失了,我需要从中获取一些数据,所以我想在会话实际过期之前执行一个方法(它需要会话处于活动状态并能够访问)。sessionListenerpublic 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());
    }
}

但是我得到了,因为要么是空的,要么是返回空的NullPointerExceptionFacesContext.getCurrentInstance().getApplication()getCurrentInstancegetApplication


答案 1

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

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() );
    }
}

答案 2

一个更优雅的解决方案:

只需向会话 Bean 添加注释即可!如果会话将被销毁,它将事先在所有会话Beans上调用PreDestroy,在那里您可以注销和所有内容!@PreDestroy

虽然这目前不适用于许多应用程序服务器,但似乎是JSF规范的一个不清楚的部分。因此,使用接受的答案(HttpSessionBindingListener)将是必要的,直到@PreDestroy在所有服务器上都能按预期工作。


推荐