shiro使用redis实现cache
Shiro默认整合了EhCache,来实现缓存,如果我们想用redis替换EhCache来实现缓存怎么做了?我们可以从Shiro的源码来找到一些端倪。
参考代码
https://github.com/gemingyi/shiro_demo
先找到shiro realm类的setCacheManager()方法,可以看到传入参数CacheManager。
到这里我们就知道CacheManager接口就行了。
CacheManager接口,该接口很简单,只有一个方法:
这个接口需要一个Cache,通过name来获取Cache,首先,我们来实现CacheManager这个接口。
public class RedisCacheManager implements CacheManager {
private long cacheLive; //cache存活时间
private String cacheKeyPrefix; //cache前缀
private RedisTemplate redisTemplate;
private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
@Override
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
Cache cache = this.caches.get(name);
if (cache == null) {
//自定义shiroCache
cache = new ShiroRedisCache<K, V>(redisTemplate, cacheLive, cacheKeyPrefix);
this.caches.put(name, cache);
}
return cache;
}
public void setCacheLive(long cacheLive) {
this.cacheLive = cacheLive;
}
public void setCacheKeyPrefix(String cacheKeyPrefix) {
this.cacheKeyPrefix = cacheKeyPrefix;
}
public void setRedisTemplate(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
}
我们在看看这个Cache接口:
我们使用redis实现(我这里使用的是RedisTemplate),下面是ShiroRedisCache代码:
public class ShiroRedisCache<K, V> implements Cache<K, V> {
private long cacheLive;
private String cacheKeyPrefix;
private RedisTemplate redisTemplate;
@Override
public V get(K k) throws CacheException {
return (V) this.redisTemplate.opsForValue().get(this.getRedisCacheKey(k));
}
@Override
public V put(K k, V v) throws CacheException {
redisTemplate.opsForValue().set(this.getRedisCacheKey(k), v, cacheLive, TimeUnit.MINUTES);
return v;
}
@Override
public V remove(K k) throws CacheException {
V obj = (V) this.redisTemplate.opsForValue().get(this.getRedisCacheKey(k));
redisTemplate.delete(this.getRedisCacheKey(k));
return obj;
}
@Override
public void clear() throws CacheException {
Set keys = this.redisTemplate.keys(this.cacheKeyPrefix + "*");
if (null != keys && keys.size() > 0) {
Iterator itera = keys.iterator();
this.redisTemplate.delete(itera.next());
}
}
@Override
public int size() {
Set<K> keys = this.redisTemplate.keys(this.cacheKeyPrefix + "*");
return keys.size();
}
@Override
public Set<K> keys() {
return this.redisTemplate.keys(this.cacheKeyPrefix + "*");
}
@Override
public Collection<V> values() {
Set<K> keys = this.redisTemplate.keys(this.cacheKeyPrefix + "*");
Set<V> values = new HashSet<V>(keys.size());
for (K key : keys) {
values.add((V) this.redisTemplate.opsForValue().get(this.getRedisCacheKey(key)));
}
return values;
}
private String getRedisCacheKey(K key) {
Object redisKey = this.getStringRedisKey(key);
if (redisKey instanceof String) {
return this.cacheKeyPrefix + redisKey;
} else {
return String.valueOf(redisKey);
}
}
private Object getStringRedisKey(K key) {
Object redisKey;
if (key instanceof PrincipalCollection) {
redisKey = this.getRedisKeyFromPrincipalCollection((PrincipalCollection) key);
} else {
redisKey = key.toString();
}
return redisKey;
}
private Object getRedisKeyFromPrincipalCollection(PrincipalCollection key) {
List realmNames = this.getRealmNames(key);
Collections.sort(realmNames);
Object redisKey = this.joinRealmNames(realmNames);
return redisKey;
}
private List<String> getRealmNames(PrincipalCollection key) {
ArrayList realmArr = new ArrayList();
Set realmNames = key.getRealmNames();
Iterator i$ = realmNames.iterator();
while (i$.hasNext()) {
String realmName = (String) i$.next();
realmArr.add(realmName);
}
return realmArr;
}
private Object joinRealmNames(List<String> realmArr) {
StringBuilder redisKeyBuilder = new StringBuilder();
for (int i = 0; i < realmArr.size(); ++i) {
String s = realmArr.get(i);
redisKeyBuilder.append(s);
}
String redisKey = redisKeyBuilder.toString();
return redisKey;
}
public ShiroRedisCache(RedisTemplate redisTemplate, long cacheLive, String cachePrefix) {
this.redisTemplate = redisTemplate;
this.cacheLive = cacheLive;
this.cacheKeyPrefix = cachePrefix;
}
}
最后贴一下ShiroConfiguration代码:
@Bean(name = "redisCacheManager")
public RedisCacheManager redisCacheManager(@Qualifier("redisTemplate") RedisTemplate redisTemplate) {
RedisCacheManager redisCacheManager = new RedisCacheManager();
//cache过期时间及前缀
redisCacheManager.setCacheLive(cacheLive);
redisCacheManager.setCacheKeyPrefix(cachePrefix);
redisCacheManager.setRedisTemplate(redisTemplate);
return redisCacheManager;
}
@Bean(name = "securityManager")
public SecurityManager securityManager(SessionManager sessionManager, RedisCacheManager redisCacheManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm());
// 自定义session管理 使用redis
securityManager.setSessionManager(sessionManager);
// 自定义缓存实现 使用redis
securityManager.setCacheManager(redisCacheManager);
return securityManager;
}