原文地址:https://www.cnblogs.com/youzhibing/p/9749427.html

前情回顾

  shiro的session创建session的查询、更新、过期、删除中,shiro对session的操作基本都讲到了,但还缺一个session共享没有讲解;session共享的原理其实在自定义session管理一文已经讲过了,本文不讲原理,只看看shiro的session共享的实现。

  为何需要session共享

    如果是单机应用,那么谈不上session共享,session放哪都无所谓,不在乎放到默认的servlet容器中,还是抽出来放到单独的地方;

    也就是说session共享是针对集群(或分布式、或分布式集群)的;如果不做session共享,仍然采用默认的方式(session存放到默认的servlet容器),当我们的应用是以集群的方式发布的时候,同个用户的请求会被分发到不同的集群节点(分发依赖具体的负载均衡规则),那么每个处理同个用户请求的节点都会重新生成该用户的session,这些session之间是毫无关联的。那么同个用户的请求会被当成多个不同用户的请求,这肯定是不行的。

  如何实现session共享

    实现方式其实有很多,甚至可以不做session共享,具体有哪些,大家自行去查资料。本文提供一种方式:redis实现session共享,就是将session从servlet容器抽出来,放到redis中存储,所有集群节点都从redis中对session进行操作。

SessionDAO

  SessionDAO其实是用于session持久化的,但里面有缓存部分,具体细节我们往下看

  shiro已有SessionDAO的实现如下

shiro源码篇 - shiro的session共享,你值得拥有

  SessionDAO接口提供的方法如下

shiro源码篇 - shiro的session共享,你值得拥有
package org.apache.shiro.session.mgt.eis;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;

import java.io.Serializable;
import java.util.Collection;


/**
 * 从EIS操作session的规范(EIS:例如关系型数据库, 文件系统, 持久化缓存等等, 具体依赖DAO实现)
 * 提供了典型的CRUD的方法:create, readSession, update, delete
 */
public interface SessionDAO {

    /**
     * 插入一个新的sesion记录到EIS 
     */
    Serializable create(Session session);

    /**
     * 根据会话ID获取会话
     */
    Session readSession(Serializable sessionId) throws UnknownSessionException;

    /**
     * 更新session; 如更新session最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
     */
    void update(Session session) throws UnknownSessionException;

    /**
     * 删除session; 当会话过期/会话停止(如用户退出时)会调用
     */
    void delete(Session session);

    /**
     * 获取当前所有活跃session, 所有状态不是stopped/expired的session
     * 如果用户量多此方法影响性能
     */
    Collection<Session> getActiveSessions();
}

相关文章: