Tomcat Session管理

Catalina通过一个称为Session管理器的组件来管理建立Session对象,该组件由org.apache.catalina.Manager接口表示。Session管理器需要与一个Context容器相关联,且必须与一个Context容器关联。相比于其他组件,Session管理器负责创建、更新、销毁Session对象,当请求来了,要返回一个有效的Session对象。

默认情况下,Session管理器会将其所管理的Session对象存放在内存中。但是,在Tomcat中,Session管理器也可以将Session对象进行持久化,存储到文件存储器或者通过JDBC写入到数据库中。

session相关的如下图:

1.Session一个接口,用于维护状态信息的HttpSession,对于用户的请求维持状态。看一下一些常量和部分接口方法。

public interface Session {
public static final String SESSION_CREATED_EVENT = "createSession";
/**
* The SessionEvent event type when a session is destroyed.
*/
public static final String SESSION_DESTROYED_EVENT = "destroySession";
/**
* The SessionEvent event type when a session is activated.
*/
public static final String SESSION_ACTIVATED_EVENT = "activateSession";
/**
* The SessionEvent event type when a session is passivated.
*/
public static final String SESSION_PASSIVATED_EVENT = "passivateSession";
/**
* Return the creation time for this session.
*/
public long getCreationTime();
/**
* Return the session identifier for this session.
*/
public String getId();
/**
* Return the <code>HttpSession</code> for which this object
* is the facade.
*/
public HttpSession getSession();
/**
* Add a session event listener to this component.
*/
public void addSessionListener(SessionListener listener);
/**
* Perform the internal processing required to invalidate this session,
* without triggering an exception if the session has already expired.
*/
public void expire();
}

2.StandardSession实现了Session、HttpSession、Serializable接口(便于session序列化) 
部分方法:

/**
* Add a session event listener to this component.
*/
@Override
public void addSessionListener(SessionListener listener) {
listeners.add(listener);
}
public void readObjectData(ObjectInputStream stream)
throws ClassNotFoundException, IOException { readObject(stream); }
public void writeObjectData(ObjectOutputStream stream)
throws IOException { writeObject(stream); }
//获取Session里面的值
public Object getAttribute(String name) { if (!isValidInternal())
throw new IllegalStateException
(sm.getString("standardSession.getAttribute.ise")); if (name == null) return null; return (attributes.get(name)); }
/**
* The collection of user data attributes associated with this Session.
*/
protected Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
//触发事件
public void fireSessionEvent(String type, Object data) {
if (listeners.size() < 1)
return;
SessionEvent event = new SessionEvent(this, type, data);
SessionListener list[] = new SessionListener[0];
synchronized (listeners) {
list = listeners.toArray(list);
} for (int i = 0; i < list.length; i++){
(list[i]).sessionEvent(event);
} }

3.Manager是一个Session管理器组件负责管理Session对象。提供了getContainer()和setContainer()方法,以便于一个容器相关联,createSession()方法用来创建Session实例。add方法将Session添加到session池中。其中load和unload用来将session对象持久化处理,unload将会包session对象存储到指定介质,load将session对象加载到内存中。

4.ManagerBase实现了Manager接口并实现了一些方法。

/**
* The default maximum inactive interval for Sessions created by
* this Manager.
* session默认有效时间30分钟
*/
protected int maxInactiveInterval = 30 * 60;
/**
* The set of currently active Sessions for this Manager, keyed by
* session identifier.
* session池
*/
protected Map<String, Session> sessions = new ConcurrentHashMap<String, Session>();
/**
* Invalidate all sessions that have expired.
* 判断所有的session是否失效,实现原理是通过一个线程定期检查。
*/
public void processExpires() { long timeNow = System.currentTimeMillis();
Session sessions[] = findSessions();
int expireHere = 0 ; if(log.isDebugEnabled())
log.debug("Start expire sessions " + getName() + " at " + timeNow + " sessioncount " + sessions.length);
for (int i = 0; i < sessions.length; i++) {
if (sessions[i]!=null && !sessions[i].isValid()) {
expireHere++;
}
}
long timeEnd = System.currentTimeMillis();
if(log.isDebugEnabled())
log.debug("End expire sessions " + getName() + " processingTime " + (timeEnd - timeNow) + " expired sessions: " + expireHere);
processingTime += ( timeEnd - timeNow ); }
//添加session
public void add(Session session) { sessions.put(session.getIdInternal(), session);
int size = getActiveSessions();
if( size > maxActive ) {
synchronized(maxActiveUpdateLock) {
if( size > maxActive ) {
maxActive = size;
}
}
}
}

5.StandardManager实现了Manager接口,实现了session可持久化。

protected String pathname = "SESSIONS.ser";//session持久化的文件
//修改
public void setPathname(String pathname) { String oldPathname = this.pathname;
this.pathname = pathname;
//触发属性修改监听
support.firePropertyChange("pathname", oldPathname, this.pathname); }

