【问题标题】:When exactly is the HttpSession expired (starts being eligible for destroying - not necessarily destroyed yet)?HttpSession 究竟何时过期(开始有资格销毁 - 不一定已销毁)?
【发布时间】:2012-12-18 17:55:57
【问题描述】:

我想知道确切地 HttpSession 何时过期(与销毁不同)?

我正在尝试确定 session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) 是否会在每次请求带有相同会话 ID 时为我提供会话到期的确切时间(以毫秒为单位)!

来自 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 ma​​xInactiveInterval
2. Tresp1 + maxInactiveInterval ma​​xInactiveInterval

这部分,the servlet container will keep this session open between client accesses 有点混乱。是在请求进入容器之间还是在响应退出和请求进入之间?

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

亲切的问候,
暴君

【问题讨论】:

  • 为什么重要?请求的时间通常是几毫秒。会话超时通常为 30 分钟。是 30.000 还是 30.002 有关系吗?你的最终目标是什么?无论如何,答案就在问题中:并以容器收到请求的时间标记
  • 这很重要,因为我想在客户端确切地知道会话何时到期。 “答案就在问题中:并由容器收到请求的时间标记”这可能仅指 lastAccessedTime。你确定过期时间是 session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) (1.case)?有没有可以证实的消息来源?感谢您的评论!
  • 您想要精确到毫秒吗?最终用户是否关心它是在 30 分钟内还是在 30 分 8 毫秒内?无论如何,那个时候会话不会被销毁,因为容器通常使用一个后台线程,每分钟左右销毁过期的会话。
  • 首先,服务器上的处理可能需要超过 8 毫秒,其次,我需要确保我没有在会话过期的某个端点发送请求(并且我想最大化我向该端点发送请求的时间)。 “那个时候会话不会被破坏”我明白这一点(参见“旁注”部分)。这并不能回答服务器过期时间(不破坏时间)的问题。我想先了解一下,服务器到底是怎么计算过期时间的。
  • 确保您没有向超时会话发送请求的方法是发送它并处理由此产生的错误情况。无论如何你必须这样做。任何预测方法迟早都会失败,在现实中无非是算命。

标签: java spring httpsession


【解决方案1】:

会话机制是Servlet specification的一部分,它要求:

在 HTTP 协议中,当客户端不存在时,没有显式的终止信号 更长时间的活跃。这意味着唯一可以用来指示何时 客户端不再处于活动状态是一个超时期限。

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

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

假设“非活动间隔”从“lastAccessedTime”开始可能是安全的。

【讨论】:

  • ok,所以session过期时间应该用session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000)来计算,情况1.是正确的吗?!
  • 我将假设上述情况。
  • 由于引用的最后一部分包含“...确定上次访问会话的时间在当前请求之前。”对我来说,这一次不是当前的请求,而是之前的请求。因此,要确定会话结束时间,您必须将请求开始时的当前时间添加到 maxInactiveInterval,如@Subin 的答案中所示。
【解决方案2】:

我正在尝试确定 session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) 是否会在每次请求带有相同会话 ID 时为我提供会话到期的确切时间(以毫秒为单位)!

由于您只能在请求线程中访问会话对象,我假设您在 servlet 中有上述代码,用于通知客户端(浏览器)在下次点击之前他可以花多长时间,这可能是一个超时计数器。

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

【讨论】:

  • “用于准确通知客户端(浏览器)”。 “我假设 System.currentTimeMillis() + (session.getMaxInactiveInterval() * 1000)”所以你假设它是 2. 案例?!任何来源,所以我们可以确定这一点?感谢您的回答!
  • 如果你想以人类可读的格式显示它,你可以使用: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");日期结果date = new Date(timeInMs); System.out.println("HRF 中的日期:" + sdf.format(resultdate));
【解决方案3】:

来源?

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

在您的服务处理程序(doGet、doXX 或 Controller 方法)中,到期时间将是 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 时:

来自 C:/Users/ssfang/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/8.5.16/tomcat-embed-core-8.5.16-sources 的代码 sn-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;
    }
}

获取会话前检查会话是否有效

后台线程扫描所有会话是否已过期。

【讨论】:

    猜你喜欢
    • 2016-05-12
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    相关资源
    最近更新 更多