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; }
3.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); }