Tomcat 服务器是一个免费的开放源代码的 web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试 JSP 程序的首选。
这篇文章主要为大家详细介绍了 Tomcat 中 session 的管理机制 , 具有一定的参考价值,感兴趣的小伙伴们可以参考一下
详细描述 Tomcat 中 session 的管理机制:
1. 请求过程中的 session 操作:
简述:在请求过程中首先要解析请求中的 sessionId 信息,然后将 sessionId 存储到 request 的参数列表中。然后再从 request 获取 session 的时候,如果存在 sessionId 那么就根据 Id 从 session 池中获取 session,如果 sessionId 不 存在或者 session 失效,那么则新建 session 并且将 session 信息放入 session 池,供下次使用。
(1)SessionId 解析过程时序图:
概述:首先用户发送一个 http 请求传递给 Http11Processor, 经由 Http11Processor 解析封装在 org.apache.coyote.Request 然后传递给 CoyoteAdapter,coyoteAdapter 是一个适配器,将 coyote 框架封装的 org.apache.coyote.Request 适配给 org.apache.catalina.connector.Request(这个流程不多说,之前都有总结过),转换完之后会调用 parsePathParameters 方法去解析路径参数中的 cookie 信息(因为当 cookie 被浏览器禁用时,会将 cookie 信息重写进 url),先尝试从 url 中尝试解析出 sessionId. 然后会调用 parseSessionCookiesId, 这个就是从 cookie 中解析 sessionId 存到 request(parsePathParameters 和 parseSessionCookiesId 方法,在调用过程中,没有看到明显的异或逻辑,即两者都执行了,但这样不是就有问题了吗?想想其实没有问题的,URL 重写设置 sessionId 或者放到 cookie 中传递过来,两者方式只会用一个,想到这点就知道没有问题了)解析到 sessionId 就放到了 request 里面。解析 SessionId 的逻辑就 ok 了。
下面贴出关键代码:
ParsePathParameters 方法(从重写 URL 中解析):
Ps: 标记出来的部分分别是从 URL 解析出变量,然后放到 request 参数列表里面。
parseSessionCookiesId 方法(从 cookie 中解析出 sessionId):
Ps: 上面的标记就是从 cookie 中获取 sessionId. 看第一个标记有个 SessionConfig.getSessionCookieName(context)的调用,这里会获取到一个默认的 sessionId 的 key,这个 key 是定义在 SessionConfig 中的,其值为 jsessionId:
(2) 从请求中获取 session 的流程基本就是上文描述的这样。那么再看一下 Servlet 获取 session 的流程:
概述:appServlet 是我们自己定义的一个 Servlet,在通过 Reqest 获取 session 的时候,其实调用的这个 HttpServletRequest(是一个接口)其实是 RequestFacade(封装了 org.apache.catalina.connector.Request 的一个门面),然后 RequestFacade 会调用真实的 Request 的 getSession 方法。Request 具体的逻辑是调用 Context 容器的 getManger 方法获取 Session 管理器(session 管理器详情下文介绍),然后如果 SessionId 如果已经被解析出来了,那么则会调用 findSession 方法从 session 对象池中获取对应的 session,反之如果 sessionId 不存在,则需要重新创建一个 Session,并放入 session 对象池中。
下面贴出关键代码:
类 RequestFacade 的 getSession 方法:
类 Request 的 getSession 方法:
类 Request 的 doGetSession 方法:
Ps:第一个标记就是根据 SessionId 从 session 对象池中获取 session 信息,第二标记就是在没有解析到 sessionId 的情况下创建一个新的 Session 对象。
这个创建一个新的 session 这里点涉及到新的 sessionId 的生成,生成 sessionId 的逻辑关键代码是在类 SessionIdGenerator 中的 generateSessionId 方法中定义:
以上即是 Servlet 获取 session 的流程,下文具体总结一下 tomcat 是怎么来管理 Session 的,即 session 管理器的知识。
2. Session 的管理机制
Session 管理器定义:Session 管理器组件负责管理 Session 对象,例如,创建和销毁 Session 对象。
首先看一张 Session 管理器的类继承结构图(这个是 tocmat7.x 的图,tomcat5 的类继承机构和这个有很大不同):
简述:下面依次总结下每个类(参考官网信息):
(1)Manager:定义了关联到某一个容器的用来管理 session 池的基本接口。
(2)ManagerBase:实现了 Manager 接口,该类提供了 Session 管理器的常见功能的实现。
(3)StandardManager:继承自 ManagerBase,tomcat 的默认 Session 管理器(不指定配置,默认使用这个),是 tomcat 处理 session 的非集群实现(也就说是单机版的),tomcat 关闭时,内存 session 信息会持久化到磁盘保存为 SESSION.ser, 再次启动时恢复。
(4)PersistentManagerBase:继承自 ManagerBase,实现了和定义了 session 管理器持久化的基础功能。
(5)PersistentManager:继承自 PersistentManagerBase,主要实现的功能是会把空闲的会话对象(通过设定超时时间)交换到磁盘上。
(6)ClusterManager:实现了 Manager 接口,通过类名应该能猜到,这个就是管理集群 session 的管理器和上面那个 StandardManager 单机版的 session 管理器是相对的概念。这个类定义类集群间 session 的复制共享接口。
(7)ClusterManagerBase:实现了 ClusterManager 接口,继承自 ManagerBase。该类实现了 session 复制的基本操作。
(8)BackupManager:继承自 ClusterManagerBase, 集群间 session 复制策略的一种实现,会话数据只有一个备份节点,这个备份节点的位置集群中所有节点都可见。这种设计使它有个优势就是支持异构部署。
(9)DeltaManager:继承自 ClusterManagerBase, 集群建 session 复制策略的一种实现,和 BackupManager 不同的是,会话数据会复制到集群中所有的成员节点,这也就要求集群中所有节点必须同构,必须部署相同的应用。
补充:下面再具体总结一点就是在 PersistentManagerBase 类中有个成员变量 Store:
持久化 session 管理器的存储策略就是有这个 Store 对象定义的,这个 Store 的类继承结构如下:
简述:接口 Store 及其实例是为 session 管理器提供了一套存储策略,store 定义了基本的接口,而 StoreBase 提供了基本的实现。其中 FileStore 类实现的策略是将 session 存储在以 setDirectory()指定目录并以. session 结尾的文件中的。JDBCStore 类是将 Session 通过 JDBC 存入数据库中,因此需要使用 JDBCStore,需要分别调用 setDriverName() 方法和 setConnectionURL() 方法来设置驱动程序名称和连接 URL。
3. Tomcat session 相关的配置
从两个层面总结一下 session 相关的配置和设置。首先是从配置文件层面,session 是有过期时间的,这个默认的过期时间是在 $catalina_home/conf/web.xml 有定义的。具体的默认配置如下(默认的过期时间是 30min,即 30min 没有访问,session 就过期了):
还有一点就是 session 管理如果不配置就默认使用 StandardManager,但如果要配置的话可以在 $catalina_home/conf/context.xml 当中指定(其中从这个配置当中可以看到 session 管理器是和 context 容器关联的,也就说每个 web 应用都会有一个 session 管理器)具体的配置如下:
Tomcat7.x 默认这个 manager 的配置是注释掉的。如果要指定的 PersistentManager 为默认管理器的话可以这么指定:
其实看到这也就发现了,其实 session 管理器或者 Store 存储策略,只要实现了相关的接口,都是可以自定义的。自己写一个配置在这里就 ok 了。
另外在从代码层面总结一下:session 的一些配置信息是写死在代码里的,比如 SessionConfig 这个类就定义了一些 session 的设置信息。Session 在 cookie 中的名字是 JSESSION. Session 通过 URL 重写的方式放在 path 里时,键值的名字是 jsessionids, 具体的代码如下:
还有一点就是 sessionId 默认指定的长度是 16 个字节, 这个在 SessionIdGenerator 当中指定:
好了,有关默认配置的就先总结这么多。
来源: http://www.phperz.com/article/17/1215/359883.html