1、提供shrio用reids对缓存的管理支持
shiro提供了缓存的接口
package org.apache.shiro.cache;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
public interface CacheManager {
<K, V> Cache<K, V> getCache(String var1) throws CacheException;
}
类之间的继承

简单实现如下:
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
public class JedisCacheManager implements CacheManager {
private JedisManager jedisManager;
@Override
public <K, V> Cache<K, V> getCache(String s) throws CacheException {
return new JedisShiroCache<>(s,getJedisManager());
}
public JedisManager getJedisManager() {
return jedisManager;
}
public void setJedisManager(JedisManager jedisManager) {
this.jedisManager = jedisManager;
}
}
因为CacheManager接口中,也需要有Cache<K,V>的相应实现类
Cache<K,V>接口详情
import java.util.Collection;
import java.util.Set;
import org.apache.shiro.cache.CacheException;
public interface Cache<K, V> {
V get(K var1) throws CacheException;
V put(K var1, V var2) throws CacheException;
V remove(K var1) throws CacheException;
void clear() throws CacheException;
int size();
Set<K> keys();
Collection<V> values();
}
我自己实现的类之间的继承关系

JedisShiroCache的结构详情:
有些方法是未实现的,因为redis里面找到所有已 *key* 开头的缓存,暂时没有找到好的方案,(jedis提供了keys 这个方法,但是返回的是 Set<String>)
import com.nanc.common.utils.SerializeUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import java.util.Collection;
import java.util.Set;
/**
* 因为该用redis做缓存
* 故自己实现shiro的cache接口
* Created by chennan on 2016/11/26.
*/
public class JedisShiroCache<K,V> implements Cache<K,V> {
private JedisManager jedisManager;
private String name;
/**
* 为了不和其他的缓存混淆,采用追加前缀方式以作区分
*/
private static final String REDIS_SHIRO_CACHE = "nanc-shiro-cache:";
private static final String REDIS_SHIRO_CACHE_PATTEN = "*nanc-shiro-cache:*";
private static final int CACHE_VAL_TIME_SPAN = 3600; //chache设置过期时间,防止长久未用,占用空间
public JedisShiroCache(String nanme,JedisManager jedisManager) {
this.name = nanme;
this.jedisManager = jedisManager;
}
@Override
public V get(K k) throws CacheException {
byte[] valByte = new byte[0];
try {
// valByte = getJedisManager().get(SerializeUtil.serialize(buildCacheKey(k))); 不用这种方法存key,因为为放入reids后,前面有部分乱码
valByte = getJedisManager().get(buildCacheKey(k).getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return (V) SerializeUtil.deserialize(valByte);
}
@Override
public V put(K k, V v) throws CacheException {
// byte[] kByte = SerializeUtil.serialize(buildCacheKey(k));
V previos = get(k);
byte[] kByte = buildCacheKey(k).getBytes();
byte[] vBytes = SerializeUtil.serialize(v);
try {
getJedisManager().set(kByte, vBytes);
getJedisManager().expire(kByte,CACHE_VAL_TIME_SPAN);
} catch (Exception e) {
e.printStackTrace();
}
return previos;
}
@Override
public V remove(K k) throws CacheException {
V v = get(k);
try {
// getJedisManager().del(SerializeUtil.serialize(buildCacheKey(k)));
getJedisManager().del(buildCacheKey(k).getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return v;
}
@Override
public void clear() throws CacheException {
/**
* 以正则形式找到所有的key,然后分别删除
*/
Set<String> set = getJedisManager().keys(REDIS_SHIRO_CACHE_PATTEN);
if (CollectionUtils.isNotEmpty(set)) {
for(String s : set){
try {
getJedisManager().del(s.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Override
public int size() {
return 0;
}
@Override
public Set<K> keys() {
Set<String> set = getJedisManager().keys(REDIS_SHIRO_CACHE_PATTEN);
return (Set<K>) set;
}
@Override
public Collection<V> values() {
return null;
}
public JedisManager getJedisManager() {
return jedisManager;
}
public void setJedisManager(JedisManager jedisManager) {
this.jedisManager = jedisManager;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String buildCacheKey(Object key) {
return REDIS_SHIRO_CACHE + getName() + ":" + key;
}
}
2、提供shiro用redis对session的管理

我们只需继承或者AbstractSessionDAO或者CachingSessionDAO即可
我的类之间继承结构如下

MySessionDAO详情如下
package com.nanc.core.shiro.dao;
import com.nanc.core.shiro.session.ShiroSession;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import java.io.Serializable;
import java.util.Collection;
public class MySessionDAO extends AbstractSessionDAO {
private ShiroSession shiroSession;
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = doCreate(session);
this.assignSessionId(session, sessionId);
shiroSession.saveSession(session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable serializable) {
return shiroSession.getSession(serializable);
}
@Override
public void update(Session session) throws UnknownSessionException {
shiroSession.saveSession(session);
}
@Override
public void delete(Session session) {
if (session == null) {
System.out.println("session为空了");
return;
}
Serializable id = session.getId();
if (id != null)
shiroSession.deleteSession(id);
}
@Override
public Collection<Session> getActiveSessions() {
return shiroSession.getAllSessions();
}
public ShiroSession getShiroSession() {
return shiroSession;
}
public void setShiroSession(ShiroSession shiroSession) {
this.shiroSession = shiroSession;
}
}
为了便于扩展,特抽取接口,对session进行相应的crud操作
结构如下:

ShiroSession详情
import org.apache.shiro.session.Session;
import java.io.Serializable;
import java.util.Collection;
/**
* 自定义shiro session的管理接口
*
*/
public interface ShiroSession {
/**
* 存储Session
* @param session
*/
void saveSession(Session session);
/**
* 删除session
* @param sessionId
*/
void deleteSession(Serializable sessionId);
/**
* 获取session
* @param sessionId
* @return
*/
Session getSession(Serializable sessionId);
/**
* 获取所有sessoin
* @return
*/
Collection<Session> getAllSessions();
}
相应ShiroSession的实现类ShiroSessionRepository
import com.nanc.common.utils.SerializeUtil;
import com.nanc.core.shiro.cache.JedisManager;
import com.nanc.core.shiro.session.ShiroSession;
import org.apache.shiro.session.Session;
import redis.clients.jedis.Jedis;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class ShiroSessionRepository implements ShiroSession {
private JedisManager jedisManager;
public static final String REDIS_SHIRO_SESSION = "nanc-shiro-session:";
//这里有个小BUG,因为Redis使用序列化后,Key反序列化回来发现前面有一段乱码,解决的办法是存储缓存不序列化
public static final String REDIS_SHIRO_ALL = "*nanc-shiro-session::*";
private static final int SESSION_VAL_TIME_SPAN = 18000;
@Override
public void saveSession(Session session) {
if (null == session || null == session.getId()) {
throw new NullPointerException("session is empty");
}
try {
byte[] key = SerializeUtil.serialize(buildRedisSessionKey(session.getId()));
byte[] value = SerializeUtil.serialize(session);
long sessionTimeOut = session.getTimeout() / 1000;
Long expireTime = sessionTimeOut + SESSION_VAL_TIME_SPAN + (5 * 60);
getJedisManager().set(key, value);
getJedisManager().expire(key,expireTime.intValue());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void deleteSession(Serializable sessionId) {
if (null == sessionId) {
throw new NullPointerException("sessionId 为空");
}
try {
getJedisManager().del(SerializeUtil.serialize(buildRedisSessionKey(sessionId)));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Session getSession(Serializable sessionId) {
if (null == sessionId) {
throw new NullPointerException("sessionId 为空");
}
Session session = null;
try {
byte[] objByte = getJedisManager().get(SerializeUtil.serialize(buildRedisSessionKey(sessionId)));
session = SerializeUtil.deserialize(objByte,Session.class);
} catch (Exception e) {
e.printStackTrace();
}
return session;
}
@Override
public Collection<Session> getAllSessions() {
Jedis jedis = null;
Set<Session> sessions = new HashSet<>();
try {
jedis = getJedisManager().getJedis();
Set<byte[]> byteKeys = jedis.keys((REDIS_SHIRO_ALL).getBytes());
if (byteKeys != null && byteKeys.size() > 0) {
for (byte[] bs : byteKeys) {
Session obj = SerializeUtil.deserialize(jedis.get(bs),Session.class);
if(obj instanceof Session){
sessions.add(obj);
}
}
}
} catch (Exception e) {
throw e;
} finally {
getJedisManager().returnResource(jedis);
}
return sessions;
}
public JedisManager getJedisManager() {
return jedisManager;
}
public void setJedisManager(JedisManager jedisManager) {
this.jedisManager = jedisManager;
}
private String buildRedisSessionKey(Serializable sessionId) {
return REDIS_SHIRO_SESSION + sessionId;
}
}
浙公网安备 33010602011771号