EhCache缓存学习(转)

在看hibernate的官方文档时,看到关于缓存的介绍。

hibernate在缓存管理上做的很好,具体使用,本章不做讲解,本篇主要研究EhCache的用法。其中hibernate使用到的缓存提供商列表如下:

 

CacheProvider classTypeCluster SafeQuery Cache Supported
Hashtable (not intended for production use)org.hibernate.cache.HashtableCacheProvidermemory yes
EHCacheorg.hibernate.cache.EhCacheProvidermemory, disk, transactional, clusteredyesyes
OSCacheorg.hibernate.cache.OSCacheProvidermemory,disk yes
SwarmCacheorg.hibernate.cache.SwarmCacheProviderclustered (ip multicast)yes (clustered invalidation) 
JBoss Cache 1.xorg.hibernate.cache.TreeCacheProviderclustered (ip multicast), transactionalyes (replication)yes (clock sync req.)
JBoss Cache 2org.hibernate.cache.jbc.JBossCacheRegionFactoryclustered (ip multicast), transactionalyes (replication or invalidation)yes (clock sync req.)


其中,我对EHCache比较感兴趣。看它支持的类型包括对内存,硬盘,传统,集群都支持。

 

我们可以单独研究一下Ehcache缓存的使用,这样方便以后我们对其他使用到缓存的地方进行缓存的自定义管理(不单单在hibernate查询数据方面)。

 

ehcache下载地址:   http://sourceforge.net/projects/ehcache/files/ehcache/  

先写个例子,看看它的api如何使用:

 

EhcacheTest

 

package org.base.cache.test;

import java.net.MalformedURLException;
import java.net.URL;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;

/**
 * Ehcache缓存管理的api测试小例子
 * @author lushuaiyin
 *
 */
public class EhcacheTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws MalformedURLException {
		net.sf.ehcache.config.Configuration config=new Configuration();
		
		//如果不使用ehcache.xml配置文件,那么必须用代码配置一个defaultCacheConfiguration
		CacheConfiguration defaultCacheConfiguration=new CacheConfiguration();
		defaultCacheConfiguration.setMaxEntriesLocalHeap(0);
		defaultCacheConfiguration.setEternal(false);
		defaultCacheConfiguration.setTimeToIdleSeconds(30);
		defaultCacheConfiguration.setTimeToLiveSeconds(30);
		
		config.addDefaultCache(defaultCacheConfiguration);//设置默认cache
		
		net.sf.ehcache.CacheManager cacheManager=CacheManager.create(config);
		
		//创建缓存信息
		/*构造方法有多种,详见文档
		 public Cache(String name,
             int maxElementsInMemory,
             boolean overflowToDisk,
             boolean eternal,
             long timeToLiveSeconds,
             long timeToIdleSeconds)
		 */
		//自定义配置缓存
		net.sf.ehcache.Cache cache1=new Cache("mycache-one", 1000, false, false, 30, 30);
		cacheManager.addCache(cache1);
		
		//只有配置了defaultCacheConfiguration,这个方法才可以使用。因为用字符串命名的缓存必须有实际配置。
		cacheManager.addCache("mycache-two");//添加一个空缓存
		
		
		
		//往缓存中放值
		String objkey1="key1",objvalue1="value1";
		cache1.put(new Element(objkey1,objvalue1));//直接放
		
		//遍历取出某个缓存中的所有值
		if(cacheManager.getCache("mycache-one")!=null){
			Cache cache11=cacheManager.getCache("mycache-one");
			if(cache11.getKeys().size()==0){
				System.out.println("mycache-one exits,but no value.");
			}else{
				for(int i=0;i<cache11.getKeys().size();i++){
					Object thekey=cache11.getKeys().get(i);
					Object thevalue=cache11.get(thekey);
					System.out.println("mycache-one-"+i+",key:"+thekey.toString()+",value:"+thevalue.toString());
				}
			}
		}else{
			System.out.println("mycache-one-is null");
		}
		
