什么时候HttpSession到期了(开始有资格进行破坏 - 还没有被破坏)?

时间:2013-01-04 09:47:42

标签: java spring httpsession

我想知道什么时候完全 HttpSession 已过期(与销毁时不一样)?

我试图弄清楚每当请求带有相同的会话ID时,session.getLastAccessedTime()+(session.getMaxInactiveInterval()* 1000)是否会以毫秒为单位给出会话到期的确切时间!

来自javadocs:

  

long 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&lt; Treq1 + Preq1req2 =&gt; maxInactiveInterval&lt; Preq1req2
2.Tresp1 + maxInactiveInterval&lt; Tresp1 + Presp1req2 =&gt; maxInactiveInterval&lt; Presp1req2

这部分the servlet container will keep this session open between client accesses有点令人困惑。这是指在进入容器的请求之间还是在退出响应和请求进入之间?

在旁注 我知道会话可能不会在到期的确切时间销毁 ,但我不知道知道它是否在容器中发生任何请求处理逻辑之前被销毁。我指的是持有过期会话ID的请求。

亲切的问候,

3 个答案:

答案 0 :(得分:10)

会话机制是Servlet specification的一部分,其任务是:

  

在HTTP协议中,当客户端为no时,没有明确的终止信号   更长的活跃。这意味着唯一可用于指示何时的机制   客户不再活跃是超时期限。

     

会话的默认超时时间由servlet容器定义,并且可以   通过HttpSession接口的getMaxInactiveInterval方法获取。   开发人员可以使用setMaxInactiveInterval更改此超时   HttpSession接口的方法。这些方法使用的超时时间   以秒为单位定义。根据定义,如果会话的超时时间设置为-1,   会话永远不会过期。会话失效将不会生效   使用该会话的servlet已退出服务方法。一次会议   启动失效,新请求必须无法看到该会话。

     

HttpSession接口的getLastAccessedTime方法允许servlet   确定在当前请求之前访问会话的最后时间。该   当作为会话的一部分的请求是第一个时,认为会话被访问   由servlet容器处理。

可以安全地假设“非活动间隔”以“lastAccessedTime”开头。

答案 1 :(得分:3)

  

我试图找出session.getLastAccessedTime()+(session.getMaxInactiveInterval()* 1000)是否会在每次请求带有相同会话ID时给出确切的时间(以毫秒为单位)!

因为你只能在一个请求线程中访问会话对象我假设你在servlet中有上面的代码,用于通知客户端(浏览器)他在下次点击之前可以采取的时间,可能是一个超时计数器。

我认为System.currentTimeMillis() + (session.getMaxInactiveInterval() * 1000)在这种情况下会更准确。

答案 2 :(得分:0)

源?

我使用“org.springframework.boot:spring-boot-starter-web:1.5.6.RELEASE”spring追踪了两次请求并得出结论:

在您的服务处理程序(doGet,doXX或Controller方法)中,到期时间将为session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000)(2。case)

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的代码片段:/Users/ssfang/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/8.5.16/tomcat-embed-core-8.5.16-sources.jar < / p>

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