https://blog.csdn.net/weixin_34137799/article/details/88068777
https://blog.csdn.net/coolwindd/article/details/84862184
Cache 接口
Shiro 提供的 Cache 接口,该接口用于自定义缓存的设置和获取等操作,我们使用的时候需要实现它来完成缓存操作,例如使用 Redis 来管理缓存。
public interface Cache<K, V> {
//根据Key获取缓存中的值
public V get(K key) throws CacheException;
//往缓存中放入key-value,返回缓存中之前的值
public V put(K key, V value) throws CacheException;
//移除缓存中key对应的值,返回该值
public V remove(K key) throws CacheException;
//清空整个缓存
public void clear() throws CacheException;
//返回缓存大小
public int size();
//获取缓存中所有的key
public Set<K> keys();
//获取缓存中所有的value
public Collection<V> values();
}
CacheManager 接口
Shiro 提供的 CacheManager 接口,该接口用于注入 securityManager 让 Shiro 来管理缓存处理。
public interface CacheManager {
//根据缓存名字获取一个Cache
<K, V> Cache<K, V> getCache(String var1) throws CacheException;
}
缓存管理器
缓存管理器的配置很简单,简单来说步骤是:在 SecurityManager 中注入 CacheManager 即可。
使用缓存可以避免需要授权信息时频繁的调用数据库查询的问题。我们可以使用 ehcache、Redis 自定义 CacheManager 的实现。
需要注意的是,我们使用的是 shiro 框架提供的缓存管理器 UserRealm里注入的 SysUserService 等service,需要延迟注入,即都要添加@Lazy注解(如果不加需要自己延迟注入),否则会导致该 service 里的 @Cacheable 缓存注解、@Transactional 事务注解等失效。
1. EhCache 实现缓存管理器
导入依赖 pom.xml
<!-- 使用 ehcache 做缓存 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.9</version>
</dependency>
添加配置文件 ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" dynamicConfig="false">
<diskStore path="java.io.tmpdir"/>
<cache name="users"
timeToLiveSeconds="300"
maxEntriesLocalHeap="1000"/>
<!--
name:缓存名称。
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
-->
<defaultCache name="defaultCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
maxElementsOnDisk="100000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
添加配置 ShiroConfig.java ```java @Bean public EhCacheManager ehCacheManager() { EhCacheManager cacheManager = new EhCacheManager(); cacheManager.setCacheManagerConfigFile(“classpath:ehcache.xml”); return cacheManager; }
@Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 管理 realm securityManager.setRealm(userRealm()); // 缓存管理器 securityManager.setCacheManager(ehCacheManager()); return securityManager; }
<a name="HzhF1"></a>
## 2. Shiro-Redis 实现缓存管理器
shiro-redis 依赖包为我们试了 Cache 和 CacheManager 接口
1. 导入依赖,这里使用 shiro-redis 简化配置
```xml
<!-- shiro-redis -->
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.1.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</exclusion>
</exclusions>
</dependency>
- 添加配置
```java
/**
- Redis 管理 *
- @return */ @Bean public RedisManager redisManager() { RedisManager redisManager = new RedisManager(); redisManager.setHost(“127.0.0.1”); redisManager.setPort(6379); redisManager.setPassword(“123456”); return redisManager; }
/**
- Redis 缓存管理器 *
- @return */ @Bean public RedisCacheManager redisCacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager(); redisCacheManager.setRedisManager(redisManager()); //redis中针对不同用户缓存 redisCacheManager.setPrincipalIdFieldName(“username”); //用户权限信息缓存时间 redisCacheManager.setExpire(200000); return redisCacheManager; } ```
3. 内存缓存管理器
这种方式配置比较简单,但无法保证缓存一致性、乐观锁定等功能,实际开发中不推荐。
@Bean
public CacheManager cacheManager() {
log.info("配置缓存管理器");
return new MemoryConstrainedCacheManager();
}
@Bean
public DefaultWebSecurityManager securityManager() {
log.info("security manager");
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 管理 realm
securityManager.setRealm(userRealm());
// 缓存管理器
securityManager.setCacheManager(cacheManager());
return securityManager;
}