问题就是:缓存到硬盘,关闭服务器后再重启,无法获得之前缓存数据
环境:
ehcache版本:
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.5.2</version>
</dependency>
ehcache.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="spring_oa" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false">
<!-- <diskStore path="java.io.tmpdir"/> Java临时目录 -->
<diskStore path="d:\cache"/> <!-- Java临时目录 -->
<!--
配置自定义缓存
maxElementsInMemory:缓存中允许创建的最大对象数
eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前, (空闲时间)
两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效,
如果该值是 0 就意味着元素可以停顿无穷长的时间。
timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值,
这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
overflowToDisk:内存不足时,是否启用磁盘缓存。
memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。
-->
<!-- My understanding is that the "default cache" is actually a template for new caches that get created, rather than being a specific named cache. -->
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"/>
<!-- 最大日期缓存到磁盘-->
<!-- 警情 -->
<cache name="jq_maxDateCache"
maxElementsInMemory="1"
eternal="true"
overflowToDisk="true"
diskPersistent="true"
memoryStoreEvictionPolicy="LFU" >
<!-- timeToIdleSeconds="60" -->
<!-- timeToLiveSeconds="0" -->
<!-- overflowToDisk="false" -->
<!-- statistics="true" -->
<BootstrapCacheLoaderFactory class="net.sf.ehcache.store.DiskStoreBootstrapCacheLoaderFactory" properties="bootstrapAsynchronously=true" />
<!-- <cacheEventListenerFactory -->
<!-- class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" /> -->
<!-- 比一般配置多了这个 -->
<!-- <bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/> -->
</cache>
<!-- 最大日期缓存到磁盘-->
<!-- 调派中队 -->
<cache name="dpzd_maxDateCache"
maxElementsInMemory="1"
eternal="true"
overflowToDisk="true"
diskPersistent="true"
memoryStoreEvictionPolicy="LFU" >
<BootstrapCacheLoaderFactory class="net.sf.ehcache.store.DiskStoreBootstrapCacheLoaderFactory" properties="bootstrapAsynchronously=true" />
<!-- <cacheEventListenerFactory -->
<!-- class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" /> -->
<!-- 比一般配置多了这个 -->
<!-- <bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/> -->
</cache>
<!-- 最大日期缓存到磁盘-->
<!-- 调派车辆 -->
<cache name="dpcl_maxDateCache"
maxElementsInMemory="1"
eternal="true"
overflowToDisk="true"
diskPersistent="true"
memoryStoreEvictionPolicy="LFU" >
<BootstrapCacheLoaderFactory class="net.sf.ehcache.store.DiskStoreBootstrapCacheLoaderFactory" properties="bootstrapAsynchronously=true" />
<!-- <cacheEventListenerFactory -->
<!-- class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" /> -->
<!-- 比一般配置多了这个 -->
<!-- <bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/> -->
</cache>
</ehcache>
applicationContext-cache.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Spring提供的基于的Ehcache实现的缓存管理器 -->
<!-- 如果有多个ehcacheManager要在bean加上p:shared="true" -->
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache/ehcache.xml"/>
</bean>
<bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache"/>
</bean>
</beans>
CacheUtils:
package jiangdu.fire.util.wj;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.util.CollectionUtils;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
/**
* Cache工具类
* @author wj
* @date 2016-12-31
*/
public class CacheUtils {
private static Logger logger = LoggerFactory.getLogger(CacheUtils.class);
private static EhCacheCacheManager cacheManager = SpringContextHolder.getBean("ehcacheManager");
public static Object get(String cacheName, Object key) {
Cache cache = getCache(cacheName);
if (cache != null) {
logger.debug("------缓存["+cacheName+"] size:"+cache.getSize());
// System.out.println("------缓存["+cacheName+"] size:"+cache.getSize());
List<String> keys = cache.getKeys();
if(!CollectionUtils.isEmpty(keys)){
for( String key1 : keys){
logger.debug("------缓存["+cacheName+"] key:"+key1+",value:"+cache.get(key1).getObjectValue());
// System.out.println("------缓存["+cacheName+"] key:"+key1+",value:"+cache.get(key1).getObjectValue());
}
}
Element element = cache.get(key);
if (element != null) {
return element.getObjectValue();
}
}
return null;
}
public static void put(String cacheName, Object key, Object value) {
Cache cache = getCache(cacheName);
if (cache != null) {
cache.put(new Element(key, value));
}
}
public static boolean remove(String cacheName, Object key) {
Cache cache = getCache(cacheName);
if (cache != null) {
return cache.remove(key);
}
return false;
}
public static void flush(String cacheName) {
Cache cache = getCache(cacheName);
if (cache != null) {
cache.flush();
}
}
public static void main(String[] args) {
String key = "key";
String value = "hello";
CacheUtils.put("mytest", key, value);
System.out.println(CacheUtils.get("mytest", key));
}
/**
* 获得一个Cache,没有则显示日志。
* @param cacheName
* @return
*/
private static Cache getCache(String cacheName){
Cache cache = cacheManager.getCacheManager().getCache(cacheName);
if (cache == null){
throw new RuntimeException("当前系统中没有定义“"+cacheName+"”这个缓存。");
}
return cache;
}
}
写入缓存代码:
//TODO 可以比较一下缓存里的日期和这里的最大日期
//将最大日期缓存磁盘(用于防止server关闭)。如果没有关闭,最大日期值 依然在外面静态变量里
CacheUtils.put(cacheName, cacheKeyName,maxBjsj);
//看看有没有持久化成功
org.springframework.util.Assert.isTrue(comparDate(((AtomicReference<Date>)CacheUtils.get(cacheName, cacheKeyName)).get(), maxBjsj.get())==0 ,"缓存日期和刚才日应该相等");
CacheUtils.flush(cacheName);
读缓存代码:
static{
if(CacheUtils.get(Contants.jq_maxDateCache, Contants.jq_maxDate_key) == null){
maxBjsj = new AtomicReference<Date>();
}else{
maxBjsj = (AtomicReference<Date>)CacheUtils.get(Contants.jq_maxDateCache, Contants.jq_maxDate_key);
}
}
这时候,如果server关闭再开启,会读不到数据。
解决:
1、we.xml 加入
<listener> <listener-class>net.sf.ehcache.constructs.web.ShutdownListener</listener-class> </listener>
让服务器关闭时候,调ehcache的shutdown方法。
2、spring 启动的时候
System.setProperty(net.sf.ehcache.CacheManager.ENABLE_SHUTDOWN_HOOK_PROPERTY,"true");
public class SpringInit implements InitializingBean, ServletContextAware{
private static Logger logger = LoggerFactory.getLogger(SpringInit.class);
@Override
public void setServletContext(ServletContext servletContext) {
logger.debug("-----init-----");
System.setProperty(net.sf.ehcache.CacheManager.ENABLE_SHUTDOWN_HOOK_PROPERTY,"true");
}
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
}
}
再把该BEAN配置到applicationContext.xml里面
<bean class="jiangdu.fire.util.wj.SpringInit">
</bean>
。如果还不行可以改源码,修改DiskStorageFactory.DiskStorageFactory(..)方法,注释掉最后的 else if,让其不删除.index文件。
我这样就可以了。然后,server运行时候,.data文件是0kb的,server关闭后,.data文件就有内容了。。。不明所以
可以参考:http://blog.csdn.net/kingofworld/article/details/44751029
----
但是运行一段时间后,在put缓存的时候,会报EOFException,但是我对象都序列化了啊。