Ehcache缓存
参考:https://www.jb51.net/article/109777.htm 仅供学习
一、概念
EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点。它是Hibernate中的默认缓存框架。
Ehcache已经发布了3.1版本。但是本文的讲解基于2.10.2版本。因为Spring4还不能直接整合Ehcache 3.x。虽然可以通过JCache间接整合,Ehcache也支持JCache,但是个人觉得不是很方便。
作用:
把它当做一个可以存储数据和读取数据的存在。缓存其实就一个key-value的数据存储工具。
一是缓存数据库的数据。
都说连接数据库的开销很大,所以对数据变化较小的一部分可以缓存起来,下次直接从缓存中取数据。(关于数据的安全性未曾考虑)。
二是存储变量。
在web后端开发过程中,有些数据需要保存起来方便下次使用。比如短信的验证码。之前都是在类中添加一个map类变量,然后存入map,下次取出或者销毁。这样做是可以的,类实例化后。类变量就加载到内存中了,可以存储数据。但有个问题,关于类的创建和销毁的声明周期问题。不能确保他什么时候去销毁。
二、安装依赖、
如果项目使用maven管理,添加以下依赖到你的pom.xml中。
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.2</version> <type>pom</type> </dependency>
如果项目不使用maven管理,请在 Ehcache官网下载地址 下载jar包。
Spring
spring-context-support这个jar包中含有Spring对于缓存功能的抽象封装接口。
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.1.4.RELEASE</version> </dependency>
三、使用
基本操作:
Element、Cache、cacheManager是Ehcacle最重要的API
Element:缓存的元素,维护着一个键值对
Cache:是Ehcache的核心类,他有多个Element,并被CacheManager管理,它实现了对缓存的逻辑行为
CacheManager:Cache的容器对象, 并管理着Cache的生命周期。
(1) 在classpath下添加ehcache.xml 并添加一个名为helloworld的缓存。
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"> <!-- 磁盘缓存位置 --> <diskStore path="java.io.tmpdir/ehcache"/> <!-- 默认缓存 --> <defaultCache maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"/> <!-- helloworld缓存 --> <cache name="helloworld" maxElementsInMemory="1000" eternal="false" timeToIdleSeconds="5" timeToLiveSeconds="5" overflowToDisk="false" memoryStoreEvictionPolicy="LRU"/> </ehcache>
ehcache.xml配置参数说明:
- name:缓存名称。
- maxElementsInMemory:缓存最大个数。
- eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
- timeToIdleSeconds:置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
- timeToLiveSeconds:缓存数据的生存时间(TTL),也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
- maxEntriesLocalDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
- overflowToDisk:内存不足时,是否启用磁盘缓存。
- diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
- maxElementsOnDisk:硬盘最大缓存个数。
- diskPersistent:是否在VM重启时存储硬盘的缓存数据。默认值是false。
- diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
- memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
- clearOnFlush:内存数量最大时是否清除。
示例代码
public class EhcacheDemo {
 public static void main(String[] args) throws Exception {
  // Create a cache manager
  final CacheManager cacheManager = new CacheManager();
 
  // create the cache called "helloworld"
  final Cache cache = cacheManager.getCache("helloworld");
 
  // create a key to map the data to
  final String key = "greeting";
 
  // Create a data element
  final Element putGreeting = new Element(key, "Hello, World!");
 
  // Put the element into the data store
  cache.put(putGreeting);
 
  // Retrieve the data element
  final Element getGreeting = cache.get(key);
 
  // Print the value
  System.out.println(getGreeting.getObjectValue());
 }
}
创建CacheManager
// 使用Ehcache默认配置获取单例的CacheManager实例
CacheManager.create();
String[] cacheNames = CacheManager.getInstance().getCacheNames();
 
// 使用Ehcache默认配置新建一个CacheManager实例
CacheManager.newInstance();
String[] cacheNames = manager.getCacheNames();
 
// 使用不同的配置文件分别创建一个CacheManager实例
CacheManager manager1 = CacheManager.newInstance("src/config/ehcache1.xml");
CacheManager manager2 = CacheManager.newInstance("src/config/ehcache2.xml");
String[] cacheNamesForManager1 = manager1.getCacheNames();
String[] cacheNamesForManager2 = manager2.getCacheNames();
 
// 基于classpath下的配置文件创建CacheManager实例
URL url = getClass().getResource("/anotherconfigurationname.xml");
CacheManager manager = CacheManager.newInstance(url);
 
// 基于文件流得到配置文件,并创建CacheManager实例
InputStream fis = new FileInputStream(new File
("src/config/ehcache.xml").getAbsolutePath());
try {
 CacheManager manager = CacheManager.newInstance(fis);
} finally {
 fis.close();
}
添加缓存
// 除了可以使用xml文件中配置的缓存,你也可以使用API动态增删缓存
// 添加缓存
manager.addCache(cacheName);
 
// 使用默认配置添加缓存
CacheManager singletonManager = CacheManager.create();
singletonManager.addCache("testCache");
Cache test = singletonManager.getCache("testCache");
 
