共计 4577 个字符,预计需要花费 12 分钟才能阅读完成。
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 当中指定:
好了,有关默认配置的就先总结这么多。
更多 Tomcat 相关教程见以下内容:
CentOS 6.6 下安装配置 Tomcat 环境 http://www.linuxidc.com/Linux/2015-08/122234.htm
RedHat Linux 5.5 安装 JDK+Tomcat 并部署 Java 项目 http://www.linuxidc.com/Linux/2015-02/113528.htm
Tomcat 权威指南(第二版)(中英高清 PDF 版 + 带书签) http://www.linuxidc.com/Linux/2015-02/113062.htm
Tomcat 安全配置与性能优化 http://www.linuxidc.com/Linux/2015-02/113060.htm
Linux 下使用 Xshell 查看 Tomcat 实时日志中文乱码解决方案 http://www.linuxidc.com/Linux/2015-01/112395.htm
CentOS 64-bit 下安装 JDK 和 Tomcat 并设置 Tomcat 开机启动操作步骤 http://www.linuxidc.com/Linux/2015-01/111485.htm
CentOS 6.5 下安装 Tomcat http://www.linuxidc.com/Linux/2015-01/111415.htm
Tomcat 的详细介绍:请点这里
Tomcat 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-09/135072.htm