我是用 Maven 管理的项目,先上依赖包:
<dependency>
<artifactId>ehcache-core</artifactId>
<groupId>net.sf.ehcache</groupId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency>
我现在项目一直是用的 Shiro + Redis 来结合使用,解决的问题有
本文只介绍 Shiro + EHCache 的结合。因为我项目之前用的是 Redis ,但是项目实际应用没那么多要求,就采用本地 缓存 EHCache 来解决了。
首先有两种方式来创建缓存实列:
一、 Spring 创建方式。
<bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="classpath:ehcache.xml"></bean>
<!-- 声明cacheManager -->
<bean id="shiroEhcacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cacheManager-ref="cacheManagerFactory" ></bean>
二、Bean创建方式。
<!-- shiro的缓存管理器,然后需要将缓存管理器注入到安全管理其中 -->
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<!--classpath是缓存属性的配置文件 -->
<property name="cacheManagerConfigFile" value="classpath:config/ehcache-shiro.xml" />
</bean>
我先暂且用第二种。
EHCache配置文件说明。
一、 EHCache 配置文件代码。
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shirocache">
<diskStore path="java.io.tmpdir"/>
<!-- 登录记录缓存 锁定10分钟 -->
<cache name="passwordRetryCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="authorizationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="authenticationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="shiro-activeSessionCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="shiro_cache"
maxElementsInMemory="2000"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
maxElementsOnDisk="0"
overflowToDisk="true"
memoryStoreEvictionPolicy="FIFO"
statistics="true">
</cache>
</ehcache>
二、 EHCache 配置文件解释:
name | Cache的名称,必须是唯一的(ehcache会把这个cache放到HashMap里) |
maxElementsInMemory | 内存中保持的对象数量 |
maxElementsOnDisk | DiskStore中保持的对象数量,默认值为0,表示不限制 |
eternal | 是否是永恒数据,如果是,则它的超时设置会被忽略 |
overflowToDisk | 如果内存中数据数量超过maxElementsInMemory限制,是否要缓存到磁盘上 |
timeToIdleSeconds | 对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问 |
timeToLiveSeconds | 对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问 |
diskPersistent | 是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false |
diskExpiryThreadIntervalSeconds | 对象检测线程运行时间间隔。标识对象状态的线程多长时间运行一次 |
diskSpoolBufferSizeMB | DiskStore使用的磁盘大小,默认值30MB。每个cache使用各自的DiskStore |
memoryStoreEvictionPolicy | 如果内存中数据超过内存限制,向磁盘缓存时的策略。默认值LRU,可选FIFO、LFU |
三、 EHCache 管理类。
package net.wenyifan.common.shiro;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import net.wenyifan.common.util.StringUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.session.Session;
/**
*
* 开发公司:itboy.net<br/>
* 版权:itboy.net<br/>
* <p>
*
* EHCache管理
*
* <p>
*
* 区分 责任人 日期 说明<br/>
* 创建 周柏成 2016年2月16日 <br/>
* <p>
* *******
* <p>
* @author zhou-baicheng
* @email i@itboy.net
* @version 1.0,2016年2月16日 <br/>
*
*/
public class CacheManager<K, V> implements Cache<K, V> {
private EhCacheManager cacheManager;
private Cache<K, V> cache = null;
public Cache<K, V> getCache() {
try {
if(null == cache){
cache = cacheManager.getCache("shiro_cache");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return cache;
}
@Override
public void clear() throws CacheException {
getCache().clear();
}
@Override
public V get(K key) throws CacheException {
return getCache().get(key);
}
@Override
public Set<K> keys() {
return getCache().keys();
}
@Override
public V put(K key, V value) throws CacheException {
return getCache().put(key, value);
}
@Override
public V remove(K key) throws CacheException {
return getCache().remove(key);
}
@Override
public int size() {
return getCache().size();
}
@Override
public Collection<V> values() {
return getCache().values();
}
public EhCacheManager getCacheManager() {
return cacheManager;
}
public void setCacheManager(EhCacheManager cacheManager) {
this.cacheManager = cacheManager;
}
public void setCache(Cache<K, V> cache) {
this.cache = cache;
}
/**
* 获取所有Session
* @throws Exception
*/
public Collection<Session> AllSession() throws Exception {
Set<Session> sessions = new HashSet<Session>();
try {
//TODO 注意事项:必须此缓存只存储Session,要不造成性能下降
cache = getCache();
Collection<V> values = cache.values();
for (V v : values) {
if(StringUtils.isNotBlank(v) && v instanceof Session){
sessions.add((Session)v);
}
}
} catch (Exception e) {
throw e;
}
return sessions;
}
}