2010-10-15 58 views
14

我的web應用程序有登錄的用戶。有一個超時。在會話過期之前,我想執行一個方法來清理一些鎖。會話過期前的調用方法

我已經實現了一個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爲空或getApplication返回null

回答

17

您可以通過實現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()); 
    } 
} 
+0

工程就像一個魅力。 +1並被接受。 – pakore 2010-10-15 15:17:26

+0

我把它放在'UserBean'類下,它知道'LockBean'。我已經通過以前的問題實現了這個問題...... BalusC:D,所以我只需要添加'lock.unlock'行並且它工作。謝謝你們。 – pakore 2010-10-15 15:19:29

+0

實現'HttpSessionBindingListener'確實更好。您只需確保在JSF請求期間調用registerSession()(但是,如果ObjectLock已經是會話範圍的託管bean,那麼該方法是無用的 – BalusC 2010-10-15 15:22:36

4

一個更優雅的解決方案:

只需添加一個@PreDestroy註釋到會話Bean的!如果會話將被銷燬,它將事先在所有會話Bean上調用PreDestroy,在那裏您可以註銷並執行所有操作!

儘管目前這種方式並不適用於許多ApplicationServers,但它似乎是JSF規範中不明確的一部分。因此,使用接受的答案(HttpSessionBindingListener)將是必要的,直到@PreDestroy將在所有服務器上按預期工作。