分布式Session

分布式session

          单服务器web应用中,session信息只需存在该服务器中,随着分布式系统的流行,单系统已经不能满足日益增长的百万级用户的需求,集群方式部署服务器已在很多公司运用起来,当高并发量的请求到达服务端的时候通过负载均衡的方式分发到集群中的某个服务器,这样就有可能导致同一个用户的多次请求被分发到集群的不同服务器上,就会出现取不到session数据的情况,于是出现了分布式Session。

将session存储在一个中间件 例如存储在 redis中,这样解决了由于服务器不同而取不到session值的问题。

Shiro-Redis-Session:

SimpleSession : Session类型

SessionFactory : 直属SessionManager,默认为SimpleSessionFactory ,负责创建Session对象,默认为SimpleSession

SessionDAO : 直属SessionManager,负责将每个Session对象存储起来,需要定制这个组件,以集成redis

SessionManager : 直属SecurityManager,负责管理Session处理的核心调度过程。

 

定义SessionDAO:

// 定义SessionDAO,负责存储Session对象
public class MySessionDAO extends AbstractSessionDAO {
    private RedisTemplate template;//需要注入RedisTemplate,以支持后续的Redis通信
    public RedisTemplate getTemplate() {
        return template;
    }
    public void setTemplate(RedisTemplate template) {
        this.template = template;
    }

    //将Session对象存入redis;(由SimpleSessionFactory创建的Session对象)
    protected Serializable doCreate(Session session) {
		// 生成sessionID
        Serializable sessionId = generateSessionId(session);
        //存入redis
        System.out.println("save session to redis");
        assignSessionId(session,sessionId);// 将sessionID赋值给Session对象
        // key = 前缀+sessionID  ;  value = session对象
        template.opsForValue().set("session"+sessionId,session);//将Session对象存入Redis,存入时定义了"前缀"
        return sessionId;
    }

    //从redis获取session对象,供项目使用
    @Override
    protected Session doReadSession(Serializable sessionId) {
        // 从redis获取session,获取时,也要定义 “前缀”; [前缀+sessionID]
        Session session = (Session)template.opsForValue().get("session"+sessionId);
        return session;
    }

    //session中数据变动时,要将session对象同步到redis
    @Override
    public void update(Session session) throws UnknownSessionException {
        System.out.println("update session");
        Serializable sessionId = session.getId();
        // 将session,覆盖存储到Redis
        template.opsForValue().set("session"+sessionId,session);
    }

    //session过期时,从redis中删除session
    @Override
    public void delete(Session session) {
        Serializable sessionId = session.getId();//获取sessionID
        // 从redis删除session
        template.delete("session"+sessionId);
    }

    //session检测时,需要获取所有session
    @Override
    public Collection<Session> getActiveSessions() {
        //从redis获取全部或部分session
        Set keys = template.keys("session*");//通过前缀获取Session
        List<Session> list = template.opsForValue().multiGet(keys);
        return list;
    }
}

配置SessionDAO:

 

将SessionDAO注册在SessionManager中

SessionManager注册在SecurityManager中

注意RedisTemplate的序列化方式

<!-- SessionManager,使用Shiro的DefaultWebSessionManager即可,其中注入自定义的SessionDAO -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    <!-- 注册SessionDAO,负责将Session对象存入redis -->
    <property name="sessionDAO">
        <bean class="com.zhj.dao.MySessionDAO">
            <property name="template" ref="redisTemplate2"/>
        </bean>
    </property>
</bean>

<!-- 注意:此RedisTemplate key序列化采用String序列化, 
          value没有使用Jackson或FastJson序列化,而是采用的默认的Jdk的序列化 -->
<bean id="ss" class="org.springframework.data.redis.serializer.StringRedisSerializer" />
<bean id="redisTemplate2" class="org.springframework.data.redis.core.RedisTemplate"
      p:connectionFactory-ref="jedisConnectionFactory"
      p:keySerializer-ref="ss"/>

<!-- Securitymanager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="myRealm"/>
    <!-- 注册cacheManager -->
    <property name="cacheManager" ref="cacheManager03"/>
    <!-- 注册sessionManager,其中会调度SessionDAO,将session存入Redis -->
    <property name="sessionManager" ref="sessionManager"/>
</bean>

  

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值