		/*打印
mycache-one-0,key:key1,value:[ key = key1, value=value1, version=1, hitCount=1, CreationTime = 1366263629054, LastAccessTime = 1366263629054 ]

		 */
		if(cacheManager.getCache("mycache-two")!=null){
			Cache cache2=cacheManager.getCache("mycache-two");
			if(cache2.getKeys().size()==0){
				System.out.println("mycache-two exits,but no value.");
			}else{
				for(int i=0;i<cache2.getKeys().size();i++){
					Object thekey=cache2.getKeys().get(i);
					Object thevalue=cache2.get(thekey);
					System.out.println("mycache-two-"+i+",key:"+thekey.toString()+",value:"+thevalue.toString());
				}
			}
		}else{
			System.out.println("mycache-two-is null");
		}
		/*打印
mycache-two exits,but no value.
		 */
		
		
	}
	
	

}



 

Ehcache在使用的大多数情况,是用ehcache.xml来配置的。在spring中的集成很方便。

下面我们使用ehcache.xml,但不在web环境下,对缓存进行自定义。

org/base/cache/test/myehcache.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
         updateCheck="true" monitoring="autodetect"
         dynamicConfig="true">

    
    <diskStore path="java.io.tmpdir"/>
    
    <!-- JTA事务配置。class属性若为空,则默认会按照一个顺序寻找TransactionManager对象。
              也可以自定义,需要实现接口net.sf.ehcache.transaction.manager.TransactionManagerLookup
    -->
    <!--
    <transactionManagerLookup class="net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup"
                              properties="jndiName=java:/TransactionManager" propertySeparator=";"/>
    -->

    <!-- CacheManagerEventListener  缓存监听,根据需要自定义监听类  
    <cacheManagerEventListenerFactory class="" properties=""/>
    -->
    
    <!-- Terracotta服务器集群配置,详细看文档 -->
    <!--
    <terracottaConfig url="localhost:9510"/>
    -->
    
    <defaultCache
           maxEntriesLocalHeap="0"
           eternal="false"
           timeToIdleSeconds="30"
           timeToLiveSeconds="30">
     <!-- <terracotta/>-->
    </defaultCache>

    <!--
           缓存名为myCache1,
    这个缓存最多包含10000个元素在内存中,并将
    闲置超过5分钟和存在超过10分钟的元素释放。
    如果超过10000元素,将溢流到磁盘缓存,并且硬盘缓存最大数量是1000.
           硬盘路径是定义的java.io.tmp。
    -->
    <cache name="myCache1"
           maxEntriesLocalHeap="500"
           maxEntriesLocalDisk="1000"
           eternal="false"
           diskSpoolBufferSizeMB="20"
           timeToIdleSeconds="300"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           transactionalMode="off">
        <persistence strategy="localTempSwap"/>
    </cache>


    <!--
            缓存名为sampleCache2。
    此缓存在内存中最大元素的数量是1000。
            没有设置溢出到磁盘,所以1000就是这个缓存的最大值。
            注意,当一个缓存eternal设置成true,那么TimeToLive
    和timeToIdle江不起作用。
    
    <cache name="sampleCache2"
           maxEntriesLocalHeap="1000"
           eternal="true"
           memoryStoreEvictionPolicy="FIFO"/>
-->

    <!-- 
           缓存名为sampleCache3的。
           这个缓存溢出会到磁盘。磁盘缓存存储在虚拟机重新启动前会持久有效。
           磁盘的终止线程的时间间隔设置为3分钟,覆盖默认的2分钟。
     
    <cache name="sampleCache3"
           maxEntriesLocalHeap="500"
           eternal="false"
           overflowToDisk="true"
           diskPersistent="true"
           timeToIdleSeconds="300"
           timeToLiveSeconds="600"
           diskExpiryThreadIntervalSeconds="180"
           memoryStoreEvictionPolicy="LFU">
    </cache>
-->
    <!-- 
    Terracotta集群缓存sampleTerracottaCache。
     
    <cache name="sampleTerracottaCache"
           maxBytesLocalHeap="10m"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="1800">
        <terracotta/>
    </cache>
