一、什么是ehcache?
在互联网应用中,数据存储和访问通常有两个地方:DB和缓存。
1. 各自的优缺点:DB属于持久化存储,缓存属于非持久化存储(有过期时间);缓存相对DB来说,插入和访问的速度要快很多。其中缓存又分为本地缓存(例如ehcache)和网络缓存(例如redis)。
2. 它们三者的访问速度比较:ehcache > redis > DB。
ehcache的特点是缓存容量小,但是存取速度快(没有网络传输消耗);redis缓存容量大,存取速度次之(因为redis缓存服务器通常单独部署在应用主机以外);DB存取速度最慢。
3. ehcache作为本地缓存,是可以共用的,即一个地方存,另一个地方可以直接使用。
使用流程一般是:先从本地缓存ehcache中取,取不到再从网络缓存redis里取,再取不到就从DB里取,中间每一步如果取到了,就将值set到对应的存储容器里,以便下次就可以直接获取到。
二、ehcache的使用方法:
1.现在pom.xml里加入ehcache的坐标:
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.10</version>
</dependency>
2.在src目录下添加一个ehcache的配置文件:ehcache.xml
此配置文件就是ehcache的使用策略配置
<defaultCache
maxEntriesLocalHeap="1000000"
eternal="false"
timeToIdleSeconds="60"
timeToLiveSeconds="120"
diskSpoolBufferSizeMB="128"
maxEntriesLocalDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</defaultCache>
<cache name="ESBController"
maxEntriesLocalHeap="1000000"
eternal="false"
timeToIdleSeconds="60"
timeToLiveSeconds="120"
diskSpoolBufferSizeMB="128"
maxEntriesLocalDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</cache>
参数介绍:
http://zzy603.iteye.com/blog/1153100
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<!--timeToIdleSeconds 当缓存闲置n秒后销毁 -->
<!--timeToLiveSeconds 当缓存存活n秒后销毁 -->
<!--
缓存配置
name:缓存名称。
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
-->
3. 创建一个ehcache的api工具类:
public class EhcacheUtil {
private static URL url = EhcacheUtil.class.getClass().getResource("/ehcache.xml");
private static CacheManager manager = new CacheManager(url);
private EhcacheUtil() {
}
private static class EhcacheUtilHolder {
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static EhcacheUtil instance = new EhcacheUtil();
}
public static EhcacheUtil getInstance() {
return EhcacheUtilHolder.instance;
}
/**
* 添加指定名称的cache
* @param cacheName
*/
public static void addCache(String cacheName){
EhcacheUtil.manager.addCache(cacheName);
}
/**
* 获取指定名称的cache
* @param cacheName
*/
public static Cache getCache(String cacheName){
return EhcacheUtil.manager.getCache(cacheName);
}
/**
* 往指定名称的cache里添加元素
* @param cacheName
* @param element
*/
public static void putElement(String cacheName, Element element){
EhcacheUtil.getCache(cacheName).put(element);
}
/**
* 往指定名称的cache里添加key和value
* @param cacheName
* @param key
* @param value
*/
public static void putElement(String cacheName, Object key, Object value){
if(EhcacheUtil.getCache(cacheName) == null){
EhcacheUtil.addCache(cacheName);
}
Element element = new Element(key, value);
EhcacheUtil.getCache(cacheName).put(element);
}
/**
* 获取指定名称的cache里的指定key对应的元素
* @param cacheName
* @param key
* @return 元素
*/
public static Element getElementByKey(String cacheName, String key){
if(EhcacheUtil.getCache(cacheName) == null){
EhcacheUtil.addCache(cacheName);
}
return EhcacheUtil.getCache(cacheName).get(key);
}
/**
* 获取指定名称的cache里的指定key对应的value
* @param cacheName
* @param key
* @return 元素value
*/
public static Object getValueByKey(String cacheName, String key){
if(EhcacheUtil.getCache(cacheName) == null){
EhcacheUtil.addCache(cacheName);
}
Element element = EhcacheUtil.getCache(cacheName).get(key);
if(element != null) {
return element.getObjectValue();
}
return null;
}
/**
* flush cache
*/
public static void clear(String cacheName){
if(EhcacheUtil.getCache(cacheName) == null){
return;
}
EhcacheUtil.getCache(cacheName).flush();
}
/**
* 测试
* @param args
*/
public static void main(String [] args) {
String cacheName = "testCache";
// 添加cache
EhcacheUtil.addCache(cacheName);
// 获取cache
Cache cache = EhcacheUtil.getCache(cacheName);
// put元素
Element element1 = new Element("id", "14073034");
cache.put(element1);
Element element2 = new Element("name", "guweiqiang");
cache.put(element2);
// get元素
Element element11 = EhcacheUtil.getElementByKey("testCache", "id");
Object value11 = element11.getObjectValue();
if(value11 != null) {
System.out.println("value11:" + value11.toString());
}
// 清除cache
EhcacheUtil.clear(cacheName);
// get元素
Object value12 = EhcacheUtil.getValueByKey(cacheName, "name");
if(value12 != null) {
System.out.println("value12:" + value12.toString());
}
}
}
在使用它的地方:
ActivityDto activity = null;
activity = (ActivityDto) EhcacheUtil.getValueByKey(ConstantUtil.ACTIVITY_EHCACHE_NAME, ConstantUtil.ACTIVITY_EHCACHE_KEY);
if (activity == null) {
synchronized (ActivityDto.class) {
if (activity == null) {
ResponseDTO<ActivityDto> activityRes = activityService.getActivity();
if (activityRes.getMessage().isSuccess() && activityRes.getResult() != null) {
activity = activityRes.getResult();
EhcacheUtil.putElement(ConstantUtil.ACTIVITY_EHCACHE_NAME, ConstantUtil.ACTIVITY_EHCACHE_KEY, activity);
}
}
}
}