本系列文章针对的是使用shiro框架实现的权限管理系统。这样的系统改成集群模式,主要是把shiro更换为集群模式,让shiro管理的session实现共享。本文介绍的就是借助分布式缓存redis来实现用户会话共享。
shiro的缓存体系分为两种情况,一是使用jvm内存缓存MemorySessionDAO,二是使继承CachingSessionDAO实现里面的抽象方法。本文实现的是集群模式,所以只能使用第二种方式。shiro没有自己实现缓存,但是定义好了缓存模板,只要把自定义的缓存管理器cacheManager注入到shiro配置文件即可。好的,接下来问题就是编写缓存管理器了。
仔细看看文章的标题,我们借助springcache来编写cacheManager,这样就不需要完整编写cacheManager了。只要把这个桥梁给适配好即可。但是缓存管理器管理的缓存对象需要自己去完整编写。
不说了,直接上代码。
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.util.Destroyable;
public class ShiroSpringCacheManager implements CacheManager, Destroyable {
private static final Logger logger = LogManager.getLogger(ShiroSpringCacheManager.class);
private org.springframework.cache.CacheManager cacheManager;
public org.springframework.cache.CacheManager getCacheManager() {
return cacheManager;
}
public void setCacheManager(org.springframework.cache.CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
@Override
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
if (logger.isTraceEnabled()) {
logger.trace("Acquiring ShiroSpringCache instance named [" + name + "]");
}
org.springframework.cache.Cache cache = cacheManager.getCache(name);
return new ShiroSpringCache<K, V>(cache);
}
@Override
public void destroy() throws Exception {
cacheManager = null;
}
}
缓存管理器以及缓存对象主要是通过组合方式实现其适配功能
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.cache.CacheException;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
@SuppressWarnings("unchecked")
public class ShiroSpringCache<K, V> implements org.apache.shiro.cache.Cache<K, V> {
private static final Logger logger = LogManager.getLogger(ShiroSpringCache.class);
private final org.springframework.cache.Cache cache;
public ShiroSpringCache(Cache cache) {
if (cache == null) {
throw new IllegalArgumentException("Cache argument cannot be null.");
}
this.cache = cache;
}
@Override
public V get(K key) throws CacheException {
if (logger.isTraceEnabled()) {
logger.trace("Getting object from cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass());
}
ValueWrapper valueWrapper = cache.get(key);
if (valueWrapper == null) {
if (logger.isTraceEnabled()) {
logger.trace("Element for [" + key + "] is null.");
}
return null;
}
return (V) valueWrapper.get();
}
@Override
public V put(K key, V value) throws CacheException {
if (logger.isTraceEnabled()) {
logger.trace("Putting object in cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass());
}
V previous = get(key);
cache.put(key, value);
return previous;
}
@Override
public V remove(K key) throws CacheException {
if (logger.isTraceEnabled()) {
logger.trace("Removing object from cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass());
}
V previous = get(key);
cache.evict(key);
return previous;
}
@Override
public void clear() throws CacheException {
if (logger.isTraceEnabled()) {
logger.trace("Clearing all objects from cache [" + this.cache.getName() + "]");
}
cache.clear();
}
@Override
public int size() {
return 0;
}
@Override
public Set<K> keys() {
return Collections.emptySet();
}
@Override
public Collection<V> values() {
return Collections.emptySet();
}
@Override
public String toString() {
return "ShiroSpringCache [" + this.cache.getName() + "]";
}
}
来源:oschina
链接:https://my.oschina.net/osokra/blog/4446546