Tomcat中session的实现方式

一、基础姿势

session依赖于cookie,当cookie被禁用的时候将尝试使用url传递jsessionid

例如:/sign_in;jsessionid=7ba49c313a84295770fecbd01e86f116166sc5feg5yhzwis9zayzx492

二、tomcat中的实现

tomcat的核心jar:lib/catalina.jar,session的实现位于org.apache.catalina.session包中。

Session默认储存在内存中、file、db(以上三种tomcat、jetty均有实现,具体配置请百度)或者继承StoreBase扩展到cache中。

session核心代码列举(ManagerBase.java):

protected Map sessions;
// ManagerBase 161行 
this.sessions = new ConcurrentHashMap();

public void add(Session session) {
    this.sessions.put(session.getIdInternal(), session);
    int size = getActiveSessions();
    if (size > this.maxActive) {
      synchronized (this.maxActiveUpdateLock) {
        if (size > this.maxActive) {
          this.maxActive = size;
        }
      }
    }
}

可以看出session实际是存储于一个map中,以sessionid作为key,value则为一个session对象。

然而session又是一个key,value的对象,当然实际实现略显复杂。StandardSession为tomcat中的具体实现。我们可以简单的将他理解成一个Map<String, Map>的结构。

三、动手使用cookie + ehcache简单实现session

设计Ehcache中的cache结构:cacheName:session,key:xxsessionid,value:map

伪代码,获取session:

getXXSessionAttr(HttpServletRequest request, String sessionKey);

getXXSessionAttr传入request,首先从request中拿到cookie中的xxsessionid:XXSESSIONID

 *注意:此sessionKey表示ehcache中存储的数据(value:map)的key,非ehcacahe的key,cache的key为xxsessionid。

sessionid从cache中找到对应缓存中的map,然后通过sessionKey,找到此次需要获取的数据。

四、session的劣势

重启之后会丢失,分布式下不能共享。将session存入数据库或者扩展到分布式cache中可解决。

或者直接抛弃session,使用纯cookie去维持用户状态。下图是我的一个简单设计:

获取到cookie之后再按照对应的方式解开,拿到userId结合ehcahe,从ehcache中拿取用户信息。这样将userId直接丢到了cookie中即使重启或者是分布式的情况下,cookie并不会丢失。顶多多请求一次数据库而已。

捐助共勉
版权声明:若无特殊注明,本文皆为原创,转载请保留文章出处。