2013-01-04 57 views
5

我想知道什麼時候究竟是一個HttpSession會不會過期(不一樣破壞)?何時HttpSession過期(開始有資格銷燬 - 不一定銷燬)?

我想弄清楚session.getLastAccessedTime()+(session.getMaxInactiveInterval()* 1000)會以毫秒爲單位給我會話過期的確切時間,每次請求都帶有相同的會話ID!

從的javadoc:

長getLastAccessedTime()

Returns the last time the client sent a request associated with this session, as the number of milliseconds since midnight January 1, 1970 GMT, and marked by the time the container received the request.  

INT getMaxInactiveInterval()

Returns the maximum time interval, in seconds, that the servlet container will keep this session open between client accesses. 

比方說,我們有以下幾點:
Treq1 - the time the container received the 1st request(HttpSession.lastAccessedTime)
Tresp1 - the time the container sends the 1st response
Preq1 - the time period between Treq1 and Tresp1 (the time period that the server processes the 1st request
Treq2 - the time the container received the 2nd request(HttpSession.lastAccessedTime)
Preq1req2 - the time period between Treq1 and Treq2 (the time between requests entering the container)
Presp1req2 - the time period between Tresp1 and Treq2 (the time between the 1st response exiting the container and the 2nd request entering the container)

所以,現在,什麼時候服務器計算會話過期?當:
1. Treq1 + maxInactiveInterval < Treq1 + Preq1req2 =>maxInactiveInterval < Preq1req2
2. Tresp1 + maxInactiveInterval < Tresp1 + Presp1req2 =>maxInactiveInterval < Presp1req2

這部分,the servlet container will keep this session open between client accesses是一個有點混亂。這是指進入集裝箱的請求之間,還是響應退出和請求輸入之間的意思?

在一個側面說明我知道,這次會議可能不會在到期日的確切時間被摧毀,但我還不知道發生的任何請求處理邏輯之前,如果它被破壞集裝箱。我指的是包含過期會話ID的請求。

親切的問候,
暴君

+1

爲什麼這很重要?請求的時間通常是幾毫秒。會話超時通常爲30分鐘。 30,000或30.002是否重要?你最終的目標是什麼?無論如何,答案是在問題:*和容器收到請求時標記* –

+0

它很重要,因爲我想知道客戶端到底什麼時候會過期。 「答案在於:容器收到請求的時間標記」這可能只涉及lastAccessedTime。你確定過期時間將會是session.getLastAccessedTime()+(session.getMaxInactiveInterval()* 1000)(1. case)嗎?有沒有可以證實的來源?感謝您的評論! – despot

+2

你想要精確到毫秒?最終用戶在30分鐘或30分鐘和8毫秒時是否在意護理?無論如何,該會話當時不會被銷燬,因爲容器通常使用後臺線程,每隔一分鐘左右銷燬過期的會話。 –

回答

10

會話機制是Servlet specification的一部分,其中准許:

在HTTP協議中,沒有顯式的終止信號,當客戶端沒有 不再有效。這意味着唯一可用於指示客戶端不再處於活動狀態的機制是超時期限。

會話的默認超時時間由servlet容器定義,並且可以通過HttpSession接口的getMaxInactiveInterval方法獲取 。 開發人員可以使用HttpSession接口的setMaxInactiveInterval 方法更改此超時。這些方法 使用的超時時間是以秒爲單位定義的。根據定義,如果會話的超時時間設置爲-1, ,則會話永遠不會過期。在所有使用該會話的 servlet都退出服務方法之前,會話失效纔會生效。一旦啓動會話 失效,新的請求就不能看到該會話。

HttpSession接口的getLastAccessedTime方法允許servlet通過 確定上次在當前請求之前訪問會話的時間。當作爲會話一部分的請求是由servlet容器處理的第一個 時,認爲會話被訪問。

假設「無效間隔」以「lastAccessedTime」開始可能是安全的。

+0

沒問題,所以會話過期時間應該使用session.getLastAccessedTime()+(session.getMaxInactiveInterval()* 1000)來計算,而案例1是正確的?! – despot

+0

我將假設上述。 – despot

+0

由於citiation的最後部分包含「...確定上一次在當前request_之前訪問會話。」對我來說意味着,這次不是當前的請求,而是之前的請求。因此,要確定會話結束時間,您必須將請求開始時的當前時間添加到maxInactiveInterval,如@Subin的答案中所示。 – cyberbrain

3

我試圖找出是否session.getLastAccessedTime()+(session.getMaxInactiveInterval()* 1000)會給我確切的時間在每個會話到期毫秒一次請求帶有相同的會話ID!

,因爲你只能在我假設你有上面的代碼在servlet告知客戶端(瀏覽器)在什麼時候,他可以在他的下次點擊之前採取的請求的線程訪問會話對象,可能是超時計數器。

我認爲System.currentTimeMillis() + (session.getMaxInactiveInterval() * 1000)在這種情況下會更準確。

+0

「。 「我假定System.currentTimeMillis()+(session.getMaxInactiveInterval()* 1000)」,所以你假設它是2. case?!任何來源,所以我們可以肯定這一點?感謝您的回答! – despot

+0

如果您想以可讀的格式顯示,您可以使用:SimpleDateFormat sdf = new SimpleDateFormat(「yyyy-MM-dd HH:mm:ss.SSS」);日期結果日期=新日期(timeInMs); System.out.println(「HRF中的日期:」+ sdf.format(resultdate)); –

0

來源?

我追查請求兩次使用「org.springframework.boot:彈簧引導起動網址:1.5.6.RELEASE」 spring,並得出結論:

在服務處理器(的doGet,doXX,或控制方法),過期時間將是session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000)(2.的情況)

