一、前言
ehcache是一個比較成熟的Java緩存框架,它提供了用內存,磁盤文件存儲,以及分布式存儲方式等多種靈活的cache管理方案。ehcache最早從hibernate發展而來。由於3.x的版本和2.x的版本API差異比較大。這裏直接學習最新版本的了,但是最後整合spring的時候還是有2.x。
二、安裝
由於我的項目是使用maven管理的,因此只要在pom文件中添加如下代碼即可。
<dependency> <groupId>javax.cache</groupId> <artifactId>cache-api</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <version>3.3.1</version> </dependency>
好像ehcache還要依賴上面的那個Cache,因此最好兩個多加上。
三、使用
1、快速入門__JAVA實現
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("preConfigured", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) .build(); cacheManager.init(); Cache<Long, String> preConfigured = cacheManager.getCache("preConfigured", Long.class, String.class); Cache<Long, String> myCache = cacheManager.createCache("myCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))); myCache.put(1L, "da one!"); String value = http://blog.csdn.net/qq_28702545/article/details/myCache.get(1L); cacheManager.removeCache("preConfigured"); cacheManager.close();
這裏使用的官網的例子。
- CacheManagerBuilder.newCacheManagerBuilder():創建緩存構造器的構建者,類似工廠模式,註意,裏面的實現不是單例。
- .withCache() :相當於創建一個自帶緩存的CacheManager。
build() :這個方法就是創建CacheManager了。
上面的build方法接受一個boolean參數:當為true時,CacheManager在使用時就不用初始化,否則,就需要CacheManager調用init()進行初始化操作。默認為false。
cacheManager.getCache():獲取緩存
- cacheManager.createCache():創建緩存。
- myCache.put(1L, “da one!”):在緩存中添加值
2、快速入門__XML實現
<cache alias="foo"> <!-- 緩存鍵值對的類型 --> <key-type>java.lang.String</key-type> <value-type>java.lang.String</value-type> <!-- 配置緩存 --> <expiry> <ttl unit="seconds">2</ttl> </expiry> <resources> <!-- 在堆中申請2000個entries --> <heap unit="entries">2000</heap> <!-- 最大非堆內存 --> <offheap unit="MB">500</offheap> </resources> </cache> <!-- 定一個模板 --> <cache-template name="myDefaults"> <key-type>java.lang.Long</key-type> <value-type>java.lang.String</value-type> <heap unit="entries">200</heap> </cache-template> <!-- 使用上面的模板 --> <cache alias="bar" uses-template="myDefaults"> <key-type>java.lang.Number</key-type> </cache> <cache alias="simpleCache" uses-template="myDefaults" />
// 測試xml @Test public void test03() { URL url = getClass().getResource("/ehcache.xml"); XmlConfiguration conf = new XmlConfiguration(url); CacheManager cacheManager = CacheManagerBuilder.newCacheManager(conf); cacheManager.init(); Cache<String, String> cache = cacheManager.getCache("foo", String.class, String.class); cache.put("key", "value"); try { Thread.sleep(1000); // 測試過期時間 String value = cache.get("key"); system.out.println("result:" + value); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
上面即演示了xml實現緩存,註釋都比較清楚了。之所以在java中調用Thread.sleep(1000),就是為了測試在xml中設置過期時間是否有效。
三、磁盤緩存
PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder() .with(CacheManagerBuilder.persistence(new File("myData"))) .withCache("threeTieredCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES) .offheap(1, MemoryUnit.MB).disk(20, MemoryUnit.MB, true))) .build(true); Cache<Long, String> threeTieredCache = persistentCacheManager.getCache("threeTieredCache", Long.class, String.class); threeTieredCache.put(1L, "stillAvailableAfterRestart"); persistentCacheManager.close();
上面代碼即會在當前項目的同級目錄下創建一個mydata目錄。
四、Spring和Ehcache整合
Spring本身並沒有提供緩存的功能,但是卻對市面上好多緩存框架提供了支持,即也支持Ehcache。由於Spring4好像對ehcache3.x不是太支持,因此這裏選用2.x。
ehcache.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <ehcache> <!-- 指定一個文件目錄,當EhCache把數據寫到硬盤上時,將把數據寫到這個文件目錄下 --> <diskStore path="java.io.tmpdir" /> <!-- 設定緩存的默認數據過期策略 --> <defaultCache maxElementsInMemory="10000" eternal="false" overflowToDisk="true" timeToIdleSeconds="10" timeToLiveSeconds="20" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" /> <!-- name:緩存名稱 maxElementsInMemory:內存中最大緩存對象數 maxElementsOnDisk:硬盤中最大緩存對象數,若是0表示無窮大 eternal:true表示對象永不過期,此時會忽略timeToIdleSeconds和timeToLiveSeconds屬性,默認為false overflowToDisk:true表示當內存緩存的對象數目達到了 maxElementsInMemory界限後,會把溢出的對象寫到硬盤緩存中。註意:如果緩存的對象要寫入到硬盤中的話,則該對象必須實現了Serializable接口才行。 diskSpoolBufferSizeMB:磁盤緩存區大小,默認為30MB。每個Cache都應該有自己的一個緩存區。 diskPersistent:是否緩存虛擬機重啟期數據,是否持久化磁盤緩存,當這個屬性的值為true時,系統在初始化時會在磁盤中查找文件名 為cache名稱,後綴名為index的文件,這個文件中存放了已經持久化在磁盤中的cache的index,找到後會把cache加載到內存,要想把 cache真正持久化到磁盤,寫程序時註意執行net.sf.ehcache.Cache.put(Element element)後要調用flush()方法。 diskExpiryThreadIntervalSeconds:磁盤失效線程運行時間間隔,默認為120秒 timeToIdleSeconds: 設定允許對象處於空閑狀態的最長時間,以秒為單位。當對象自從最近一次被訪問後,如果處於空閑狀態的時間超過了timeToIdleSeconds屬性 值,這個對象就會過期,EHCache將把它從緩存中清空。只有當eternal屬性為false,該屬性才有效。如果該屬性值為0,則表示對象可以無限 期地處於空閑狀態 timeToLiveSeconds:設定對象允許存在於緩存中的最長時間,以秒為單位。當對象自從被存放到緩存中後,如果處於緩存中的時間超過了 timeToLiveSeconds屬性值,這個對象就會過期,EHCache將把它從緩存中清除。只有當eternal屬性為false,該屬性才有 效。如果該屬性值為0,則表示對象可以無限期地存在於緩存中。timeToLiveSeconds必須大於timeToIdleSeconds屬性,才有 意義 memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理內存。可選策略有:LRU(最近最少使用,默認策略)、FIFO(先進先出)、LFU(最少訪問次數)。 --> <cache name="cacheTest" maxElementsInMemory="1000" eternal="false" overflowToDisk="true" timeToIdleSeconds="10" timeToLiveSeconds="20" /> </ehcache>
application.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd"> <!-- 自動掃描註解的bean --> <context:component-scan base-package="com.lw.spring.ehcache" /> <!-- 註解掃描 --> <cache:annotation-driven cache-manager="ehCacheCacheManager" /> <!-- 實例CacheManager --> <bean id="ehCacheCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="ehcache"></property> </bean> <!-- 加載ehcache配置文件 --> <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:ehcache.xml"></property> </bean> </beans>
創建一個service接口,並添加實現。
package com.lw.spring.ehcache; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service public class EhcacheServiceImpl implements EhcacheService { /** * @Cacheable * 表明所修飾的方法是可以緩存的:當第一次調用這個方法時, * 它的結果會被緩存下來,在緩存的有效時間內。如果每次緩存返回的結果都是一樣的,則不會執行方法體的代碼 * 以後訪問這個方法都直接返回緩存結果,不再執行方法中的代碼段。 * @CachePut:功能比@Cacheable更強,不僅緩存方法結果,還緩存代碼段,每次都會執行方法體的內容 * @CacheEvict:功能和@Cacheable功能相反,@CacheEvict表明所修飾的方法是用來刪除失效或無用的緩存數據。 * @CacheConfig:與前面的緩存註解不同,這是一個類級別的註解。如果類的所有操作都是緩存操作,你可以使用@CacheConfig來指定類,省去一些配置。 * condition:緩存的條件,可以為null,使用spel編寫,只有返回true的情況下才進行緩存 * 這個方法會以key中的值作為緩存中的key,返回結果作為緩存中的值進行緩存 */ @CachePut(value = http://blog.csdn.net/qq_28702545/article/details/"cacheTest", key = "#param",condition="1<2") public String getTime(String param) { System.out.println("getTime方法調用了..."); Long time = System.currentTimeMillis(); return time.toString(); } }
測試:
package com.lw.spring.ehcache; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; @ContextConfiguration(locations={"classpath:application.xml"}) public class EhcacheTest extends AbstractJUnit4SpringContextTests{ @Autowired private EhcacheService ehcacheService; @Test public void getTimestampTest() throws InterruptedException{ System.out.println("第一次調用:" + ehcacheService.getTime("param")); System.out.println("調用:" + ehcacheService.getTime("param")); System.out.println("調用:" + ehcacheService.getTime("param")); System.out.println("調用:" + ehcacheService.getTime("param")); System.out.println("調用:" + ehcacheService.getTime("param")); System.out.println("調用:" + ehcacheService.getTime("param")); System.out.println("調用:" + ehcacheService.getTime("param")); Thread.sleep(11000);// 10s之後緩存消失 System.out.println("再過11秒之後調用:" + ehcacheService.getTime("param")); } }
上面就完成了Spring和ehcache的結合了。其實主要就是ehcache的核心類交給了Spring。上面還有幾個註解,註釋裏也解釋了。
Tags: hibernate version spring java JAVA
文章來源: