java HttpSession 究竟何时过期(开始有资格销毁 - 不一定已销毁)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14154696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When exactly is the HttpSession expired (starts being eligible for destroying - not necessarily destroyed yet)?
提问by despot
I would like to know when exactlyan HttpSession would be expired(not the same as destroyed)?
我想知道HttpSession究竟何时过期(与销毁不同)?
I am trying to figure out if session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) will give me the exact time in milliseconds of session expiry each time a request comes with the same session id!
我想弄清楚 session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) 是否会在每次请求带有相同会话 ID 时给我会话到期的确切时间(以毫秒为单位)!
From the javadocs:
从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.
长 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.
Lets say we have the following:
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)
假设我们有以下内容:
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)
So now, when does the server calculate the session as expired?When:
1. Treq1 + maxInactiveInterval < Treq1 + Preq1req2 => maxInactiveInterval < Preq1req2
2. Tresp1 + maxInactiveInterval < Tresp1 + Presp1req2 => maxInactiveInterval < Presp1req2
那么现在,服务器何时计算会话已过期?当:
1. Treq1 + maxInactiveInterval < Treq1 + Preq1req2 => maxInactiveInterval < Preq1req2
2. Tresp1 + maxInactiveInterval < Tresp1 + Presp1req2 => maxInactiveInterval < Presp1req2
This part, the servlet container will keep this session open between client accesses
is a bit confusing. Does it mean between requests entering the container or between response exiting and requests entering?
这部分,the servlet container will keep this session open between client accesses
有点混乱。它是指请求进入容器之间还是响应退出和请求进入之间?
On a side note, I know that the session might not be destroyed at the exact time of expiry, but I don't know yet if it is destroyed before any request processing logic occurs in the container. I am referring to the request that holds an expired session id.
附带说明一下,我知道会话可能不会在到期的确切时间被销毁,但我不知道它是否在容器中发生任何请求处理逻辑之前被销毁。我指的是持有过期会话 ID 的请求。
Kind Regards,
Despot
亲切的问候,
暴君
回答by meriton
The session mechanism is part of the Servlet specification, which mandates:
会话机制是Servlet 规范的一部分,它要求:
In the HTTP protocol, there is no explicit termination signal when a client is no longer active. This means that the only mechanism that can be used to indicate when a client is no longer active is a time out period.
The default time out period for sessions is defined by the servlet container and can be obtained via the getMaxInactiveInterval method of the HttpSession interface. This time out can be changed by the Developer using the setMaxInactiveInterval method of the HttpSession interface. The time out periods used by these methods are defined in seconds. By definition, if the time out period for a session is set to -1, the session will never expire. The session invalidation will not take effect until all servlets using that session have exited the service method. Once the session invalidation is initiated, a new request must not be able to see that session.
The getLastAccessedTime method of the HttpSession interface allows a servlet to determine the last time the session was accessed before the current request. The session is considered to be accessed when a request that is part of the session is first handled by the servlet container.
在 HTTP 协议中,当客户端不再活动时,没有明确的终止信号。这意味着可用于指示客户端何时不再活动的唯一机制是超时时间段。
会话的默认超时时间由 servlet 容器定义,可以通过 HttpSession 接口的 getMaxInactiveInterval 方法获取。开发人员可以使用 HttpSession 接口的 setMaxInactiveInterval 方法更改此超时。这些方法使用的超时时间以秒为单位定义。根据定义,如果会话的超时期限设置为 -1,则会话将永不过期。直到所有使用该会话的 servlet 都退出服务方法后,会话失效才会生效。一旦会话失效被启动,新的请求一定不能看到那个会话。
HttpSession 接口的 getLastAccessedTime 方法允许 servlet 确定在当前请求之前访问会话的最后时间。当作为会话一部分的请求首先由 servlet 容器处理时,会话被视为被访问。
It is probably safe to assume that the "inactive interval" starts with the "lastAccessedTime".
假设“非活动间隔”以“lastAccessedTime”开始可能是安全的。
回答by Subin Sebastian
I am trying to figure out if session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) will give me the exact time in milliseconds of session expiry each time a request comes with the same session id!
我想弄清楚 session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) 是否会在每次请求带有相同会话 ID 时给我会话到期的确切时间(以毫秒为单位)!
since you can access session object only in a request thread I am assuming you are having above code in a servlet for informing client(browser) on what time he can take before his next click, may be a timeout counter.
由于您只能在请求线程中访问会话对象,因此我假设您在 servlet 中具有上述代码,用于通知客户端(浏览器)在下次单击之前他可以花费什么时间,可能是超时计数器。
I assume System.currentTimeMillis() + (session.getMaxInactiveInterval() * 1000)
will be more accurate in that case.
我认为System.currentTimeMillis() + (session.getMaxInactiveInterval() * 1000)
在这种情况下会更准确。
回答by samm
source?
来源?
I traced requests twice using "org.springframework.boot:spring-boot-starter-web:1.5.6.RELEASE" springand concluded:
我使用 "org.springframework.boot:spring-boot-starter-web:1.5.6.RELEASE" spring跟踪请求两次并得出结论:
In your service handler (doGet, doXX, or Controller methods), the expiration time is going to be session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000)
(2. case)
在您的服务处理程序(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
When lastAccessedTime is updated after service:
Code snippet from C:/Users/ssfang/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/8.5.16/tomcat-embed-core-8.5.16-sources.jar
来自 C:/Users/ssfang/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/8.5.16/tomcat-embed-core-8.5.16-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
在获取会话之前检查会话是否有效
A background thread to scan all sessions whether have expired.
用于扫描所有会话是否已过期的后台线程。