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 }
View Code

应用

 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     }
View Code

 

posted @ 2022-02-22 12:02  zhangtianhong511  阅读(256)  评论(0)    收藏  举报