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使用监听的事件比较多,对一些属性的修改都进行了监听,使用的非常巧妙。