// 使用自定义配置添加缓存,注意缓存未添加进CacheManager之前并不可用
CacheManager singletonManager = CacheManager.create();
Cache memoryOnlyCache = new Cache("testCache", 5000, false, false, 5, 2);
singletonManager.addCache(memoryOnlyCache);
Cache test = singletonManager.getCache("testCache");
 
// 使用特定的配置添加缓存
CacheManager manager = CacheManager.create();
Cache testCache = new Cache(
 new CacheConfiguration("testCache", maxEntriesLocalHeap)
 .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LFU)
 .eternal(false)
 .timeToLiveSeconds(60)
 .timeToIdleSeconds(30)
 .diskExpiryThreadIntervalSeconds(0)
 .persistence(new PersistenceConfiguration().strategy(Strategy.LOCALTEMPSWAP)));
 manager.addCache(testCache);
删除缓存
CacheManager singletonManager = CacheManager.create();
singletonManager.removeCache("sampleCache1");
实现基本缓存操作
/**
 * 测试:使用默认配置或使用指定配置来创建CacheManager
 *
 * @author victor zhang
 */
public class CacheOperationTest {
 private final Logger log = LoggerFactory.getLogger(CacheOperationTest.class);
 
 /**
  * 使用Ehcache默认配置(classpath下的ehcache.xml)获取单例的CacheManager实例
  */
 @Test
 public void operation() {
  CacheManager manager = CacheManager.newInstance("src/test/resources/ehcache/ehcache.xml");
 
  // 获得Cache的引用
  Cache cache = manager.getCache("userCache");
 
  // 将一个Element添加到Cache
  cache.put(new Element("key1", "value1"));
 
  // 获取Element,Element类支持序列化,所以下面两种方法都可以用
  Element element1 = cache.get("key1");
  // 获取非序列化的值
  log.debug("key:{}, value:{}", element1.getObjectKey(), element1.getObjectValue());
  // 获取序列化的值
  log.debug("key:{}, value:{}", element1.getKey(), element1.getValue());
 
  // 更新Cache中的Element
  cache.put(new Element("key1", "value2"));
  Element element2 = cache.get("key1");
  log.debug("key:{}, value:{}", element2.getObjectKey(), element2.getObjectValue());
 
  // 获取Cache的元素数
  log.debug("cache size:{}", cache.getSize());
 
  // 获取MemoryStore的元素数
  log.debug("MemoryStoreSize:{}", cache.getMemoryStoreSize());
 
  // 获取DiskStore的元素数
  log.debug("DiskStoreSize:{}", cache.getDiskStoreSize());
 
  // 移除Element
  cache.remove("key1");
  log.debug("cache size:{}", cache.getSize());
 
  // 关闭当前CacheManager对象
  manager.shutdown();
 
  // 关闭CacheManager单例实例
  CacheManager.getInstance().shutdown();
 }
}
四、项目示例
工具类
 
1 import net.sf.ehcache.Cache; 2 import net.sf.ehcache.Element; 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.cache.ehcache.EhCacheCacheManager; 5 import org.springframework.stereotype.Component; 6 7 import java.util.Map; 8 9 /** 10 * ehcache缓存帮助类 11 */ 12 @Component(value = "ehcacheUtils") 13 public class EhcacheUtils { 14 @Autowired 15 private EhCacheCacheManager cacheManager; 16 17 public Cache getCache(String cacheName){ 18 return cacheManager.getCacheManager().getCache(cacheName); 19 } 20 public boolean cacheExists(String cacheName){ 21 return cacheManager.getCacheManager().cacheExists(cacheName); 22 } 23 public void putDataByCacheName(String cacheName,String key,Object value){ 24 Element element = new Element(key,value); 25 Cache cache = cacheManager.getCacheManager().getCache(cacheName); 26 if(cache !=null){ 27 cache.put(element); 28 }else{ 29 cacheManager.getCacheManager().addCache(cacheName); 30 cache = cacheManager.getCacheManager().getCache(cacheName); 31 cache.put(element); 32 } 33 } 34 35 public void putDataByCacheNameLock(String cacheName,String key,Object value){ 36 Cache cache = cacheManager.getCacheManager().getCache(cacheName); 37 if(cache == null){ 38 cacheManager.getCacheManager().addCache(cacheName); 39 cache = cacheManager.getCacheManager().getCache(cacheName); 40 } 41 42 cache.acquireWriteLockOnKey(key); 43 try { 44 Element element = new Element(key,value); 45 cache.put(element); 46 }finally { 47 cache.releaseWriteLockOnKey(key); 48 } 49 } 50 public void deleteCache(String cacheName){ 51 cacheManager.getCacheManager().removeCache(cacheName); 52 } 53 54 public Element getElementByKey(String cacheName,String key){ 55 Cache cache = cacheManager.getCacheManager().getCache(cacheName); 56 if(cache == null){ 57 return null; 58 } 59 return cache.get(key); 60 } 61 public void deleteElementByKey(String cacheName,String key){ 62 Cache cache = cacheManager.getCacheManager().getCache(cacheName); 63 if(cache !=null){ 64 cache.remove(key); 65 } 66 } 67 68 public Map<Object,Element> getAllElement(String cacheName){ 69 Cache cache = cacheManager.getCacheManager().getCache(cacheName); 70 if(cache == null){ 71 return null; 72 } 73 return cache.getAll(cache.getKeys()); 74 } 75 76 public Object getValueByKey(String cacheName,String key){ 77 Cache cache = cacheManager.getCacheManager().getCache(cacheName); 78 Element element = cache.get(key); 79 if(element !=null){ 80 return element.getObjectKey(); 81 } 82 return null; 83 } 84 }
应用
 
