緩存工具類 緩存名創(chuàng)建后即使移除緩存,也不會(huì)重新創(chuàng)建
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.*; /** * 緩存工具類 緩存名創(chuàng)建后即使移除緩存,也不會(huì)重新創(chuàng)建 * * @version 1.00 (2014.09.15) * @author SHNKCS 張軍 {@link <a target=_blank href="http://www.shanghaijiadun.com">上海加盾信息科技有限公司</a> <a target=_blank href="http://www.eyofj.com">張軍個(gè)人網(wǎng)站</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.eyofj.com"; /** * 獲取緩存管理器 * * @return 緩存管理器 */ public static synchronized CacheManager getCacheManager() { return getCacheManager(DEFAULT_CACHE_FILE); } /** * 根據(jù)ehcache文件路徑獲取緩存管理器對(duì)象 * * @param filePath * ehcache文件路徑,默認(rèn)classes下的/ehcache.xml文件 * @return 緩存管理器對(duì)象 */ 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創(chuàng)建是因?yàn)閑hcache.xml文件和二級(jí)緩存中的文件是同一個(gè)文件 // 日志: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("【成功】根據(jù)流創(chuàng)建緩存"); cacheManager = CacheManager.create(is); } } } catch (Exception e) { logger.error("創(chuàng)建緩存對(duì)象失敗", e); } finally { if (cacheManager == null) { // 創(chuàng)建默認(rèn)的cacheManager cacheManager = CacheManager.getInstance(); logger.warn("創(chuàng)建默認(rèn)的緩存管理器"); } } } return cacheManager; } // Cache構(gòu)造函數(shù) // Cache(java.lang.String name, int maxElementsInMemory, boolean // overflowToDisk, boolean eternal, long timeToLiveSeconds, long // timeToIdleSeconds, boolean diskPersistent, long // diskExpiryThreadIntervalSeconds); /** * 根據(jù)緩存名獲取緩存對(duì)象(可以在系統(tǒng)啟動(dòng)的時(shí)候調(diào)用即可) * * @param cacheName * 緩存名稱 * @param timeToLiveSeconds * 存活時(shí)間在180秒內(nèi) * @param timeToIdleSeconds * 相鄰2次獲取數(shù)據(jù)的時(shí)間間隔如果小于60秒(timeToIdleSeconds) * @return */ public static synchronized Cache getCache(String cacheName, long timeToLiveSeconds, long timeToIdleSeconds) { // 1.必須要有的屬性: // name: cache的名字,用來(lái)識(shí)別不同的cache,必須惟一。 // maxElementsInMemory: 內(nèi)存管理的緩存元素?cái)?shù)量最大限值。(內(nèi)存中存儲(chǔ)對(duì)象的最大值) // maxElementsOnDisk: 硬盤管理的緩存元素?cái)?shù)量最大限值。默認(rèn)值為0,就是沒(méi)有限制。 // eternal: 設(shè)定元素是否持久話。若設(shè)為true,則緩存元素不會(huì)過(guò)期。 // overflowToDisk: 設(shè)定是否在內(nèi)存填滿的時(shí)候把數(shù)據(jù)轉(zhuǎn)到磁盤上。 // 2.下面是一些可選屬性: // timeToIdleSeconds: 設(shè)置Element在失效前的允許閑置時(shí)間。僅當(dāng)element不是永久有效時(shí)使用,可選屬性,默認(rèn)值是0,也就是可閑置時(shí)間無(wú)窮大。 // timeToLiveSeconds: 設(shè)置Element在失效前允許存活時(shí)間。最大時(shí)間介于創(chuàng)建時(shí)間和失效時(shí)間之間。僅當(dāng)element不是永久有效時(shí)使用,默認(rèn)是0.,也就是element存活時(shí)間無(wú)窮大。其他與timeToIdleSeconds類似。 // diskPersistent: 設(shè)定在虛擬機(jī)重啟時(shí)是否進(jìn)行磁盤存儲(chǔ),默認(rèn)為false.(我的直覺(jué),對(duì)于安全小型應(yīng)用,宜設(shè)為true)。 // diskExpiryThreadIntervalSeconds: 訪問(wèn)磁盤線程活動(dòng)時(shí)間。 // diskSpoolBufferSizeMB: 存入磁盤時(shí)的緩沖區(qū)大小,默認(rèn)30MB,每個(gè)緩存都有自己的緩沖區(qū)。 // memoryStoreEvictionPolicy: 元素逐出緩存規(guī)則。共有三種,Recently Used (LRU)最近最少使用,為默認(rèn)。 First In First Out (FIFO),先進(jìn)先出。Less Frequently Used(specified as LFU)最少使用。 // clearOnFlush:內(nèi)存數(shù)量最大時(shí)是否清除。 // 首先來(lái)說(shuō)明一下這兩個(gè)屬性分別有什么作用:(當(dāng)然,只有在eternal為false時(shí),這2個(gè)屬性才有效) // timeToLiveSeconds 當(dāng)對(duì)象自從被存放到緩存中后,如果處于緩存中的時(shí)間超過(guò)了 timeToLiveSeconds屬性值,這個(gè)對(duì)象就會(huì)過(guò)期,EHCache將把它從緩存中清除;即緩存自創(chuàng)建日期起能夠存活的最長(zhǎng)時(shí)間,單位為秒(s) // timeToIdleSeconds 當(dāng)對(duì)象自從最近一次被訪問(wèn)后,如果處于空閑狀態(tài)的時(shí)間超過(guò)了timeToIdleSeconds屬性值,這個(gè)對(duì)象就會(huì)過(guò)期,EHCache將把它從緩存中清空;即緩存被創(chuàng)建后,最后一次訪問(wèn)時(shí)間到緩存失效之時(shí),兩者之間的間隔,單位為秒(s) // 什么意思呢? // 現(xiàn)在假設(shè)有如下配置: // timeToIdleSeconds=60 // timeToLiveSeconds=180 // 則一個(gè)數(shù)據(jù)被添加進(jìn)緩存后,該數(shù)據(jù)能夠在緩存中存活的最長(zhǎng)時(shí)間為180秒(timeToLiveSeconds),而在180秒內(nèi),假設(shè)不止一次去緩存中拿取該數(shù)據(jù),那么相鄰2次獲取數(shù)據(jù)的時(shí)間間隔如果小于60秒(timeToIdleSeconds),則能成功獲取到數(shù)據(jù),但如果最近一次獲取到下一次獲取的時(shí)間間隔超過(guò)60秒,那么,將得到null,因?yàn)榇藭r(shí)該數(shù)據(jù)已經(jīng)被移出緩存了。 // 而且,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("創(chuàng)建緩存:" + cacheName); } else { // logger.debug("緩存存在:" + cacheName); } return cache; } // ------------------------------------------------------------------------------------------------------ /** * 根據(jù)緩存名獲取緩存對(duì)象(永久緩存) 如果未獲取到,超時(shí)緩存也被設(shè)置為永久緩存 * * @param cacheName * 緩存名 * @return 緩存對(duì)象 */ public static synchronized Cache getCache(String cacheName) { // 1.必須要有的屬性: // name: cache的名字,用來(lái)識(shí)別不同的cache,必須惟一。 // maxElementsInMemory: 內(nèi)存管理的緩存元素?cái)?shù)量最大限值。(內(nèi)存中存儲(chǔ)對(duì)象的最大值) // maxElementsOnDisk: 硬盤管理的緩存元素?cái)?shù)量最大限值。默認(rèn)值為0,就是沒(méi)有限制。 // eternal: 設(shè)定元素是否持久話。若設(shè)為true,則緩存元素不會(huì)過(guò)期。 // overflowToDisk: 設(shè)定是否在內(nèi)存填滿的時(shí)候把數(shù)據(jù)轉(zhuǎn)到磁盤上。 // 2.下面是一些可選屬性: // timeToIdleSeconds: 設(shè)置Element在失效前的允許閑置時(shí)間。僅當(dāng)element不是永久有效時(shí)使用,可選屬性,默認(rèn)值是0,也就是可閑置時(shí)間無(wú)窮大。 // timeToLiveSeconds: 設(shè)置Element在失效前允許存活時(shí)間。最大時(shí)間介于創(chuàng)建時(shí)間和失效時(shí)間之間。僅當(dāng)element不是永久有效時(shí)使用,默認(rèn)是0.,也就是element存活時(shí)間無(wú)窮大。其他與timeToIdleSeconds類似。 // diskPersistent: 設(shè)定在虛擬機(jī)重啟時(shí)是否進(jìn)行磁盤存儲(chǔ),默認(rèn)為false.(我的直覺(jué),對(duì)于安全小型應(yīng)用,宜設(shè)為true)。 // diskExpiryThreadIntervalSeconds: 訪問(wèn)磁盤線程活動(dòng)時(shí)間。 // diskSpoolBufferSizeMB: 存入磁盤時(shí)的緩沖區(qū)大小,默認(rèn)30MB,每個(gè)緩存都有自己的緩沖區(qū)。 // memoryStoreEvictionPolicy: 元素逐出緩存規(guī)則。共有三種,Recently Used (LRU)最近最少使用,為默認(rèn)。 First In First Out (FIFO),先進(jìn)先出。Less Frequently Used(specified as LFU)最少使用。 // clearOnFlush:內(nèi)存數(shù)量最大時(shí)是否清除。 // 首先來(lái)說(shuō)明一下這兩個(gè)屬性分別有什么作用:(當(dāng)然,只有在eternal為false時(shí),這2個(gè)屬性才有效) // timeToLiveSeconds 當(dāng)對(duì)象自從被存放到緩存中后,如果處于緩存中的時(shí)間超過(guò)了 timeToLiveSeconds屬性值,這個(gè)對(duì)象就會(huì)過(guò)期,EHCache將把它從緩存中清除;即緩存自創(chuàng)建日期起能夠存活的最長(zhǎng)時(shí)間,單位為秒(s) // timeToIdleSeconds 當(dāng)對(duì)象自從最近一次被訪問(wèn)后,如果處于空閑狀態(tài)的時(shí)間超過(guò)了timeToIdleSeconds屬性值,這個(gè)對(duì)象就會(huì)過(guò)期,EHCache將把它從緩存中清空;即緩存被創(chuàng)建后,最后一次訪問(wèn)時(shí)間到緩存失效之時(shí),兩者之間的間隔,單位為秒(s) // 什么意思呢? // 現(xiàn)在假設(shè)有如下配置: // timeToIdleSeconds=60 // timeToLiveSeconds=180 // 則一個(gè)數(shù)據(jù)被添加進(jìn)緩存后,該數(shù)據(jù)能夠在緩存中存活的最長(zhǎng)時(shí)間為180秒(timeToLiveSeconds),而在180秒內(nèi),假設(shè)不止一次去緩存中拿取該數(shù)據(jù),那么相鄰2次獲取數(shù)據(jù)的時(shí)間間隔如果小于60秒(timeToIdleSeconds),則能成功獲取到數(shù)據(jù),但如果最近一次獲取到下一次獲取的時(shí)間間隔超過(guò)60秒,那么,將得到null,因?yàn)榇藭r(shí)該數(shù)據(jù)已經(jīng)被移出緩存了。 // 而且,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; } /** * 設(shè)置緩存數(shù)據(jù) * * @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)); } /** * 設(shè)置緩存數(shù)據(jù)對(duì)象 * * @param cacheName * 緩存名 * @param value * 緩存值(以{@link #DEFAULT_CACHE_KEY}為鍵,值為值) */ public static synchronized <T> void put(String cacheName, T value) { put(cacheName, null, value); } /** * 設(shè)置緩存數(shù)據(jù) * * @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))); } } /** * 獲取緩存數(shù)據(jù) * * @param cacheName * 緩存名 * @param key * 緩存鍵 * @return 緩存數(shù)據(jù) */ @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(); } /** * 獲取緩存數(shù)據(jù) * * @param cacheName * 緩存名 * @return 緩存數(shù)據(jù) */ public static synchronized <T> T getT(String cacheName) { return get(cacheName, null); } /** * 獲取緩存數(shù)據(jù) * * @param cacheName * 緩存名 * @return 緩存數(shù)據(jù) */ @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 所有緩存數(shù)據(jù) */ public static synchronized <T> List<String> getCacheNames() { return Arrays.asList(getCacheManager().getCacheNames()); } /** * 獲取所有緩存數(shù)據(jù) * * @return 所有緩存數(shù)據(jù) */ @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; } /** * 移除緩存數(shù)據(jù) * * @param cacheName * 緩存名 * @see #remove(String) */ @Deprecated public static synchronized void removeCache(String cacheName) { getCacheManager().removeCache(cacheName); } /** * 移除緩存數(shù)據(jù) * * @param cacheName * 緩存名 * @param key * 緩存鍵 */ public static synchronized void remove(String cacheName, String key) { Cache cache = getCache(cacheName); key = getKey(key); cache.remove(key); } /** * 移除緩存數(shù)據(jù) * * @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(); // 調(diào)用上面方法后刪除緩存報(bào)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. // 再設(shè)置緩存無(wú)效了,使用下面方法 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.eyofj.com">張軍個(gè)人網(wǎng)站</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; } /** * 設(shè)置緩存名字 * * @param name * 緩存名字 */ public void setName(String name) { this.name = name; } /** * 獲取緩存中所有對(duì)象 * * @return 緩存中所有對(duì)象 */ public Map<String, T> getCacheMap() { return cacheMap; } /** * 設(shè)置緩存中所有對(duì)象 * * @param cacheMap * 緩存中所有對(duì)象 */ public void setCacheMap(Map<String, T> cacheMap) { this.cacheMap = cacheMap; } /** * 獲取緩存中對(duì)象數(shù) * * @return 緩存中對(duì)象數(shù) */ public int getCacheSize() { return cacheSize; } /** * 設(shè)置緩存中對(duì)象數(shù) * * @param cacheSize * 緩存對(duì)象數(shù) */ public void setCacheSize(int cacheSize) { this.cacheSize = cacheSize; } /** * 獲取緩存讀取的命中次數(shù) * * @return 緩存讀取的命中次數(shù) */ public long getCacheHits() { return cacheHits; } /** * 設(shè)置緩存讀取的命中次數(shù) * * @param cacheHits * 緩存讀取的命中次數(shù) */ public void setCacheHits(long cacheHits) { this.cacheHits = cacheHits; } /** * 獲取緩存讀取的錯(cuò)失次數(shù) * * @return 緩存讀取的錯(cuò)失次數(shù) */ public long getCacheMisses() { return cacheMisses; } /** * 設(shè)置緩存讀取的錯(cuò)失次數(shù) * * @param cacheMisses * 緩存讀取的錯(cuò)失次數(shù) */ public void setCacheMisses(long cacheMisses) { this.cacheMisses = cacheMisses; } /** * 獲取緩存對(duì)象占用內(nèi)存的大小 * * @return 緩存對(duì)象占用內(nèi)存的大小 */ public long getMemoryStoreSize() { return memoryStoreSize; } /** * 設(shè)置緩存對(duì)象占用內(nèi)存的大小 * * @param memoryStoreSize * 緩存對(duì)象占用內(nèi)存的大小 */ public void setMemoryStoreSize(long memoryStoreSize) { this.memoryStoreSize = memoryStoreSize; } }
本文為張軍原創(chuàng)文章,轉(zhuǎn)載無(wú)需和我聯(lián)系,但請(qǐng)注明來(lái)自張軍的軍軍小站,個(gè)人博客http://www.eyofj.com
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