-->
    

    
</ehcache>

 

 

关于配置的属性的含义,可以到官网的文档中查看,这里给出一些常用的属性。

 

    Cache的以下属性是必须的。

    name:
    cache的唯一标识。

    maxEntriesLocalHeap:
    在内存创建对象的最大数量。0=无限制。
    无限制实际指Integer.MAX_SIZE (2147483647)。

    maxEntriesLocalDisk:
    设置在硬盘上存储的对象的最大数量。默认0,即无限制。

    eternal:
    设置元素是否持久化。如果是,元素不会过期。









    Cache的以下属性是可选的。

    overflowToOffHeap:
    此功能仅在企业版的Ehcache。
    当设置为true,可利用无限制的离堆内存的缓存
    存储,以提高性能。离堆内存是不受Java
    GC限制的。默认值是false。

    maxBytesLocalHeap:
    定义多少字节缓存可能会使用虚拟机的堆。如果一个CacheManager的
    maxBytesLocalHeap已经被定义,这个缓存的指定金额将
    减去从CacheManager的。其他的高速缓存将分享剩下的人。
    此属性的值是<数字> K | K |米| M| G| G
    千字节(K| K),兆字节(M| M)或千兆字节(G| G)。
    例如,maxBytesLocalHeap的“2G”下发2 GB的堆内存。
    如果您指定一个maxBytesLocalHeap,就不能再使用属性maxEntriesLocalHeap。

    maxBytesLocalOffHeap:
    此功能仅在企业版的Ehcache。
    离堆内存量,可以使用这个缓存设置,将保留。
    此设置将设置overflowToOffHeap为true 。设置explicitly为false来禁用溢出行为。
    需要注意的是使用时离堆,设置maxEntriesLocalHeap建议至少100个元素,
    否则性能会出现严重退化,并提出警告。
    可分配的最低金额为128MB。没有最大值。



    maxBytesLocalDisk:
    As for maxBytesLocalHeap, but specifies the limit of disk storage this cache will ever use.

    timeToIdleSeconds:
    设置元素闲置时长。单位:秒。(在eternal设置成false的情况下有效)
    可选属性。值为0意味着元素可以闲置无穷。
    默认值是0。

    timeToLiveSeconds:
    设置元素过期时长。单位:秒。(在eternal设置成false的情况下有效)
    可选属性。值为0意味着,元素可以住无穷。
    默认值是0。

    diskExpiryThreadIntervalSeconds:
    磁盘到期线程运行之间的秒数。默认值为120秒。

    diskSpoolBufferSizeMB:
    这是分配硬盘存储的缓冲区的大小。信息被写入
    这个区域,然后异步写入到磁盘中。默认大小为30MB。
    每个缓冲区仅用于由其缓存。如果你遇到内存溢出错误试着
    降低此值。为了提高硬盘存储性能应考虑增加此值。

    clearOnFlush:
    调用flush()方法时,硬盘存储缓存被清除。
    默认值是true。

    memoryStoreEvictionPolicy:
    内存管理策略,默认是最近最少使用策略(即Least Recently Used,LRU)。
    其他可选的有先进先出策略(即 First In First Out,FIFO),最少使用频率策略
    (即Less Frequently Used,LFU)。

    copyOnRead:
    一个元素被复制时是否从缓存中读取。
    默认false。

    copyOnWrite:
    一个元素被添加到缓存中时是否被复制。
    默认false。



 


EhcacheManagerTest

 

package org.base.cache.test;

import java.net.URL;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.Status;

/**
 * Ehcache缓存管理的初步学习实例
 * @author lushuaiyin
 *
 */
public class EhcacheManagerTest {
	public static net.sf.ehcache.CacheManager cacheManager = null;
	private static String configPath="org/base/cache/test/myehcache.xml";//配置文件路径,一般会放在源文件夹
	
