[置顶] apache shiro分布式session共享实战(redis版)

时间:2020-11-30 17:27:12

源码下载: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、上图:

[置顶]        apache shiro分布式session共享实战(redis版)