1、HttpServletRequest获取session的几种方式 request.getSession() request.getSession(true) reqeust.getSession(false) 前两个意思相同,获取当前request中的session,如果session不存在,就新建一个。 第三个方法,参数为false,表示如果session不存在,则返回null。 2、Session何时创建 当服务端程序执行HttpServletRequest.getSession()或者HttpServletRequest.getSession(true)代码时,session才会被创建。 当访问JSP页面时,默认也会创建Session对象,这是由于JSP在被编译成servlet时会被自动加上HttpSession session = HttpServletRequest.getSession(true)语句,这也是JSP中隐藏Session对象的来历。当 在jsp中显示使用<% @page session="false"%> 时,访问jsp页面就不会再创建session对象。 3、Session的创建过程 3.1 sessionId解析 在请求过程中首先要解析请求中的sessionId信息,然后将sessionId存储到request的参数列表中。然后再从 request获取session的时候,如果存在sessionId那么就根据Id从session池中获取session,如果sessionId不 存在或者session失效,那么则新建session并且将session信息放入session池,供下次使用。 ParsePathParameters方法从URL中解析sessionId(当cookie禁用,使用URL重写携带sessionId时)。 parseSessionCookiesId方法从cookie中解析出sessionId。 3.2 Servlet获取session的流程 appServlet是我们自己定义的一个Servlet,在通过Reqest获取session的时候,其实调用的这个 HttpServletRequest(是一个接口)其实是RequestFacade(封装了 org.apache.catalina.connector.Request的一个门面),然后RequestFacade会调用真实的Request 的getSession方法。Request具体的逻辑是调用Context容器的getManger方法获取Session管理器(默认为StandardManager管理器),然后如果SessionId如果已经被解析出来了,那么则会调用findSession方法从session对象池(ConcurrentHashMap)中获取对应的 session,反之如果sessionId不存在,则需要重新创建一个Session,并放入session对象池中。 当创建新的session时,涉及到新的sessionId的生成,生成sessionId的逻辑关键代码是在类StandardSessionIdGenerator中的generateSessionId方法中定义,可以根据实际需要修改sessionId的生成算法。 4、Session的类继承关系 tomcat中session对象的实现包的路径是:org.apache.catalina.session,tomcat对外提供session调用的接口不在这个实现包里,对外接口是在包javax.servlet.http下的HttpSession,而实现包里的StandardSession是tomcat提供的标准实现,当然对外tomcat不希望用户直接操作StandardSession,而是提供了一个StandardSessionFacade类,tomcat容器里具体操作session的组件是servlet,而servlet操作session是通过StandardSessionFacade进行的,这样就可以防止程序员直接操作StandardSession所带来的安全问题。(StandardSessionFacade使用了设计模式里的Façade(外观)模式,外观模式能让不同逻辑层的组件进行解耦)。 5、Session的管理器 在tomcatsession管理的类标准实现为StandardManager。 ManagerBase中使用ConcurrentHashMap存储和管理session,支持高并发的HashMap实现。 Session管理类负责创建和销毁session对象,其中ManagerBase是所有session管理工具类的基类,它是一个抽象类,所有具体实现session管理功能的类都要继承这个类,该类有一个受保护的方法,该方法就是创建sessionId值的方法(tomcat的session的id值生成的机制是一个随机数加时间加上jvm的id值,jvm的id值会根据服务器的硬件信息计算得来,因此不同jvm的id值都是唯一的),StandardManager类是tomcat容器里默认的session管理实现类,它会将session的信息存储到web容器所在服务器的内存里。 (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。
|