构建集中式会话的分析与实践(二)

前言

本文继续延伸之前的博客 构建集中式会话的分析与实践(一),主要结合http servlet api & tomcat部分源码 & spring-session项目核心对基于redis存储的集中式会话管理客户端的实现。

Tomcat会话管理源码分析

关于会话相关的接口,主要体现在org.apache.catalina.Manager接口,org.apache.catalina.session.ManagerBase抽象类,org.apache.catalina.Session接口。

其中Manager主要是对会话对象的管理操作,比如:创建会话、添加会话、移除会话、根据会话id查找会话等一系列管理接口,ManagerBase是其实现类,主要实现了大部分接口,所以org.apache.catalina.session.StandardManager需要实现的内容很少;

Session接口主要是会话内部操作Api,如会话创建时间、有效时间、会话id、最大有效时间、最近一次接触时间等,另外还有获取HttpSession的方法等;

看一下Session接口的实现类org.apache.catalina.session.StandardSession;

public class StandardSession implements HttpSession, Session, Serializable {...}

也同时实现了servlet的接口HttpSession。(由此可以看出tomcat是严重依赖于servlet api的)

细看一下具体实现,主要是存储在java内存中的对象ConcurrentHashMap和一些基础类型。

Spring Session源码分析

org.springframework.session.SessionRepository类相当于会话管理接口类(会话仓库接口类),org.springframework.session.Session是会话内部操作类;

org.springframework.session.data.redis.RedisOperationsSessionRepository是会话管理的核心实现类,其内部的org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession是会话操作的核心实现类;

另外,org.springframework.session.MapSession是java内存会话操作类,会话接口的基础实现;

总体来说,Spring Session的会话操作和Tomcat是比较相似的,区别主要在于实现的一些差异,RedisSession依赖于对Redis操作的一些接口,Spring Session直接依赖于Spring-Data-Redis进行redis的操作,另外,对会话的管理,Spring Session做了一些优化,一般情况下进行双写,写入java内存和redis中,这样读取的时候可以直接获取内存中的值,需要注意的是,如果内存写成功,redis操作失败的异常情境。

另外,Spring Session项目也单独集成了Servlet Api,使会话管理更加方便,像传统的调用方式那样:

org.springframework.session.web.http.SessionRepositoryFilter实现了servlet的filter接口,调用封装后的org.springframework.session.web.http.SessionRepositoryFilter.SessionRepositoryRequestWrapper和org.springframework.session.web.http.SessionRepositoryFilter.SessionRepositoryResponseWrapper,并在其内部实现Redis会话的管理。

演示示例:

以下为基于redis的会话管理集成servlet api时的演示示例(手动处理会话方式略麻烦,需要额外处理cookie,就不演示了)。

...
    // 判断会话是否有效,如果有效则返回用户对象
    protected User getUser() {
        HttpSession session = request.getSession(false);
        if (null == session)
            throw new SessionException("用户会话失效!");
        Object user = session.getAttribute("user");
        if (null == user)
            throw new SessionException("用户会话失效!");
        return (User) user;
    }
...
    // 创建会话和设置用户
    User user = createUser();
    request.getSession().setAttribute("user", user);// 默认createIfNX
...
    // 登出,使会话失效
    HttpSession session = request.getSession();
    if (session != null) {
       session.removeAttribute("user");
       session.invalidate();
    }
...

 

转载于:https://my.oschina.net/wnjustdoit/blog/1935868

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值