6.Store用于存储session和用户数据

/*
Save the specified Session into this Store. Any previously saved
* information for the associated session identifier is replaced.
*/
public void save(Session session) throws IOException;
/**
* Remove all Sessions from this Store.
*/
public void clear() throws IOException;
public Session load(String id)
throws ClassNotFoundException, IOException;

总结:tomcat使用监听的事件比较多,对一些属性的修改都进行了监听,使用的非常巧妙。

Tomcat学习笔记(九)的更多相关文章

  1. 多线程学习笔记九之ThreadLocal

    目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...

  2. MDX导航结构层次:《Microsoft SQL Server 2008 MDX Step by Step》学习笔记九

    <Microsoft SQL Server 2008 MDX Step by Step>学习笔记九:导航结构层次   SQL Server 2008中SQL应用系列及BI笔记系列--目录索 ...

  3. python3.4学习笔记(九) Python GUI桌面应用开发工具选择

    python3.4学习笔记(九) Python GUI桌面应用开发工具选择 Python GUI开发工具选择 - WEB开发者http://www.admin10000.com/document/96 ...

  4. Go语言学习笔记九: 指针

    Go语言学习笔记九: 指针 指针的概念是当时学C语言时了解的.Go语言的指针感觉与C语言的没啥不同. 指针定义与使用 指针变量是保存内存地址的变量.其他变量保存的是数值,而指针变量保存的是内存地址.这 ...

  5. go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin)

    目录 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin) zipkin使用demo 数据持久化 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin ...

  6. Python学习笔记九

    Python学习笔记之九 为什么要有操作系统 管理硬件,提供接口. 管理调度进程,并且将多个进程对硬件的竞争变得有序. 操作系统发展史 第一代计算机:真空管和穿孔卡片 没有操作系统,所有的程序设计直接 ...

  7. vue学习笔记(九)vue-cli中的组件通信

    前言 在上一篇博客vue学习笔记(八)组件校验&通信中,我们学会了vue中组件的校验和父组件向子组件传递信息以及子组件通知父组件(父子组件通信),上一篇博客也提到那是对组件内容的刚刚开始,而本 ...

  8. C#线程学习笔记九:async & await入门二

    一.异步方法返回类型 只能返回3种类型(void.Task和Task<T>). 1.1.void返回类型:调用方法执行异步方法,但又不需要做进一步的交互. class Program { ...

  9. java jvm学习笔记九(策略文件)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao/article/details/8271407 课程源码:http://download.csdn.net/detail ...

随机推荐

  1. zip压缩工具,unzip解压缩工具

    zip压缩工具,unzip解压缩工具=================== [root@aminglinux tmp]# yum install -y zip[root@aminglinux tmp] ...

  2. php-语言参考-基本语法3.1

    一,PHP代码的开始和结束标记 1,<?php 和 ?> //重点 2,<script language="php"> 和 </script> ...

  3. Ado访问sqlserver 端口号非1433时 连接串的写法

    Provider=SQLOLEDB.;Persist Security Info=False;Data Source=hostName,Port //注意用 逗号分隔主机名与端口号

  4. 【机器学习算法基础+实战系列】KNN算法

    k 近邻法(K-nearest neighbor)是一种基本的分类方法 基本思路: 给定一个训练数据集,对于新的输入实例,在训练数据集中找到与该实例最邻近的k个实例,这k个实例多数属于某个类别,就把输 ...

  5. poj 1611 dsu

    The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 35918   Accepted: 17458 De ...

  6. python使用网易邮箱发邮件

    # -*- coding: UTF-8 -*- import smtplib from email.mime.text import MIMEText import email.mime.multip ...

  7. tomcat7 配置 https安全访问

    在apache-tomcat-7.0.33-windows-x64.zip配置https,结果在配置SSL时遇到一些问题 1.用JDK自带的keytool来生成私有密钥和自签发的证书,如下: keyt ...

  8. error LNK2001: unresolved external symbol @__security_check_cookie

    Q:VS2005编译的静态库, 在vc++6.0中连接出现错误 error LNK2001: unresolved external symbol @__security_check_cookie@l ...

  9. Android学习记录(2)—Android中数据库的常见操作

    android中数据库操作是非常常见了,我们会经常用到,操作的方法也有很多种形式,这里我就把最常见的两种形式记录下来了,以备以后用到方便查看.我就不写注释和解释了,因为android数据库的操作和其它 ...

  10. 关于safaire下hash前面需要加/(正斜杠)

    就是我们1.1框架是根据hash跳转的,今天我2.0跳转到1.1,pc一直测下来都是好的, 然后发现手机上一直跳转有问题,然后排查了半小时左右才发现  hash前面需要加/ 分割. 例如:http:/ ...