Duration:  |<---------- Preq1req2 ---------->| 
Duration:  |   |<---- Presp1req2 --->| 
Time :  Treq1  Tresp1    Treq2  Tresp2 
Action : req1-->|--service--|-->resp1 ... req2-->|--service--|-->resp2 
Duration:  |<- Preq1 ->|      |<- Preq2 ->| 
       |   |         | 
Set :  creationTime  |         | 
      lastAccessedTime |         |    
         lastAccessedTime     lastAccessedTime 

當lastAccessedTime被服務之後更新: After HTTP service

代碼選自C片段:/ US ERS/ssfang/.m2目錄/庫/組織/阿帕奇/ tomcat的/嵌入/ Tomcat的嵌入核/ 16年5月8日/ Tomcat的嵌入核心 - 16年5月8日 - sources.jar

package org.apache.catalina.session; 
public class StandardSession implements HttpSession, Session, Serializable { 
    /** The time this session was created, in milliseconds since midnight, January 1, 1970 GMT. */ 
    protected long creationTime = 0L; 

    /** 
    * We are currently processing a session expiration, so bypass 
    * certain IllegalStateException tests. NOTE: This value is not 
    * included in the serialized version of this object. 
    */ 
    protected transient volatile boolean expiring = false; 

    /** The last accessed time for this Session. */ 
    protected volatile long lastAccessedTime = creationTime; 

    /** The session event listeners for this Session. */ 
    protected transient ArrayList<SessionListener> listeners = new ArrayList<>(); 

    /** Flag indicating whether this session is valid or not. */ 
    protected volatile boolean isValid = false; 

    /** The current accessed time for this session. */ 
    protected volatile long thisAccessedTime = creationTime; 


    /** The access count for this session. */ 
    protected transient AtomicInteger accessCount = null; 

    /** 
    * The maximum time interval, in seconds, between client requests before the servlet container may 
    * invalidate this session. A negative time indicates that the session should never time out. 
    */ 
    protected volatile int maxInactiveInterval = -1; 

    /** 
    * Return the idle time from last client access time without invalidation check 
    * @see #getIdleTime() 
    */ 
    @Override 
    public long getIdleTimeInternal() { 
     long timeNow = System.currentTimeMillis(); 
     long timeIdle; 
     if (LAST_ACCESS_AT_START) { 
      timeIdle = timeNow - lastAccessedTime; 
     } else { 
      timeIdle = timeNow - thisAccessedTime; 
     } 
     return timeIdle; 
    } 

    /** 
    * Set the creation time for this session. This method is called by the 
    * Manager when an existing Session instance is reused. 
    * 
    * @param time The new creation time 
    */ 
    @Override 
    public void setCreationTime(long time) { 
     this.creationTime = time; 
     this.lastAccessedTime = time; 
     this.thisAccessedTime = time; 
    } 

    /** Return the <code>isValid</code> flag for this session. */ 
    @Override 
    public boolean isValid() { 
     if (!this.isValid) { 
      return false; 
     } 
     if (this.expiring) { 
      return true; 
     } 
     if (ACTIVITY_CHECK && accessCount.get() > 0) { 
      return true; 
     } 
     if (maxInactiveInterval > 0) { 
      int timeIdle = (int) (getIdleTimeInternal()/1000L); 
      if (timeIdle >= maxInactiveInterval) { 
       expire(true); 
      } 
     } 
     return this.isValid; 
    } 
} 

檢查是否會議得到了會議

Check whether the session is valid before getting the session

後臺線程掃描是否已經過期的所有會話之前是有效的。

background thread to scan sessions