应用场景:Shiro为每个用户的角色和权限信息提供缓存支持,通过Shiro自己定义的CacheManager实现,默认实现有Ehcache和内存(就是一个Map结构),在应用中通常使用redis作为缓存服务器,因此使用redis来作为shiro的缓存。
优缺点:一般来说缓存放在本地,通过本地内存进行缓存速度更快,但是在分布式环境下,修改了用户权限需要进行同步。将缓存和Session放在统一的地方进行管理可以解决,但是网络请求延迟较高,且容易造成瞬间高并发。 代码分析:
1、实现AbstractCacheManager:
import org.apache.shiro.cache.AbstractCacheManager; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * @author: yykk **/ @Component public class MyCacheManager extends AbstractCacheManager { @Autowired private MCahce mCahce; @Override protected Cache createCache(String name) throws CacheException { return mCahce; } }
2、实现Shiro定义的Cache接口
import lombok.extern.slf4j.Slf4j; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.Collection; import java.util.Set; /** * @author: yykk **/ @Slf4j @Component public class MCahce<K,V> implements Cache<K,V> { //redis key private final K prefix = (K)"shiro_cache"; @Autowired private RedisTemplate redisTemplate; public RedisTemplate getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } //------------------------ @Override public V get(K key) throws CacheException { Object o = redisTemplate.opsForHash().get(prefix,key); return o == null ? null : (V) o; } @Override public V put(K key, V value) throws CacheException { V old = this.get(key); redisTemplate.opsForHash().put(prefix,key,value); return old; } @Override public V remove(K key) throws CacheException { V old = this.get(key); redisTemplate.opsForHash().delete(prefix,key); return old; } @Override public void clear() throws CacheException { redisTemplate.delete(prefix); } @Override public int size() { return redisTemplate.opsForHash().size(prefix).intValue(); } @Override public Set<K> keys() { return redisTemplate.opsForHash().keys(prefix); } @Override public Collection<V> values() { return redisTemplate.opsForHash().values(prefix); } }
3、配置shiro注入缓存管理器:
@bean public AuthorizingRealm myrealm(CacheManager cacheManager) { log.info("myrealm()"); AuthorizingRealm realm = new MyRealm(); realm.setCachingEnabled(true); //开启缓存 realm.setCacheManager(cacheManager); //注入缓存管理器 return realm; }
4、Redis序列化
jdk序列化
new JdkSerializationRedisSerializer()
json序列化
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();