问题就是:缓存到硬盘,关闭服务器后再重启,无法获得之前缓存数据
环境:
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,但是我对象都序列化了啊。