记一次,ehcache缓存到磁盘,再恢复的过程

 

问题就是:缓存到硬盘,关闭服务器后再重启,无法获得之前缓存数据 

 

环境:

 

 

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,但是我对象都序列化了啊。

 

猜你喜欢

转载自cainiao1923.iteye.com/blog/2348396