2012-08-05 63 views
1

在用户关闭浏览器并走开的情况下,我想在会话超时时记录日志。例如,作为系统引起的注销而不是用户请求(我已经有工作和测试的代码来记录用户请求的注销)。如果浏览器关闭,JSF会话过期阶段监听器

由于用户没有主动提交请求(特别是如果它只是现在未使用的会话在服务器上超时的问题),我不认为过滤器是可能的。这可以通过阶段监听器完成吗?如果是的话,你能提供一些见解或骨架,或至少指出我如何做到这一点的正确方向。

我的理解是,服务器上的会话仍然是活动的,直到它超时或其他一些机制使其无效。因此,我假设阶段侦听器也将能够告诉您是否作为登录方法的一部分,在用户以全新视图,其他机器等重新登录之前终止任何现有会话。

我是确定研究,但至少要开始时指向正确的方向。 :)

在第二个注意:是否有可能区分会话超时和视图过期?


想我会后我结束了基于该建议的解决方案:

public class ElsSoulardSessionListener implements HttpSessionListener { 

    @EJB 
    private SessionLogger sessionLogger = new SessionLogger(); 
    private SessionLogDTO sessionData = new SessionLogDTO(); 
    private ElsDateTimeFunctions ts = new ElsDateTimeFunctions(); 
    private static final Logger logger = Logger.getLogger(ElsSoulardSessionListener.class.getSimpleName()); 

    @Override 
    public void sessionCreated(HttpSessionEvent se) { 
     // Nothing to do yet 
    } 

    @Override 
    public void sessionDestroyed(HttpSessionEvent se) { 
     logger.log(Level.FINE, "SESSION DESTROYED LISTENER"); 

     HttpSession session = se.getSession(); 
     finalizeUserSessionLog(session); 
    } 

    /** 
    * Utility method to finalize user's session log entry. Returns 
    * early if the session log isn't found or more than one is returned. 
    * @param session 
    */ 
    private void finalizeUserSessionLog(HttpSession session) { 

     String sessionId = session.getId(); 
     LogoutReasonType logoutReason = (LogoutReasonType) session.getAttribute("logoutreason"); 

     if (logoutReason == null) { 
      logoutReason = LogoutReasonType.SESSION_TIMEOUT; 
     } 

     try { 
      sessionData = sessionLogger.findBySessionId(sessionId); 
     } catch (NonexistentEntityException | UnexpectedResultSetSizeException ex) { 
      logger.log(Level.WARNING, " sessionDestroyed ", ex); 
      return; 
     } 

     Calendar now = ts.getUtcDateTimeAsCalendar(); 
     sessionData.setLogoutTimestamp(now); 
     sessionData.setLogoutReason(logoutReason); 
     sessionLogger.update(sessionData); 

    } 
} 
+0

您可以使用[HttpSessionListener](http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpSessionListener.html )来处理会话更改。 – 2012-08-05 17:03:11

回答

2

如果这有助于你...

在我们的应用已经扩展HttpSessionListener并使用sessionDestroyed方法记录会话超时事件。

,并注册了相同的web.xml

<listener> 
    <listener-class> 
     com.ourpackage.OurHttpSessionListener 
    </listener-class> 
</listener> 
+0

好吧,我以为我不能将ejbs注入到听众中,但是它确实在调用managedbeans,然后无法正确调用我的ejbs ......真的不问。 :)我只是做了我所需要的东西,它不是直接从听众那里注入,包括注入我的loggingservice ejb,它像一个魅力一样工作。尝试新事物的乐趣。谢谢。 – BillR 2012-08-07 02:50:46

0

我相信,你只能通过ServletFilters赶上servlet容器的事件。在servlet请求之后,PhaseListener只存在于JSF“会话”中。检查JSF生命周期以确保。之后,您可以创建另一个请求以使JSF中的“会话”失效