Catalina通过一个叫管理器的组建来完成Session的管理。该管理器由一个接口Interface表示。
一个管理器通常和一个上下文容器相互管理,它负责创建,更新以及销毁session对象并给
任何请求组件返回一个合法的session.

一个servlet可以使用getSession方法获得一个session对象,该方法在javax.servlet.http.HttpServletRequest定义
它在默认连接器里由org.apache.catalina.connector.HttpRequestBase类实现

public HttpSession getSession() {
	return (getSession(true));
}
public HttpSession getSession(boolean create) {
	....
	return doGetSession(create);
}
private HttpSession doGetSession(boolean create) {
	if (context == null)
		return (null);
	if ((session != null) && !session.isValid())
		session = null;
	if (session != null)
		return (session.getSession());
	Manager manager = null;
	if (context != null)
		manager = context.getManager();
	if (manager == null)
		return (null);
	if (requestedSessionId != null) {
		try {
			session = manager.findSession(requestedSessionId);
		}catch (IOException e) {
			session = null;
		}
		if ((session != null) && !session.isValid())
			session = null;
		
		if (session != null) {
			return (session.getSession());
		}
	}

	if (!create)
		return (null);
	if (session != null)
		return (session.getSession());
	else
		return (null);
}

 

默认情况下管理器将session对象存储在内存中,但是Tomcat也允许将session对象存储在文件或者数据库中(通过JDBC)

Sessions

在servlet编程中,一个session对象使用javax.servlet.http.HttpSession接口表示。该接口的标准实现是StandardSession类
由于一个Session对象常常被一个管理器持有,所以接口提供了setManager和getManager方法来关联一个Session对象和一个管理器
一个Session实例在跟管理器相关联的容器有一个唯一的ID。
StandardSession类
StandardSession类是Session接口的标准是实现。
实现了javax.servlet.http.HttpSession 和org.apache.catalina.Session之外,
它还实现了java.lang.Serializable接口来使得Session对象可序列化。
接下来是几个重要的变量在存放Session状态。注意transient使得该关键字不可序列化。

private HashMap attributes = new HashMap();
private transient String authType = null;
private transient boolean expiring = false;
private transient StandardSessionFacade facade = null;


一个Session对象如果在由maxInactiveInterval变量的时间内没有被进入则被终结。
使用Session接口中定义的expire方法可以终结一个Session对象

 

 

public void expire(boolean notify) {

        // Mark this session as "being expired" if needed
        if (expiring)
            return;
        expiring = true;
        setValid(false);

        // Remove this session from our manager's active sessions
        if (manager != null)
            manager.remove(this);

        // Unbind any objects associated with this session
        String keys[] = keys();
        for (int i = 0; i < keys.length; i++)
            removeAttribute(keys[i], notify);

        // Notify interested session event listeners
        if (notify) {
            fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
        }

        // Notify interested application event listeners
        // FIXME - Assumes we call listeners in reverse order
        Context context = (Context) manager.getContainer();
        Object listeners[] = context.getApplicationListeners();
        if (notify && (listeners != null)) {
            HttpSessionEvent event =
              new HttpSessionEvent(getSession());
            for (int i = 0; i < listeners.length; i++) {
                int j = (listeners.length - 1) - i;
                if (!(listeners[j] instanceof HttpSessionListener))
                    continue;
                HttpSessionListener listener =
                    (HttpSessionListener) listeners[j];
                try {
                    fireContainerEvent(context,
                                       "beforeSessionDestroyed",
                                       listener);
                    listener.sessionDestroyed(event);
                    fireContainerEvent(context,
                                       "afterSessionDestroyed",
                                       listener);
                } catch (Throwable t) {
                    try {
                        fireContainerEvent(context,
                                           "afterSessionDestroyed",
                                           listener);
                    } catch (Exception e) {
                        ;
                    }
                    // FIXME - should we do anything besides log these?
                    log(sm.getString("standardSession.sessionEvent"), t);
                }
            }
        }

        // We have completed expire of this session
        expiring = false;
        if ((manager != null) && (manager instanceof ManagerBase)) {
            recycle();
        }

    }

 

管理器
管理器用来管理Session对象
管理器由org.apache.catalina.Manager接口表示
ManagerBase类有两个直接子类:StandardManager和PersistentManagerBase类。
在运行的时候,StandardManager将session对象存放在内存中。
但是,当停止的时候,它将Session对象存放到文件中。当它再次启动的时候,重新载入Session对象。
PersistentManagerBase类作为一个管理器组件将Session对象存放到二级存储器中。
它有两个直接子类:PersistentManager和DistributedManager类