Tomcat中的session实现

Tomcat中一个会话对应一个session,其实现类是StandardSession,查看源码,可以找到一个attributes成员属性,即存储session的数据结构,为ConcurrentHashMap,支持高并发的HashMap实现;

/**
* The collection of user data attributes associated with this Session.
*/
protected Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();

那么,tomcat中多个会话对应的session是由谁来维护的呢?ManagerBase类,查看其代码,可以发现其有一个sessions成员属性,存储着各个会话的session信息:

/**
    * The set of currently active Sessions for this Manager, keyed by
    * session identifier.
    */
protected Map<String, Session> sessions = new ConcurrentHashMap<String, Session>();

接下来,看一下几个重要的方法,

服务器查找Session对象的方法

客户端每次的请求,tomcat都会在HashMap中查找对应的key为JSESSIONID的Session对象是否存在,可以查看Request的doGetSession方法源码,如下源码:

先看doGetSession方法中的如下代码,这个一般是第一次访问的情况,即创建session对象,session的创建是调用了ManagerBase的createSession方法来实现的; 另外,注意response.addSessionCookieInternal方法,该方法的功能就是上面提到的往响应头写入“Set-Cookie”信息;最后,还要调用session.access方法记录下该session的最后访问时间,因为session是可以设置过期时间的

session = manager.createSession(sessionId);

// Creating a new session cookie based on that session
if ((session != null) && (getContext() != null)
        && getContext().getServletContext().
                getEffectiveSessionTrackingModes().contains(
                        SessionTrackingMode.COOKIE)) {
    Cookie cookie =
        ApplicationSessionCookieConfig.createSessionCookie(
                context, session.getIdInternal(), isSecure());

    response.addSessionCookieInternal(cookie);
}

if (session == null) {
    return null;
}

session.access();
return session;

再看doGetSession方法中的如下代码,这个一般是第二次以后访问的情况,通过ManagerBase的findSession方法查找session,其实就是利用map的key从ConcurrentHashMap中拿取对应的value,这里的key即requestedSessionId,也即JSESSIONID,同时还要调用session.access方法,记录下该session的最后访问时间;

if (requestedSessionId != null) {
    try {
        session = manager.findSession(requestedSessionId);
    } catch (IOException e) {
        session = null;
    }
    if ((session != null) && !session.isValid()) {
        session = null;
    }
    if (session != null) {
        session.access();
        return (session);
    }
}

在session对象中查找和设置key-value的方法

这个我们一般调用getAttribute/setAttribute方法:

getAttribute方法很简单,就是根据key从map中获取value;

setAttribute方法稍微复杂点,除了设置key-value外,如果添加了一些事件监听(HttpSessionAttributeListener)的话,还要通知执行,如beforeSessionAttributeReplaced, afterSessionAttributeReplaced, beforeSessionAttributeAdded、 afterSessionAttributeAdded。。。

猜你喜欢

转载自www.cnblogs.com/frankyou/p/9066416.html