Tomcat-session的实现:线程安全与管理

本文详细解析了Tomcat中Session的创建、管理、过期清理的过程。从`Request.getSession()`开始,分析了如何查找、创建和返回Session。重点介绍了Session的生命周期,包括如何通过`StandardSession`实现过期检查及清理,以及在`StandardManager`中的存储和查找机制。文章还提及了面试中可能涉及的相关知识点。
摘要由CSDN通过智能技术生成

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
return AccessController.
doPrivileged(new GetSessionPrivilegedAction(create));
} else {
// RequestFacade 是个外观模式实现,核心请求还是会传递给 Request处理的
// org.apache.catalina.connector.Request
return request.getSession(create);
}
}

// org.apache.catalina.connector.Request#getSession(boolean)
/**

  • @return the session associated with this Request, creating one
  • if necessary and requested.
  • @param create Create a new session if one does not exist
    */
    @Override
    public HttpSession getSession(boolean create) {
    // 由 create 字段决定是否需要创建新的session, 如果不存在的话。
    // Session 是tomcat的一个会话实现类,并非对接规范接口类,其会包装一个HttpSession,以便统一交互
    // 因为只有 HttpSession 才是 Servlet 的接口规范,在tomcat中会以 StandardSessionFacade 实现接口,其也是一个外观模式的实现,具体工作由 StandardSession 处理。
    Session session = doGetSession(create);
    if (session == null) {
    return null;
    }
    // 包装 Session 为 HttpSession 规范返回
    return session.getSession();
    }
    // org.apache.catalina.connector.Request#doGetSession
    protected Session doGetSession(boolean create) {

// There cannot be a session if no context has been assigned yet
// mappingData.context;
Context context = getContext();
if (context == null) {
return (null);
}

// Return the current session if it exists and is valid
// 此处检查session有效性时,也会做部分清理工作
if ((session != null) && !session.isValid()) {
session = null;
}
if (session != null) {
return (session);
}

// Return the requested session if it exists and is valid
// 获取manager 实例,即真正进行 Session 管理的类,其实主要分两种:1. 基于内存;2. 基于文件的持久化;
Manager manager = context.getManager();
if (manager == null) {
return (null); // Sessions are not supported
}
if (requestedSessionId != null) {
try {
// 如果不是第一次请求,则会带上服务返回的 sessionId, 就会主动查找原来的session
// 从 sessions 中查找即可
session = manager.findSession(requestedSessionId);
} catch (IOException e) {
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
// 主动请求session时,才会继续后续逻辑
if (!create) {
return (null);
}
if (response != null
&& context.getServletContext()
.getEffectiveSessionTrackingModes()
.contains(SessionTrackingMode.COOKIE)
&& 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 {
    // 当session无效时,需要将原来的seesionId置空,删除并新创建一个使用
    sessionId = null;
    }
    // 创建session, StandardManager -> ManagerBase
    session = manager.createSession(sessionId);

// Creating a new session cookie based on that session
if (session != null
&& context.

  • 26
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值