	private static String CACHE_MYCACHE1="myCache1";//定义文件中配置的缓存
	//实例化cacheManager,单例模式
	public static CacheManager getCacheManagerInstance(){
		if (cacheManager == null) {
			URL configUrl=null;
			configUrl = EhcacheManagerTest.class.getClassLoader().getResource(configPath);
			cacheManager = CacheManager.create(configUrl);
		}
		return cacheManager;
	}
	public static net.sf.ehcache.CacheManager getCacheManager() {
		return getCacheManagerInstance();//单例缓存管理
	}
	//这个set可以不开放
	public static void setCacheManager(net.sf.ehcache.CacheManager cacheManager) {
		EhcacheManagerTest.cacheManager = cacheManager;
	}
	
	//添加新缓存
	public static void addCacheByName(String cacheName){
		if(cacheName==null||cacheName.trim().equals("")){
			System.out.println("cacheName is null");
		}else{
			if(getCacheManager().getCache(cacheName.trim())!=null){
				getCacheManager().removeCache(cacheName.trim());
			}
			getCacheManager().addCache(cacheName.trim());
			System.out.println(cacheName+ "重新添加");
		}
	}
	//得到cache对象
	public static Cache getCacheByName(String cacheName){
		Cache cache=null;
		if(cacheName==null||cacheName.trim().equals("")){
			System.out.println("cacheName is null");
		}else{
			if(getCacheManager().getCache(cacheName.trim())!=null){
				cache=getCacheManager().getCache(cacheName.trim());
			}
		}
		
		return cache;
	}
	
	
	//往缓存中添加元素
	public static void putElementToCache(String cacheName,String elementKey,Object elementValue){
		Cache cache=null;
		if(cacheName==null||cacheName.trim().equals("")){
			System.out.println("添加缓存元素失败,cacheName is null");
		}else if(elementKey==null||elementValue==null){
			System.out.println("添加缓存元素失败,elementKey or elementValue is null");
		}else{
			if(getCacheByName(cacheName.trim())!=null){//缓存存在
				cache=getCacheByName(cacheName.trim());
			}else{//缓存不存在
				addCacheByName(cacheName.trim());
				cache=getCacheByName(cacheName.trim());
			}
			//对cache对象添加Element
			Element element=null;
			if(cache.get(elementKey.trim())!=null){
				cache.remove(elementKey.trim());
			}
			element=new Element(elementKey.trim(),elementValue);
			cache.put(element);
			System.out.println("添加缓存元素:"+elementKey+"成功!");
		}
		
	}
	
	//从缓存中获取指定key的值
	public static Object getElementValueFromCache(String cacheName,String elementKey){
		Object result=null;
		Cache cache=null;
		if(cacheName==null||cacheName.trim().equals("")){
			System.out.println("获取缓存元素失败,cacheName is null");
		}else if(elementKey==null){
			System.out.println("获取缓存元素失败,elementKey  is null");
		}else{
			if(getCacheByName(cacheName.trim())!=null){//缓存存在
				cache=getCacheByName(cacheName.trim());
				
				Element element=null;
				if(cache.get(elementKey.trim())!=null){
					element=cache.get(elementKey.trim());
					if(element.getObjectValue()==null){
						System.out.println("缓存中"+elementKey+" 的值为空.");
					}else{
						result=element.getObjectValue();
					}
				}else{
					System.out.println("缓存中"+elementKey+" 的Element值为空.");
				}
			}else{//缓存不存在
				System.out.println("获取缓存元素失败,缓存"+cacheName+" 为空.");
			}
		}
		
		return result;
	}
	
	/**
	 * 把所有cache中的内容删除,但是cache对象还是保留.
	 * Clears the contents of all caches in the CacheManager,
	 *  but without removing any caches.
	 */
	public static void clearAllFromCacheManager(){
		if(getCacheManager()!=null){
			getCacheManager().clearAll();
			System.out.println("CacheManager was clearAll...");
		}
	} 
	