1 @Override 2 public Area findById(AreaParam param){ 3 try{ 4 MessageParam updateParam = new MessageParam(); 5 updateParam.setAction(param.getAction()); 6 updateParam.setOldNo(param.getOldNo()); 7 updateParam.setDataType(RabbitDataType.AREA_DATA_TYPE); 8 Area area = null; 9 if(param.getAction() !=null && param.getAction().equals(0)){ 10 if (StringUtils.isNotBlank(param.getAreaCode())) { 11 Element obj = ehcacheUtils.getElementByKey(EhcachekeyConstant.AREA_SUBSCRIBE_LIST,"a_"+ param.getAreaCode()); 12 if(obj !=null){ 13 area = (Area) obj.getObjectValue(); 14 }else if(redisUtils.hasHKey(RedisKeyConstant.IMINE_AREA_DATA_SUBSCRIBE,"a_"+param.getAreaCode())){ 15 Object obj1 = redisUtils.hGet(RedisKeyConstant.IMINE_AREA_DATA_SUBSCRIBE,"a_"+param.getAreaCode()); 16 area = new Gson().fromJson(obj1.toString(),Area.class); 17 18 } 19 }else if(area !=null && param.getAreaId() !=null && redisUtils.hasHKey(RedisKeyConstant.IMINE_AREA_DATA_SUBSCRIBE_ID,"id_"+param.getAreaId())){ 20 Object obj = redisUtils.hGet(RedisKeyConstant.IMINE_AREA_DATA_SUBSCRIBE_ID,"id_"+param.getAreaId()); 21 area = new Gson().fromJson(obj.toString(),Area.class); 22 } 23 redisUtils.hDelete(RedisKeyConstant.IMINE_AREA_DATA_SUBSCRIBE,"a_"+param.getAreaCode()); 24 redisUtils.hDelete(RedisKeyConstant.IMINE_AREA_DATA_SUBSCRIBE_ID,"id_"+param.getAreaId()); 25 redisUtils.hDelete(RedisKeyConstant.IMINE_AREA_DATA_SUBSCRIBE,"a_"+param.getOldNo()); 26 ehcacheUtils.deleteElementByKey(EhcachekeyConstant.AREA_SUBSCRIBE_LIST,"a_"+param.getOldNo()); 27 ehcacheUtils.deleteElementByKey(EhcachekeyConstant.AREA_SUBSCRIBE_LIST,"a_"+param.getAreaCode()); 28 updateParam.setObjNo(area.getAreaCode()); 29 rabbitMQUtil.sendNotic(updateParam); 30 return area; 31 } 32 redisUtils.hDelete(RedisKeyConstant.IMINE_AREA_DATA_SUBSCRIBE,"a_"+param.getOldNo()); 33 ehcacheUtils.deleteElementByKey(EhcachekeyConstant.AREA_SUBSCRIBE_LIST,"a_"+param.getOldNo()); 34 area = areaMapper.findById(param); 35 String haskey = "a_"+area.getAreaCode(); 36 String idKey = "id_"+area.getAreaId(); 37 if(area!=null){ 38 Object object= hGet(RedisKeyConstant.AREA_OVERMAN_ACTION,area.getAreaCode()); 39 if(object!=null){ 40 Gson gson = new Gson(); 41 ActiveObj activeObj = gson.fromJson(object.toString(),ActiveObj.class); 42 String strJson = activeObj.getTriggerJson().toString(); 43 TriggerConf triggerConf = gson.fromJson(strJson, TriggerConf.class); 44 area.setAllowNum(triggerConf.getCondition().getLimitNum()); 45 area.setIsWhiteList(triggerConf.getCondition().getIsWhiteList()); 46 area.setDutyList(triggerConf.getCondition().getDutyList()); 47 } 48 redisUtils.hPut(RedisKeyConstant.IMINE_AREA_DATA_SUBSCRIBE,haskey,area); 49 redisUtils.hPut(RedisKeyConstant.IMINE_AREA_DATA_SUBSCRIBE_ID,idKey,area); 50 ehcacheUtils.putDataByCacheNameLock(EhcachekeyConstant.AREA_SUBSCRIBE_LIST,haskey,area); 51 } 52 updateParam.setObjNo(area.getAreaCode()); 53 rabbitMQUtil.sendNotic(updateParam); 54 return area; 55 }catch (Exception ex){ 56 log.error("AreaServiceImpl:findById:"+ex.getMessage()+":"+param.getAreaId()); 57 } 58 return null; 59 }
 
                    
                     
                    
                 
                    
                
 
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号