apache shiro分布式session共享实战(redis版)

源码下载:http://pan.baidu.com/s/1ntD0BwP

1、原理

     所有session集中管理,根据sessionId做标识,session对象用objectStream做序列化,缓存到redis中

2、环境搭建

     ①配置jdk7、gradle2.2.1、redis3.0.4环境;

     ②在java代码中配置org.demo.shiro.rediscache.RedisClient.redisServerIp

3、运行shiro-redis-session\gradle-jettyRun.bat(不用打开eclipse)

4、关键代码分析(重写shiro的会话dao)

package org.demo.shiro.rediscache;

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

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RedisSessionDao extends AbstractSessionDAO {
	private RedisClient sessionCacheClient=new RedisClient();

	Logger log= LoggerFactory.getLogger(getClass());
	@Override
	public void update(Session session) throws UnknownSessionException {
		log.info("更新seesion,id=[{}]",session.getId().toString());
		 try {  
	            sessionCacheClient.replace(session.getId().toString(), session);  
	        } catch (Exception e) {  
	           e.printStackTrace(); 
	        }  
	}

	@Override
	public void delete(Session session) {
		log.info("删除seesion,id=[{}]",session.getId().toString());
		 try {  
	            sessionCacheClient.delete(session.getId().toString());  
	        } catch (Exception e) {  
	           e.printStackTrace(); 
	        }  
		
	}

	@Override
	public Collection<Session> getActiveSessions() {
		log.info("获取存活的session");
		 return Collections.emptySet(); 
	}

	@Override
	protected Serializable doCreate(Session session) {
		Serializable sessionId = generateSessionId(session);  
        assignSessionId(session, sessionId);  
        log.info("创建seesion,id=[{}]",session.getId().toString());
        try {  
            sessionCacheClient.set(sessionId.toString(),  session);  
        } catch (Exception e) {  
            log.error(e.getMessage());  
        }  
        return sessionId;  
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		
		log.info("获取seesion,id=[{}]",sessionId.toString());
		Session session = null;  
        try {  
            session = (Session) sessionCacheClient.get(sessionId.toString());  
        } catch (Exception e) {  
            log.error(e.getMessage());  
        }  
        return session;  
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<bean id="myRealm" class="org.demo.shiro.MyRealm" />
	<!-- 会话管理器 -->
	<bean id="sessionManager"
		class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
		<property name="sessionValidationSchedulerEnabled" value="false" />
		<property name="sessionDAO" ref="sessionDAO" />
		<property name="globalSessionTimeout" value="60000" />
	</bean>
	<bean id="sessionDAO" class="org.demo.shiro.rediscache.RedisSessionDao"></bean>

	<!-- 安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="sessionManager" ref="sessionManager" />
		<!-- <property name="cacheManager" ref="shiroCacheManager" /> -->
		<property name="realm" ref="myRealm" />
	</bean>
	<bean id="shiroFilter" class="org.demo.shiro.MyShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<property name="loginUrl" value="/" />
		<!-- <property name="successUrl" value="/system/main"/> -->
		<property name="unauthorizedUrl" value="/" />
	</bean>

	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />



</beans>

package org.demo.shiro.rediscache;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import org.apache.shiro.codec.Base64;
import org.apache.shiro.session.Session;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisClient {

	private static JedisPool pool;
	private static String redisServerIp="124.193.90.xx";

	/**
	 * 建立连接池 真实环境,一般把配置参数缺抽取出来。
	 * 
	 */
	private static void createJedisPool() {

		// 建立连接池配置参数
		JedisPoolConfig config = new JedisPoolConfig();

		// 设置最大连接数
		config.setMaxActive(1000);

		// 设置最大阻塞时间,记住是毫秒数milliseconds
		config.setMaxWait(1000);

		// 设置空间连接
		config.setMaxIdle(10);

		// 创建连接池
		pool = new JedisPool(config, redisServerIp, 6379);

	}

	/**
	 * 在多线程环境同步初始化
	 */
	private static synchronized void poolInit() {
		if (pool == null)
			createJedisPool();
	}

	/**
	 * 获取一个jedis 对象
	 * 
	 * @return
	 */
	private static Jedis getJedis() {

		if (pool == null)
			poolInit();
		return pool.getResource();
	}

	/**
	 * 归还一个连接
	 * 
	 * @param jedis
	 */
	private static void returnRes(Jedis jedis) {
		pool.returnResource(jedis);
	}

	void set(String sessionId, Session session) {
		jedis = getJedis();
		jedis.append(sessionId, serialize(session));
		returnRes(jedis);
	}

	void replace(String sessionId, Session session) {
		set(sessionId, session);

	}

	Jedis jedis = null;

	void delete(String sessionId) {
		jedis = getJedis();
		jedis.del(sessionId);
		returnRes(jedis);
	}

	Object get(String sessionId) {
		jedis = getJedis();
		Object obj = deserialize(jedis.get(sessionId));
		returnRes(jedis);
		return obj;
	}

	private static Object deserialize(String str) {
		ByteArrayInputStream bis = null;
		ObjectInputStream ois = null;
		try {
			bis = new ByteArrayInputStream(Base64.decode(str));
			ois = new ObjectInputStream(bis);
			return ois.readObject();
		} catch (Exception e) {
			throw new RuntimeException("deserialize session error", e);
		} finally {
			try {
				ois.close();
				bis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
	}

	private static String serialize(Object obj) {
		ByteArrayOutputStream bos = null;
		ObjectOutputStream oos = null;
		try {
			bos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(bos);
			oos.writeObject(obj);
			return Base64.encodeToString(bos.toByteArray());
		} catch (Exception e) {
			throw new RuntimeException("serialize session error", e);
		} finally {
			try {
				oos.close();
				bos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
	}

}


5、上图:


  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shiro-Redis 是一个用于在 Shiro 中实现 Session 共享的插件,它使用 Redis 作为数据存储和缓存,以实现分布式环境下的 Session 共享。 要实现 Shiro-RedisSession 共享,你需要进行以下步骤: 1. 引入 Shiro-Redis 插件依赖:在项目的 Maven 或 Gradle 配置文件中添加 Shiro-Redis 依赖。 2. 配置 Redis 连接信息:在项目的配置文件中配置 Redis 的连接信息,包括主机名、端口号、密码等。 3. 配置 RedisSessionDAO:在 Shiro 的配置文件中配置 RedisSessionDAO,指定使用 Redis 作为 Session 存储和缓存的实现。可以设置过期时间、前缀等参数。 4. 配置 Session Manager:在 Shiro 的配置文件中配置 Session Manager,指定使用自定义的 RedisSessionManager 作为 Session 的管理器。同时,需要将之前配置的 RedisSessionDAO 设置给 RedisSessionManager。 5. 配置 SecurityManager:在 Shiro 的配置文件中配置 SecurityManager,指定使用自定义的 RedisSessionManager 作为 Session 管理器。同时,需要将之前配置的 RedisSessionDAO 设置给 RedisSessionManager。 6. 配置 Filter Chain:在 Shiro 的配置文件中配置 Filter Chain,将自定义的 RedisSessionManager 添加到 Filter Chain 中,以便对请求进行 Session 管理。 通过以上步骤配置完成后,Shiro 将会使用 Redis 进行 Session 的存储和缓存,从而实现 Session共享。在分布式环境中,不同应用节点之间可以通过 Redis 共享 Session 数据,从而实现用户的登录状态和会话信息的共享

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值