在getSession会调用doGetSession org.apache.catalina.connector.Request#doGetSession
// org.apache.catalina.connector.Request#getSession()
public HttpSession getSession() {
Session session = doGetSession(true);
if (session == null) {
return null;
}
return session.getSession();
}
doGetSession核心的逻辑
- session是否存在存在的话是否有效
- 然后查看cookie里携带的sessionId在当前tomcat里是否有 + 是否有效
- 如果携带的sessionId无效,最后会生成一个新的sessionId(manager.createSession(sessionId))
protected Session doGetSession(boolean create) {
// There cannot be a session if no context has been assigned yet
Context context = getContext();
if (context == null) {
return null;
}
// Return the current session if it exists and is valid
if ((session != null) && !session.isValid()) {
session = null;
}
if (session != null) {
return session;
}
// Return the requested session if it exists and is valid
Manager manager = context.getManager();
if (manager == null) {
return null; // Sessions are not supported
}
if (requestedSessionId != null) {
try {
session = manager.findSession(requestedSessionId);
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("request.session.failed", requestedSessionId, e.getMessage()), e);
} else {
log.info(sm.getString("request.session.failed", requestedSessionId, e.getMessage()));
}
session = null;
}
if ((session != null) && !session.isValid()) {
session = null;
}
if (session != null) {
session.access();
return session;
}
}
// Create a new session if requested and the response is not committed
if (!create) {
return null;
}
boolean trackModesIncludesCookie =
context.getServletContext().getEffectiveSessionTrackingModes().contains(SessionTrackingMode.COOKIE);
if (trackModesIncludesCookie && response.getResponse().isCommitted()) {
throw new IllegalStateException(sm.getString("coyoteRequest.sessionCreateCommitted"));
}
// Re-use session IDs provided by the client in very limited
// circumstances.
String sessionId = getRequestedSessionId();
if (requestedSessionSSL) {
// If the session ID has been obtained from the SSL handshake then
// use it.
} else if (("/".equals(context.getSessionCookiePath()) && isRequestedSessionIdFromCookie())) {
/*
* This is the common(ish) use case: using the same session ID with multiple web applications on the same
* host. Typically this is used by Portlet implementations. It only works if sessions are tracked via
* cookies. The cookie must have a path of "/" else it won't be provided for requests to all web
* applications.
*
* Any session ID provided by the client should be for a session that already exists somewhere on the host.
* Check if the context is configured for this to be confirmed.
*/
if (context.getValidateClientProvidedNewSessionId()) {
boolean found = false;
for (Container container : getHost().findChildren()) {
Manager m = ((Context) container).getManager();
if (m != null) {
try {
if (m.findSession(sessionId) != null) {
found = true;
break;
}
} catch (IOException e) {
// Ignore. Problems with this manager will be
// handled elsewhere.
}
}
}
if (!found) {
sessionId = null;
}
}
} else {
sessionId = null;
}
session = manager.createSession(sessionId);
// Creating a new session cookie based on that session
if (session != null && trackModesIncludesCookie) {
Cookie cookie =
ApplicationSessionCookieConfig.createSessionCookie(context, session.getIdInternal(), isSecure());
response.addSessionCookieInternal(cookie);
}
if (session == null) {
return null;
}
session.access();
return session;
}
总结
在分布式情况下。拿着其他服务器的sessionId请求新的服务器时会返回新的sessionID。然后再拿这个sessionId请求其他的服务器又会产生新的sessionId。如此反复,最终失效了。