	/**
	 * 把所有cache对象都删除。慎用!
	 * Removes all caches using removeCache(String) for each cache.
	 */
	public static void removalAllFromCacheManager(){
		if(getCacheManager()!=null){
			getCacheManager().removalAll();
			System.out.println("CacheManager was removalAll...");
		}
	} 
	//不用缓存时,要关闭,不然会占用cpu和内存资源。
	public static void shutdownCacheManager(){
		if(getCacheManager()!=null){
			getCacheManager().shutdown();
			System.out.println("CacheManager was shutdown...");
		}
	}
	
	
	//打印方法1,为了测试用
	public static void printCache(Cache cache){
		System.out.println("缓存状态: "+cache.getStatus().toString());
		if(cache==null){
			System.out.println("cache is null,no print info.");
		}else if(cache.getStatus().toString().equals(Status.STATUS_UNINITIALISED)){
			System.out.println("缓存状态: 未初始化"+cache.getStatus().toString());
		}else if(cache.getStatus().toString().equals(Status.STATUS_SHUTDOWN)){
			System.out.println("缓存状态: 已关闭"+cache.getStatus().toString());
		}else if(cache.getStatus().toString().equals(Status.STATUS_ALIVE)){
			if(cache.getKeys().size()==0){
				System.out.println(cache.getName()+" exits,but no value.");
			}else{
				for(int i=0;i<cache.getKeys().size();i++){
					Object thekey=cache.getKeys().get(i);
					Object thevalue=cache.get(thekey);
					System.out.println(cache.getName()+"--"+i+",key:"+thekey.toString()+",value:"+thevalue.toString());
				}
			}
		}
		
		
	}
	
	//打印方法2,为了测试用
	public static void printCacheByName(String cacheName){
		if(cacheName==null||cacheName.trim().equals("")){
			System.out.println("cacheName is null,no print info.");
		}else{
			if(getCacheManager().getCache(cacheName.trim())!=null){
				Cache cache=getCacheManager().getCache(cacheName.trim());
				printCache(cache);
			}else{
				System.out.println(cacheName+" --null");
			}
		}
		
		
	}
	
	public static void main(String[] sdfsf){
		Cache cache1=EhcacheManagerTest.getCacheByName(EhcacheManagerTest.CACHE_MYCACHE1);
		printCache(cache1);
		
		EhcacheManagerTest.putElementToCache(EhcacheManagerTest.CACHE_MYCACHE1, "111", "111haah");
		EhcacheManagerTest.putElementToCache(EhcacheManagerTest.CACHE_MYCACHE1, "222", "222haah");
		EhcacheManagerTest.putElementToCache(EhcacheManagerTest.CACHE_MYCACHE1, "333", "333haah");
		
		printCache(cache1);
		
		EhcacheManagerTest.putElementToCache(EhcacheManagerTest.CACHE_MYCACHE1, "111", "111的新值。");
		
		System.out.println(EhcacheManagerTest.getElementValueFromCache(EhcacheManagerTest.CACHE_MYCACHE1, "111"));
		printCache(cache1);
		
		clearAllFromCacheManager();
		printCache(cache1);
		
		removalAllFromCacheManager();
		printCache(cache1);
		
		shutdownCacheManager();
	}
	/*打印
缓存状态: STATUS_ALIVE
添加缓存元素:111成功!
添加缓存元素:222成功!
添加缓存元素:333成功!
缓存状态: STATUS_ALIVE
添加缓存元素:111成功!
111的新值。
缓存状态: STATUS_ALIVE
CacheManager was clearAll...
缓存状态: STATUS_ALIVE
CacheManager was removalAll...
缓存状态: STATUS_SHUTDOWN
CacheManager was shutdown...

	 */
}



 

通过上面的使用,我们初步了解Ehcache的api。在web环境下,我们可以注入EhcacheManager对象,

把需要的数据,放入缓存。在其他地方取数据的时候,就从过EhcacheManager来获取,而不是直接

从数据库查询。这样就提高了效率。

 

值得注意的是,缓存的使用一般在一些数据比较固定的地方。如果某个查询需要保证数据的实时性,使用缓存

就是错误的做法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值