Shiro提供了类似于Spring的Cache抽象,即Shiro本身不实现Cache,但是对Cache进行了又抽象,方便更换不同的底层Cache实现。所以我们如果想要实现redis缓存处理,必须先实现两个抽象接口Cache和CacheManager
(1)实现Cache参考代码
//定义继承Cache类,去在原先shiro处理缓存的基础上,让其把缓存的权限角色缓存到redis中 public class RedisCache<k,V> implements Cache<k,V> { //RedisTemplate是Spring-date的一个核心操作类 private RedisTemplate<String,Object> redisTemplate; //定义一个构造方法需要把redisTempate接收过来,在Shiro原先提供的缓存增删改查方案上 //利用redisTempate进行redis数据库储存 public RedisCache(RedisTemplate<String,Object> redisTemplate){ this.redisTemplate=redisTemplate; } //取 @Override public V get(k k) throws CacheException { System.out.println("get:key:"+k); return (V)redisTemplate.opsForValue().get(k.toString()); } //存 @Override public V put(k k, V v) throws CacheException { System.out.println("put:key:"+k+"Value:"+v); redisTemplate.opsForValue().set(k.toString(),v); return v; } //删 @Override public V remove(k k) throws CacheException { System.out.println("remove:k:"+k); //定义一个方法取得要删除key的value V v=this.get(k); redisTemplate.delete(k.toString()); return v; } @Override public void clear() throws CacheException { System.out.println("*****flushdb****"); //OpsForValue是execute的封装版,execute可以进行类似原始jedis操作 redisTemplate.execute(new RedisCallback<Boolean>() { @Override public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException { //清空数据库 redisConnection.flushDb(); return true; } }); } //查询所有数据量 @Override public int size() { System.out.println("******size*****"); return redisTemplate.execute(new RedisCallback<Integer>() { @Override public Integer doInRedis(RedisConnection redisConnection) throws DataAccessException { //keys返回的是集合,再跟上size方法,得到数据的数量 return redisConnection.keys("*".getBytes()).size(); } }); } //获得所有的key @Override public Set<k> keys() { System.out.println("*******keys******"); return redisTemplate.execute(new RedisCallback<Set<k>>() { @Override public Set<k> doInRedis(RedisConnection redisConnection) throws DataAccessException { Set<k> set=new HashSet<k>(); //key从redis数据库中取出以字节数组的形式返回 Set<byte[]> keys=redisConnection.keys("*".getBytes()); Iterator<byte[]> iter=keys.iterator(); while (iter.hasNext()){ set.add((k) iter.next()); } return set; } }); } //获得所有的Value @Override public Collection<V> values() { System.out.println("*****keys******"); return redisTemplate.execute(new RedisCallback<Set<V>>() { @Override public Set<V> doInRedis(RedisConnection redisConnection) throws DataAccessException { Set<V> set=new HashSet<V>(); //key从redis数据库中取出以字节数组的形式返回 Set<byte[]> keys=redisConnection.keys("*".getBytes()); Iterator<byte[]> iter=keys.iterator(); while (iter.hasNext()){ set.add((V)redisConnection.get(iter.next())); } return set; }; }); } }(2)实现cacheManager接口
public class RedisCacheMange implements CacheManager { private final ConcurrentMap<String,Cache> caches=new ConcurrentHashMap<String, Cache>(); private RedisTemplate<String,Object> redisTemplate; //定义一个方法,让其从外部进行注入redisTemplate public void setRedisTemplate(RedisTemplate<String,Object> redisTemplate){ this.redisTemplate=redisTemplate; } //CacheManger带的方法,获取cache @Override public <K, V> Cache<K, V> getCache(String s) throws CacheException { //首先通过ConcurrentMap中取得(也就是从电脑缓存中取得) Cache<K,V> cache=caches.get(s); //如果从电脑中无法取得缓存数据,那就需要从redis数据库中取 if (cache==null){ //实例化自定义的RedisCache类,并讲注入的redisTemplate传入进去 //因为自定义的类继承了Shiro的CRUD所以可以自动从redis数据取 cache=new RedisCache(this.redisTemplate); //如果能从redis数据库取出数据,还需要保存到当前服务器上,也就是保存在ConcurrentMap中 this.caches.put(s,cache); } return cache; } }bean实现接口类,且需要注入已经配置好的redisTemplate
<!--配置自定义redis缓存机制--> <bean id="redisCacheMange" class="cn.travel.Cache.RedisCacheMange"> <property name="redisTemplate" ref="redisTemplate"/> </bean>在shiroSecurity中注入缓存机制
!--配置安全管理器--> <bean id="scurityManage" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!--配置你需要使用的Realms--> <property name="realm" ref="empRealm"/> <!--配置会话管理--> <property name="sessionManager" ref="sessionManager"/> <!--配置缓存管理--> <property name="cacheManager" ref="redisCacheMange"/> </bean>在项目登陆后会出现如下 实现类讲权限缓存入redis数据库 我们进入redis服务器查看这条数据
成功!!!
