java 在会话到期之前调用方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3943368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:04:30  来源:igfitidea点击:

Invoke method just before session expires

javajsfservlets

提问by pakore

My webapp has users who login. There is a timeout. Before the session expires, I would like to execute a method to cleanup some locks.

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

I've implemented a sessionListenerbut once I reach public void sessionDestroyed(HttpSessionEvent event)the session is already gone and I need some data from it, so I would like to execute a method (which needs the session alive and be able to access FacesConfig.getCurrentInstance()) before the session is actually expired.

我已经实现了一个sessionListener但是一旦我到达public void sessionDestroyed(HttpSessionEvent event)会话已经消失了,我需要从中获取一些数据,所以我想FacesConfig.getCurrentInstance()在会话实际过期之前执行一个方法(需要会话处于活动状态并且能够访问)。

How can I do that? Any ideas? This is my Session Listener:

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

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

But I'm getting NullPointerExceptionat FacesContext.getCurrentInstance().getApplication()because either getCurrentInstanceis null or getApplicationreturns null

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

回答by stacker

You can achieve that by implementing a HttpSessionBindingListener you need to register a session which holds a lock by calling registerSession(the string "sessionBindingListener" may not be changed). The container will callback the valueUnbound()method after the session timed out and beforethe session is destroyed.

您可以通过实现 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() );
    }
}

回答by Falco

One more elegant solution:

一种更优雅的解决方案:

Just add a @PreDestroyAnnotation to a Session-Bean! If the Session is going to be destroyed, it will call PreDestroy on all SessionBeans beforehand, there you can logout and everything!

只需@PreDestroy在 Session-Bean 中添加注解即可!如果 Session 将要被销毁,它会预先在所有 SessionBeans 上调用 PreDestroy,在那里你可以注销和一切!

Although this doesn't currently work with many ApplicationServers, seems to be an unclear segment of the JSF Specification. So going with the accepted answer (HttpSessionBindingListener) will be necessary, until @PreDestroy will work as intended on all servers.

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