Apache Shiro(六)——Shiro缓存管理

xiaoxiao2025-11-03  5

一、概述

CacheManagerAware 接口

Shiro 内部相应的组件(DefaultSecurityManager)会自动检测相应的对象(如Realm)是否实现了CacheManagerAware 并自动注入相应的CacheManager。

Realm 缓存

Shiro 提供了 CachingRealm,其实现了CacheManagerAware 接口,提供了缓存的一些基础实现。 AuthenticatingRealm 及 AuthorizingRealm 也分别提供了对AuthenticationInfo 和 AuthorizationInfo 信息的缓存。

Session 缓存

如 SecurityManager 实现了 SessionSecurityManager,其会判断 SessionManager 是否实现了CacheManagerAware 接口,如果实现了会把CacheManager 设置给它。 SessionManager 也会判断相应的 SessionDAO(如继承自CachingSessionDAO)是否实现了CacheManagerAware,如果实现了会把 CacheManager设置给它。

设置了缓存的 SessionManager,查询时会先查缓存,如果找不到才查数据库。

二、整合redis,实现shiro的CacheManager

Shiro默认整合了EhCache,来实现缓存,如果我们想用redis替换EhCache来实现缓存怎么做了?我们可以从Shiro的源码来找到一些端倪。我们可以模拟EhCacheManager的实现方式,EhCacheManager类定义如下:

public class EhCacheManager implements CacheManager, Initializable, Destroyable { }

我们从上面的代码可以看到,最终要的是实现了CacheManager接口,该接口很简单,只有一个方法:

public interface CacheManager { /** * Acquires the cache with the specified <code>name</code>. If a cache does not yet exist with that name, a new one * will be created with that name and returned. * * @param name the name of the cache to acquire. * @return the Cache with the given name * @throws CacheException if there is an error acquiring the Cache instance. */ public <K, V> Cache<K, V> getCache(String name) throws CacheException; }

从上面的注释中,我们可以发现,这个接口需要一个Cache,通过name来获取Cache,首先,我们来实现CacheManager这个接口:

@Service public class RedisCacheManager implements CacheManager { @Autowired private RedisTemplate redisTemplate; // RedisTemplate,如果不明白怎么使用的,请参考http://blog.csdn.net/liuchuanhong1/article/details/54601037 @Override public <K, V> Cache<K, V> getCache(String name) throws CacheException { System.out.println("name:"+name); return new RedisCache<K, V>(120, redisTemplate);// 为了简化代码的编写,此处直接new一个Cache } }

下面,我们来实现Cache类:

import java.util.Collection; import java.util.Set; import java.util.concurrent.TimeUnit; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.springframework.data.redis.core.RedisTemplate; public class RedisCache<K, V> implements Cache<K, V> { private long expireTime = 120;// 缓存的超时时间,单位为s private RedisTemplate<K, V> redisTemplate;// 通过构造方法注入该对象 public RedisCache() { super(); } public RedisCache(long expireTime, RedisTemplate<K, V> redisTemplate) { super(); this.expireTime = expireTime; this.redisTemplate = redisTemplate; } /** * 通过key来获取对应的缓存对象 * 通过源码我们可以发现,shiro需要的key的类型为Object,V的类型为AuthorizationInfo对象 */ @Override public V get(K key) throws CacheException { return redisTemplate.opsForValue().get(key); } /** * 将权限信息加入缓存中 */ @Override public V put(K key, V value) throws CacheException { redisTemplate.opsForValue().set(key, value, this.expireTime, TimeUnit.SECONDS); return value; } /** * 将权限信息从缓存中删除 */ @Override public V remove(K key) throws CacheException { V v = redisTemplate.opsForValue().get(key); redisTemplate.opsForValue().getOperations().delete(key); return v; } @Override public void clear() throws CacheException { } @Override public int size() { return 0; } @Override public Set<K> keys() { return null; } @Override public Collection<V> values() { return null; } }

这两步完成之后,就是需要将原来的EhCacheManager的配置换成RedisCacheManager了。

@Bean public DefaultWebSessionManager configWebSessionManager(){ DefaultWebSessionManager manager = new DefaultWebSessionManager(); manager.setCacheManager(cacheManager);// 换成Redis的缓存管理器 manager.setSessionDAO(sessionDao); manager.setDeleteInvalidSessions(true); manager.setGlobalSessionTimeout(sessionDao.getExpireTime()); manager.setSessionValidationSchedulerEnabled(true); return manager; }

通过上面的几步,我们就实现了用Redis来缓存Shiro的权限等相关信息。

三、相关连接

springboot②最正确的集成shiro并使用ehcache缓存 spring boot整合redis,实现shiro的CacheManager

转载请注明原文地址: https://www.6miu.com/read-5038996.html

最新回复(0)