2015-10-01 139 views
3

在我的Vaadin應用程序中,當「會話超時」消息之後Vaadin不會使會話無效時出現問題。得到這個消息後,用戶有時可以單擊鏈接或刷新頁面並繼續工作,就好像他們仍然被登錄 我使用下列參數:有時,Vaadin不會在「會話超時」消息之後使會話無效

closeIdleSessions=true 
heartbeatInterval=60 
session-timeout=15 

末參數(會話超時)是因爲我沒有從vaadin文檔中得到清楚的結果,它在context.xml(session-timeout = 900)和web.xml(session-config/session-timeout = 15)中設置,是否有這樣的vaadin servlet參數。

有人問題嗎?

UPDATE 1:固定參數片段。

UPDATE 2SessionDestroyListener.sessionDestroy在出現Session expired消息時未觸發。

UPDATE 3:之前的錯誤是由於代碼錯誤而出現的。現在SessionDestroyListener.sessionDestroy被調用,但我無法訪問給定事件中的HttpSession

這裏是我的SessionDestroyListener代碼(請注意,if的一個分支評論):

private static class SynchronizerSessionDestroyListener implements SessionDestroyListener { 
    @Override 
    public void sessionDestroy(SessionDestroyEvent event) { 
     if (event.getSession() != null){ 
      WrappedSession wrappedSession = event.getSession().getSession(); 
      if (wrappedSession instanceof WrappedHttpSession){ 
       WrappedHttpSession wrappedHttpSession = (WrappedHttpSession) wrappedSession; 
       HttpSession httpSession = wrappedHttpSession.getHttpSession(); 
       if (httpSession != null){ 
        try { 
         httpSession.invalidate(); 
         logger.debug("Session '{}' was invalidated", httpSession.getId()); 
        } catch (IllegalStateException e){ 
         // do nothing, already invalidated 
         logger.debug("Session '{}' was already invalidated: {}", httpSession.getId(), e.getMessage()); 
        } 
       } else { 
        logger.warn("Could not invalidate http session for vaadin session: http session is null"); // THIS IS THE BRANCH WHICH IS ACTUALLY GET EXECUTED ON 'SESSION EXPIRED' MESSAGE: event.getSession().getSession() is null! 
       } 
      } else { 
       logger.warn("Could not invalidate http session for vaadin session: event session is not an http session"); 
      } 
     } else { 
      logger.warn("Could not invalidate http session for vaadin session: event session is null"); 
     } 
    } 
} 

這裏是我連接監聽器:

public class X extends VaadinServlet { 
    // different class members 
    @Override 
    protected void servletInitialized() throws ServletException { 
     super.servletInitialized(); 
     getService().addSessionDestroyListener(new SynchronizerSessionDestroyListener()); 
    } 
} 
+0

你可以發佈你的'網絡。 xml'看起來像那些參數?或者您是否使用註釋使用參數? – JDC

回答

8

我會盡量解釋如何會話失效基本上起作用,也許這有助於(我無法從你的問題中讀出太多信息):

  • 通常會話將在參數 session-timeout中的指定時間後超時。
  • 你有拿心跳 間隔考慮。如果您的心跳間隔比會話超時(通常是)短 ,則心跳將永久保持會話存活 。

  • 這就是參數closeIdleSessions是相關的。將此參數設置爲 此參數爲true瀏覽器將不會將心跳作爲 作爲超時的有效請求,但最後的非心跳 請求

  • 秒BUT:什麼時候會識別超時?客戶端引擎只能在心跳或者用戶採取某些行動時才能識別這種情況(因爲在這兩種情況下都向服務器發出了請求)。因此,當指定的超時已經過去時,實際的超時將不會發生,但在超時後下一次心跳。
  • 其他情況:在3次心跳丟失後,服務器也關閉會話。例如。如果瀏覽器關閉,會導致會話失效,因爲沒有心跳被髮送。

樣品web.xml更好地說明:

<context-param> 
<!-- ATTENTION: This value is set in SECONDS --> 
<param-name>heartbeatInterval</param-name> 
<param-value>180</param-value> 
</context-param> 

<session-config> 
    <!-- ATTENTION: This value is set in MINUTES --> 
    <session-timeout>4</session-timeout> 
</session-config> 

<servlet> 
    <servlet-name>VaadinServlet</servlet-name> 
    <servlet-class>com.example.VaadinServlet</servlet-class> 
    <init-param> 
     <param-name>closeIdleSessions</param-name> 
     <param-value>true</param-value> 
    </init-param> 
</servlet> 

使用上述的web.xml 6分鐘(無需用戶交互)之後的會話將超時。

說明:
會話超時設置爲4分鐘,但在4分鐘內沒有心跳。下一次心跳將在6分鐘。現在客戶端引擎知道會話實際超時,並顯示相應的消息。

我不確定在使用Vaadin Push時這是否是相同的過程,因爲我們有從客戶端到服務器的連續通道。

來源:
Book of Vaadin - 4.8.7. Session Expiration
Book of Vaadin - 4.9.6. Other Servlet Configuration Parameters, Session Timeout After User Inactivity

其他信息:
即將Vaadin 7.6似乎提高客戶端 - 服務器連接的穩定性:Blog Post

+0

好的,但解決方案呢? –

+0

正如我所說,這只是對會話機制如何工作的解釋,因爲我無法重現您的確切問題。心跳間隔是否設置得太低可能是可能的? – JDC

+0

對不起,我有一個不正確的引用參數,請參閱更新的版本。心跳間隔設置爲1分鐘。據我所知,JEE會議比Vaadin的會議晚3次。 Vaadin有沒有什麼方法可以監聽它自己的會話過期消息,所以我可以做jeeSession.invalidate()? –