缓存工具类 缓存名创建后即使移除缓存,也不会重新创建
package zj.cache.util;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.apache.log4j.Logger;
import zj.cache.bean.CacheModel;
import zj.check.util.CheckUtil;
import zj.common.exception.ServiceException;
import zj.io.util.FileUtil;
import zj.java.util.JavaUtil;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.util.*;
/**
* 缓存工具类 缓存名创建后即使移除缓存,也不会重新创建
*
* @version 1.00 (2014.09.15)
* @author SHNKCS 张军 {@link <a target=_blank href="http://www.shanghaijiadun.com">上海加盾信息科技有限公司</a> <a target=_blank href="http://www.zhangjunbk.com">张军个人网站</a> <a target=_blank href="http://user.qzone.qq.com/360901061/">张军QQ空间</a>}
*/
public class EhCacheUtil implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(EhCacheUtil.class.getName());
private static CacheManager cacheManager;
public static String DEFAULT_CACHE_FILE = "/ehcache.xml";
private static final String DEFAULT_CACHE_KEY = "www.zhangjunbk.com";
/**
* 获取缓存管理器
*
* @return 缓存管理器
*/
public static synchronized CacheManager getCacheManager() {
return getCacheManager(DEFAULT_CACHE_FILE);
}
/**
* 根据ehcache文件路径获取缓存管理器对象
*
* @param filePath
* ehcache文件路径,默认classes下的/ehcache.xml文件
* @return 缓存管理器对象
*/
public static synchronized CacheManager getCacheManager(String filePath) {
if (cacheManager == null) {
try {
if (CheckUtil.isNull(filePath)) {
filePath = DEFAULT_CACHE_FILE;
}
File file = new File(FileUtil.getPathByResourceNoException(filePath));
if (file.isDirectory()) {
file = new File(file, "ehcache.xml");
// logger.debug("【不存在】缓存文件【" + FileUtil.linuxSeparator(file.getAbsolutePath()) + "】");
}
if (!file.exists()) {
file = new File(filePath);
// logger.debug("【不存在】缓存文件【" + FileUtil.linuxSeparator(file.getAbsolutePath()) + "】");
}
if (!file.exists()) {
file = new File(DEFAULT_CACHE_FILE);
// logger.debug("【不存在】缓存文件【" + FileUtil.linuxSeparator(file.getAbsolutePath()) + "】");
}
if (!file.exists()) {
if (JavaUtil.isWindows()) {
file = new File("C:", DEFAULT_CACHE_FILE);
} else {
file = new File("/tmp", DEFAULT_CACHE_FILE);
}
// logger.debug("【不存在】缓存文件【" + FileUtil.linuxSeparator(file.getAbsolutePath()) + "】");
}
if (!file.exists()) {
file = new File(System.getProperty("java.io.tmpdir"), DEFAULT_CACHE_FILE);
// logger.debug("【不存在】缓存文件【" + FileUtil.linuxSeparator(file.getAbsolutePath()) + "】");
}
if (!file.exists()) {
file = new File(System.getProperty("user.dir"), DEFAULT_CACHE_FILE);
// logger.debug("【不存在】缓存文件【" + FileUtil.linuxSeparator(file.getAbsolutePath()) + "】");
}
if (file.exists()) {
logger.debug("【成功】缓存配置文件路径:" + FileUtil.linuxSeparator(file.getAbsolutePath()));
// ehcache_auto_created_1420510852968创建是因为ehcache.xml文件和二级缓存中的文件是同一个文件
// 日志:Creating a new instance of CacheManager using the diskStorePath
cacheManager = CacheManager.create(file.getAbsolutePath());
} else {
InputStream is = EhCacheUtil.class.getResourceAsStream(DEFAULT_CACHE_FILE);
if (is == null) {
throw new ServiceException("未找到ehcache.xml文件");
} else {
logger.debug("【成功】根据流创建缓存");
cacheManager = CacheManager.create(is);
}
}
} catch (Exception e) {
logger.error("创建缓存对象失败", e);
} finally {
if (cacheManager == null) {
// 创建默认的cacheManager
cacheManager = CacheManager.getInstance();
logger.warn("创建默认的缓存管理器");
}
}
}
return cacheManager;
}
// Cache构造函数
// Cache(java.lang.String name, int maxElementsInMemory, boolean
// overflowToDisk, boolean eternal, long timeToLiveSeconds, long
// timeToIdleSeconds, boolean diskPersistent, long
// diskExpiryThreadIntervalSeconds);
/**
* 根据缓存名获取缓存对象(可以在系统启动的时候调用即可)
*
* @param cacheName
* 缓存名称
* @param timeToLiveSeconds
* 存活时间在180秒内
* @param timeToIdleSeconds
* 相邻2次获取数据的时间间隔如果小于60秒(timeToIdleSeconds)
* @return
*/
public static synchronized Cache getCache(String cacheName, long timeToLiveSeconds, long timeToIdleSeconds) {
// 1.必须要有的属性:
// name: cache的名字,用来识别不同的cache,必须惟一。
// maxElementsInMemory: 内存管理的缓存元素数量最大限值。(内存中存储对象的最大值)
// maxElementsOnDisk: 硬盘管理的缓存元素数量最大限值。默认值为0,就是没有限制。
// eternal: 设定元素是否持久话。若设为true,则缓存元素不会过期。
// overflowToDisk: 设定是否在内存填满的时候把数据转到磁盘上。
// 2.下面是一些可选属性:
// timeToIdleSeconds: 设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
// timeToLiveSeconds: 设置Element在失效前允许存活时间。最大时间介于创建时间和失效时间之间。仅当element不是永久有效时使用,默认是0.,也就是element存活时间无穷大。其他与timeToIdleSeconds类似。
// diskPersistent: 设定在虚拟机重启时是否进行磁盘存储,默认为false.(我的直觉,对于安全小型应用,宜设为true)。
// diskExpiryThreadIntervalSeconds: 访问磁盘线程活动时间。
// diskSpoolBufferSizeMB: 存入磁盘时的缓冲区大小,默认30MB,每个缓存都有自己的缓冲区。
// memoryStoreEvictionPolicy: 元素逐出缓存规则。共有三种,Recently Used (LRU)最近最少使用,为默认。 First In First Out (FIFO),先进先出。Less Frequently Used(specified as LFU)最少使用。
// clearOnFlush:内存数量最大时是否清除。
// 首先来说明一下这两个属性分别有什么作用:(当然,只有在eternal为false时,这2个属性才有效)
// timeToLiveSeconds 当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除;即缓存自创建日期起能够存活的最长时间,单位为秒(s)
// timeToIdleSeconds 当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清空;即缓存被创建后,最后一次访问时间到缓存失效之时,两者之间的间隔,单位为秒(s)
// 什么意思呢?
// 现在假设有如下配置:
// timeToIdleSeconds=60
// timeToLiveSeconds=180
// 则一个数据被添加进缓存后,该数据能够在缓存中存活的最长时间为180秒(timeToLiveSeconds),而在180秒内,假设不止一次去缓存中拿取该数据,那么相邻2次获取数据的时间间隔如果小于60秒(timeToIdleSeconds),则能成功获取到数据,但如果最近一次获取到下一次获取的时间间隔超过60秒,那么,将得到null,因为此时该数据已经被移出缓存了。
// 而且,timeToLiveSeconds必须大于timeToIdleSeconds才有意义。
Cache cache = getCacheManager().getCache(cacheName);
if (cache == null) {
cache = new Cache(cacheName, 10000, true, false, timeToLiveSeconds, timeToIdleSeconds, false, 120);
getCacheManager().addCache(cache);
logger.debug("创建缓存:" + cacheName);
} else {
// logger.debug("缓存存在:" + cacheName);
}
return cache;
}
// ------------------------------------------------------------------------------------------------------
/**
* 根据缓存名获取缓存对象(永久缓存) 如果未获取到,超时缓存也被设置为永久缓存
*
* @param cacheName
* 缓存名
* @return 缓存对象
*/
public static synchronized Cache getCache(String cacheName) {
// 1.必须要有的属性:
// name: cache的名字,用来识别不同的cache,必须惟一。
// maxElementsInMemory: 内存管理的缓存元素数量最大限值。(内存中存储对象的最大值)
// maxElementsOnDisk: 硬盘管理的缓存元素数量最大限值。默认值为0,就是没有限制。
// eternal: 设定元素是否持久话。若设为true,则缓存元素不会过期。
// overflowToDisk: 设定是否在内存填满的时候把数据转到磁盘上。
// 2.下面是一些可选属性:
// timeToIdleSeconds: 设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
// timeToLiveSeconds: 设置Element在失效前允许存活时间。最大时间介于创建时间和失效时间之间。仅当element不是永久有效时使用,默认是0.,也就是element存活时间无穷大。其他与timeToIdleSeconds类似。
// diskPersistent: 设定在虚拟机重启时是否进行磁盘存储,默认为false.(我的直觉,对于安全小型应用,宜设为true)。
// diskExpiryThreadIntervalSeconds: 访问磁盘线程活动时间。
// diskSpoolBufferSizeMB: 存入磁盘时的缓冲区大小,默认30MB,每个缓存都有自己的缓冲区。
// memoryStoreEvictionPolicy: 元素逐出缓存规则。共有三种,Recently Used (LRU)最近最少使用,为默认。 First In First Out (FIFO),先进先出。Less Frequently Used(specified as LFU)最少使用。
// clearOnFlush:内存数量最大时是否清除。
// 首先来说明一下这两个属性分别有什么作用:(当然,只有在eternal为false时,这2个属性才有效)
// timeToLiveSeconds 当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除;即缓存自创建日期起能够存活的最长时间,单位为秒(s)
// timeToIdleSeconds 当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清空;即缓存被创建后,最后一次访问时间到缓存失效之时,两者之间的间隔,单位为秒(s)
// 什么意思呢?
// 现在假设有如下配置:
// timeToIdleSeconds=60
// timeToLiveSeconds=180
// 则一个数据被添加进缓存后,该数据能够在缓存中存活的最长时间为180秒(timeToLiveSeconds),而在180秒内,假设不止一次去缓存中拿取该数据,那么相邻2次获取数据的时间间隔如果小于60秒(timeToIdleSeconds),则能成功获取到数据,但如果最近一次获取到下一次获取的时间间隔超过60秒,那么,将得到null,因为此时该数据已经被移出缓存了。
// 而且,timeToLiveSeconds必须大于timeToIdleSeconds才有意义。
Cache cache = getCacheManager().getCache(cacheName);
if (cache == null) {
cache = new Cache(cacheName, 10000, true, true, 0, 0, false, 120);
getCacheManager().addCache(cache);
}
return cache;
}
/**
* 获取key
*
* @param key
* @return
*/
private static synchronized String getKey(String key) {
if (CheckUtil.isNull(key)) {
key = DEFAULT_CACHE_KEY;
}
return key;
}
/**
* 设置缓存数据
*
* @param cacheName
* 缓存名
* @param key
* 缓存键
* @param value
* 缓存值
*/
public static synchronized <T> void put(String cacheName, String key, T value) {
Cache cache = getCache(cacheName);
key = getKey(key);
cache.put(new Element(key, value));
}
/**
* 设置缓存数据对象
*
* @param cacheName
* 缓存名
* @param value
* 缓存值(以{@link #DEFAULT_CACHE_KEY}为键,值为值)
*/
public static synchronized <T> void put(String cacheName, T value) {
put(cacheName, null, value);
}
/**
* 设置缓存数据
*
* @param cacheName
* 缓存名
* @param map
* 缓存值(以map中的key为键,值为值)
*/
public static synchronized <T> void put(String cacheName, Map<String, T> map) {
Cache cache = getCache(cacheName);
for (String key : map.keySet()) {
cache.put(new Element(key, map.get(key)));
}
}
/**
* 获取缓存数据
*
* @param cacheName
* 缓存名
* @param key
* 缓存键
* @return 缓存数据
*/
@SuppressWarnings("unchecked")
public static synchronized <T> T get(String cacheName, String key) {
Cache cache = getCache(cacheName);
key = getKey(key);
Element element = cache.get(key);
if (element == null) {
return null;
}
// 1.2.3版本
// return (T) element.getValue();
return (T) element.getObjectValue();
}
/**
* 获取缓存数据
*
* @param cacheName
* 缓存名
* @return 缓存数据
*/
public static synchronized <T> T getT(String cacheName) {
return get(cacheName, null);
}
/**
* 获取缓存数据
*
* @param cacheName
* 缓存名
* @return 缓存数据
*/
@SuppressWarnings("unchecked")
public static synchronized <T> Map<String, T> get(String cacheName) {
Map<String, T> map = new HashMap<String, T>();
Cache cache = getCache(cacheName);
List<String> list = (List<String>) cache.getKeys();
for (Iterator<String> it = list.iterator(); it.hasNext();) {
String key = it.next();
// 1.2.3版本
// map.put(key, (T) cache.get(key).getValue());
map.put(key, (T) cache.get(key).getObjectValue());
}
return map;
}
/**
* 获取所有缓存键
*
* @return 所有缓存数据
*/
public static synchronized <T> List<String> getCacheNames() {
return Arrays.asList(getCacheManager().getCacheNames());
}
/**
* 获取所有缓存数据
*
* @return 所有缓存数据
*/
@SuppressWarnings("unchecked")
public static synchronized <T> List<CacheModel<T>> getAllCache() {
List<CacheModel<T>> list = new ArrayList<CacheModel<T>>();
String[] cacheNames = getCacheManager().getCacheNames();
// 1.2.3版本
// if (cacheNames != null) {
// for (String cacheName : cacheNames) {
// Cache cache = this.getCache(cacheName);
// CacheModel<T> cacheModel = new CacheModel<T>();
// cacheModel.setName(cacheName);
// cacheModel.setCacheMap(this.get(cacheName));
// cacheModel.setCacheSize(cache.getSize());
// cacheModel.setMemoryStoreSize(cache.getMemoryStoreSize());
// int cacheHits = cache.getStatistics().getCacheHits();
// cacheModel.setCacheHits(cacheHits);
// int misses = cache.getStatistics().getCacheMisses();
// cacheModel.setCacheMisses(misses);
// list.add(cacheModel);
// }
// }
if (cacheNames != null) {
for (String cacheName : cacheNames) {
Cache cache = getCache(cacheName);
CacheModel<T> cacheModel = new CacheModel<T>();
cacheModel.setName(cacheName);
cacheModel.setCacheMap((Map<String, T>) get(cacheName));
cacheModel.setCacheSize(cache.getSize());
cacheModel.setMemoryStoreSize(cache.getStatistics().getLocalHeapSize());
cacheModel.setCacheHits(cache.getStatistics().cacheHitCount());
cacheModel.setCacheMisses(cache.getStatistics().cacheMissCount());
list.add(cacheModel);
}
}
return list;
}
/**
* 移除缓存数据
*
* @param cacheName
* 缓存名
* @see #remove(String)
*/
@Deprecated
public static synchronized void removeCache(String cacheName) {
getCacheManager().removeCache(cacheName);
}
/**
* 移除缓存数据
*
* @param cacheName
* 缓存名
* @param key
* 缓存键
*/
public static synchronized void remove(String cacheName, String key) {
Cache cache = getCache(cacheName);
key = getKey(key);
cache.remove(key);
}
/**
* 移除缓存数据
*
* @param cacheName
* 缓存名
*/
public static synchronized void remove(String cacheName) {
getCacheManager().removeCache(cacheName);
}
/**
* 停止缓存
*/
public static synchronized void shutdown() {
getCacheManager().shutdown();
}
/**
* 停止所有缓存
*/
public static synchronized void removalAll() {
// 1.2.3版本
// cacheManager.removalAll();
// getCacheManager().removeAllCaches();
// 调用上面方法后删除缓存报An API change between ehcache-1.1 and ehcache-1.2 results in the persistence path being set to C:\Users\ADMINI~1\AppData\Local\Temp\ when the ehcache-1.1 constructor is used. Please change to the 1.2 constructor.
// 再设置缓存无效了,使用下面方法
List<String> cacheNames = getCacheNames();
for (String cacheName : cacheNames) {
remove(cacheName);
}
}
}Cache封装类
package zj.cache.bean;
import java.io.Serializable;
import java.util.Map;
/**
* Cache封装类
*
* @version 1.00 (2014.09.15)
* @author SHNKCS 张军 {@link <a target=_blank href="http://www.zhangjunbk.com">张军个人网站</a> <a target=_blank href="http://user.qzone.qq.com/360901061/">张军QQ空间</a>}
*/
public class CacheModel<T> implements Serializable {
private static final long serialVersionUID = 1l;
private String name;
private Map<String, T> cacheMap;
private int cacheSize;
private long memoryStoreSize;
private long cacheHits;
private long cacheMisses;
/**
* 获取缓存键名
*
* @return 缓存键名
*/
public String getName() {
return name;
}
/**
* 设置缓存名字
*
* @param name
* 缓存名字
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取缓存中所有对象
*
* @return 缓存中所有对象
*/
public Map<String, T> getCacheMap() {
return cacheMap;
}
/**
* 设置缓存中所有对象
*
* @param cacheMap
* 缓存中所有对象
*/
public void setCacheMap(Map<String, T> cacheMap) {
this.cacheMap = cacheMap;
}
/**
* 获取缓存中对象数
*
* @return 缓存中对象数
*/
public int getCacheSize() {
return cacheSize;
}
/**
* 设置缓存中对象数
*
* @param cacheSize
* 缓存对象数
*/
public void setCacheSize(int cacheSize) {
this.cacheSize = cacheSize;
}
/**
* 获取缓存读取的命中次数
*
* @return 缓存读取的命中次数
*/
public long getCacheHits() {
return cacheHits;
}
/**
* 设置缓存读取的命中次数
*
* @param cacheHits
* 缓存读取的命中次数
*/
public void setCacheHits(long cacheHits) {
this.cacheHits = cacheHits;
}
/**
* 获取缓存读取的错失次数
*
* @return 缓存读取的错失次数
*/
public long getCacheMisses() {
return cacheMisses;
}
/**
* 设置缓存读取的错失次数
*
* @param cacheMisses
* 缓存读取的错失次数
*/
public void setCacheMisses(long cacheMisses) {
this.cacheMisses = cacheMisses;
}
/**
* 获取缓存对象占用内存的大小
*
* @return 缓存对象占用内存的大小
*/
public long getMemoryStoreSize() {
return memoryStoreSize;
}
/**
* 设置缓存对象占用内存的大小
*
* @param memoryStoreSize
* 缓存对象占用内存的大小
*/
public void setMemoryStoreSize(long memoryStoreSize) {
this.memoryStoreSize = memoryStoreSize;
}
}
本文为张军原创文章,转载无需和我联系,但请注明来自张军的军军小站,个人博客http://www.zhangjunbk.com

