Tomcat中的session是通过一个manager来管理的,其中Session接口默认实现类有StandardSession,管理器的默认实现是StandardManager。
我们平时在servlet中使用的session也就是HashMap中的一个session对象,同时session除了在内存存储,同时还提供了持久化方法,tomcat中持久化有两种,一种是保存为文件,另一种则是保存到数据库。
这一节首先来看一下默认的StandardSession和StandardManager。
public interface Session {
// ----------------------------------------------------- Manifest Constants
public static final String SESSION_CREATED_EVENT = "createSession";
public static final String SESSION_DESTROYED_EVENT = "destroySession";
// ------------------------------------------------------------- Properties
public String getAuthType();
public void setAuthType(String authType);
public long getCreationTime();
public void setCreationTime(long time);
public String getId();
public void setId(String id);
public String getInfo();
public long getLastAccessedTime();
public Manager getManager();
public void setManager(Manager manager);
public int getMaxInactiveInterval();
public void setMaxInactiveInterval(int interval);
public void setNew(boolean isNew);
public Principal getPrincipal();
public void setPrincipal(Principal principal);
public HttpSession getSession();
public void setValid(boolean isValid);
public boolean isValid();
// --------------------------------------------------------- Public Methods
public void access();
public void addSessionListener(SessionListener listener);
public void expire();
public Object getNote(String name);
public Iterator getNoteNames();
public void recycle();
public void removeNote(String name);
public void removeSessionListener(SessionListener listener);
public void setNote(String name, Object value);
}
1.StandardManager中整个启动过程
public void start() throws LifecycleException {
if (debug >= 1)
log("Starting");
// Validate and update our current component state
if (started)
throw new LifecycleException
(sm.getString("standardManager.alreadyStarted"));
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Force initialization of the random number generator
if (debug >= 1)
log("Force random number initialization starting");
String dummy = generateSessionId();
if (debug >= 1)
log("Force random number initialization completed");
// Load unloaded sessions, if any
try {
//用于加载持久化的session,加载以后放入sessions(hashMap)中
load();
} catch (Throwable t) {
log(sm.getString("standardManager.managerLoad"), t);
}
// Start the background reaper thread
threadStart();
}
//启动一个管理器线程,用于实现自动重新加载
private void threadStart() {
if (thread != null)
return;
threadDone = false;
threadName = "StandardManager[" + container.getName() + "]";
thread = new Thread(this, threadName);
thread.setDaemon(true);
thread.setContextClassLoader(container.getLoader().getClassLoader());
thread.start();
}
/**
* The background thread that checks for session timeouts and shutdown.
*/
public void run() {
// Loop until the termination semaphore is set
while (!threadDone) {
threadSleep();
processExpires();
}
}
private void threadSleep() {
try {
Thread.sleep(checkInterval * 1000L);
} catch (InterruptedException e) {
;
}
}
/**
* Invalidate all sessions that have expired.
*/
//管理StandardSession中session,去除无效的session
private void processExpires() {
long timeNow = System.currentTimeMillis();
//获取存活的sessions
Session sessions[] = findSessions();
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
//有效,则不移除
if (!session.isValid())
continue;
int maxInactiveInterval = session.getMaxInactiveInterval();
//如果设置最大存活时间是-1,则不终止
if (maxInactiveInterval < 0)
continue;
int timeIdle = // Truncate, do not round up
(int) ((timeNow - session.getLastAccessedTime()) / 1000L);
if (timeIdle >= maxInactiveInterval) {
try {
session.expire();
} catch (Throwable t) {
log(sm.getString("standardManager.expireException"), t);
}
}
}
}
2.StandardManager中整个停止过程
public void stop() throws LifecycleException {
if (debug >= 1)
log("Stopping");
// Validate and update our current component state
if (!started)
throw new LifecycleException
(sm.getString("standardManager.notStarted"));
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
// Stop the background reaper thread
threadStop();
// Write out sessions
try {
//将存活的session持久化
unload();
} catch (IOException e) {
log(sm.getString("standardManager.managerUnload"), e);
}
// Expire all active sessions
Session sessions[] = findSessions();
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
if (!session.isValid())
continue;
try {
//终止所有的session
session.expire();
} catch (Throwable t) {
;
}
}
// Require a new random number generator if we are restarted
this.random = null;
private void threadStop() {
if (thread == null)
return;
threadDone = true;
//将当前线程设置为中断状态
thread.interrupt();
try {
//当前线程被挂起,直达thread线程结束才运行改线程
thread.join();
} catch (InterruptedException e) {
;
}
thread = null;
}
1.StandardManager中创建一个session
public Session createSession() {
if ((maxActiveSessions >= 0) &&
(sessions.size() >= maxActiveSessions))
throw new IllegalStateException
(sm.getString("standardManager.createSession.ise"));
//实际调用的是ManagerBase中的creatSession()方法
return (super.createSession());
}
//ManagerBase类中creatSession方法
public Session createSession() {
// Recycle or create a Session instance
Session session = null;
synchronized (recycled) {
int size = recycled.size();
if (size > 0) {
session = (Session) recycled.get(size - 1);
recycled.remove(size - 1);
}
}
if (session != null)
session.setManager(this);
else
session = new StandardSession(this);
// Initialize the properties of the new session and return it
session.setNew(true);
session.setValid(true);
session.setCreationTime(System.currentTimeMillis());
session.setMaxInactiveInterval(this.maxInactiveInterval);
String sessionId = generateSessionId();
String jvmRoute = getJvmRoute();
// @todo Move appending of jvmRoute generateSessionId()???
if (jvmRoute != null) {
sessionId += '.' + jvmRoute;
session.setId(sessionId);
}
/*
synchronized (sessions) {
while (sessions.get(sessionId) != null) // Guarantee uniqueness
sessionId = generateSessionId();
}
*/
session.setId(sessionId);
return (session);
}