Spring整合ehCache全過程
1. 基本介紹
EhCache 是一個純Java的進程內(nèi)緩存框架,具有快速、精干等特點,是Hibernate中默認(rèn)Cache方式。
Ehcache是一種廣泛使用的開源Java分布式緩存。
它具有內(nèi)存和磁盤存儲,緩存加載器,緩存擴展,緩存異常處理程序等特點。
Spring 提供了對緩存功能的抽象:即允許綁定不同的緩存解決方案(如Ehcache),但本身不直接提供緩存功能的實現(xiàn)。它支持注解方式使用緩存,非常方便。
2. 主要的特性
- 1、快速
- 2、簡單
- 3、多種緩存策略
- 4、緩存數(shù)據(jù)有兩級:內(nèi)存和磁盤,因此無需擔(dān)心容量問題
- 5、緩存數(shù)據(jù)會在虛擬機重啟的過程中寫入磁盤
- 6、可以通過RMI、可插入API等方式進行分布式緩存
3. 集成
可以單獨使用,一般在第三方庫中被用到的比較多(如mybatis、shiro等)。
ehcache 對分布式支持不夠好,多個節(jié)點不能同步,通常和redis一塊使用。
一般使用ehcache做本地緩存,解決Redis單點壓力過大等問題。
4. ehcache 和 redis 比較
- ehcache直接在jvm虛擬機中緩存,速度快,效率高;但是緩存共享麻煩,集群分布式應(yīng)用不方便。
- redis是通過socket訪問到緩存服務(wù),效率比ecache低,比數(shù)據(jù)庫要快很多。
- ehcache也有緩存共享方案,不過緩存共享復(fù)雜,維護不方便;
5. ehcache 與 Spring整合
①. pom.xml 引入spring和ehcache
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> ? <modelVersion>4.0.0</modelVersion> ? <groupId>com.mengdee</groupId> ? <artifactId>ehcache</artifactId> ? <version>0.0.1-SNAPSHOT</version> ?? ? <properties> ? ?? ?<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> ? ?? ?<junit.version>4.10</junit.version> ?? ?<spring.version>4.2.3.RELEASE</spring.version> ? </properties> ?? ? <dependencies> ? ? <dependency> ? ? ? <groupId>junit</groupId> ? ? ? <artifactId>junit</artifactId> ? ? ? <version>${junit.version}</version> ? ? ? <scope>test</scope> ? ? </dependency> ? ?? ? ? <dependency> ? ? ? ? ?<groupId>org.springframework</groupId> ? ? ? ? ?<artifactId>spring-test</artifactId> ? ? ? ? ?<version>${spring.version}</version> ? ? ? ? ?<scope>test</scope> ? ? ?</dependency> ? ?? ? ?? ? ? <!-- springframework --> ? ? <dependency> ?? ??? ?<groupId>org.springframework</groupId> ?? ??? ?<artifactId>spring-webmvc</artifactId> ?? ??? ?<version>${spring.version}</version> ?? ?</dependency> ?? ?<dependency> ?? ??? ?<groupId>org.springframework</groupId> ?? ??? ?<artifactId>spring-core</artifactId> ?? ??? ?<version>${spring.version}</version> ?? ?</dependency> ?? ?<dependency> ?? ??? ?<groupId>org.springframework</groupId> ?? ??? ?<artifactId>spring-context</artifactId> ?? ??? ?<version>${spring.version}</version> ?? ?</dependency> ?? ?<dependency> ?? ??? ?<groupId>org.springframework</groupId> ?? ??? ?<artifactId>spring-context-support</artifactId> ?? ??? ?<version>${spring.version}</version> ?? ?</dependency> ? ?? ?? ?<dependency> ?? ? ? ?<groupId>net.sf.ehcache</groupId> ?? ? ? ?<artifactId>ehcache</artifactId> ?? ? ? ?<version>2.10.3</version> ?? ?</dependency> ? ? ?? ? </dependencies> ?? ? <repositories> ? ? <repository> ? ? ? ? <id>aliyun</id> ? ? ? ? <name>aliyun</name> ? ? ? ? <url>http://maven.aliyun.com/nexus/content/groups/public</url> ? ? </repository> ? </repositories> </project>
②applicationContext.xml中引入ehcache配置
<!-- ehcache配置 --> <import resource="classpath*:conf/spring/ehcache-mamage.xml" />
③ehcache-mamage.xml 配置文件
<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" ? ? ? ?xsi:schemaLocation="http://www.springframework.org/schema/beans ? ? ? ? http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ? ? ? ? http://www.springframework.org/schema/cache ? ? ? ? http://www.springframework.org/schema/cache/spring-cache-3.1.xsd"> ? ? ? <!-- 啟用緩存注解開關(guān) --> ? ? <cache:annotation-driven /> ? ? ? <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> ? ? ? ? <property name="cacheManager" ref="ehcacheManager"/> ? ? </bean> ? ? ? <!-- ehCache 配置管理器 --> ? ? <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> ? ? ? ? <property name="configLocation" value="classpath:conf/ehcache.xml" /> ? ? ? ? <!--true:單例,一個cacheManager對象共享;false:多個對象獨立 --> ? ? ? ? <property name="shared" value="true" /> ? ? </bean> </beans>
④ehcache.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ? ? ? ? ?xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> ? ? <!-- ? ? ?? ?name:緩存區(qū)名稱,用以區(qū)別緩存區(qū),必須唯一 ? ? ?? ?maxEntriesLocalHeap:設(shè)置緩存在本地內(nèi)存中最大緩存項數(shù)量,0表示無限,等效于舊版本中的maxElementsInMemory屬性 ? ? ?? ?eternal:設(shè)置緩存項是否為永久的。如果設(shè)置為true,緩存項的過期設(shè)置將被忽略,緩存項永不過期 ? ? ?? ?timeToIdleSeconds:設(shè)置一個緩存項在過期前的閑置時間。即一個緩存項在其過期前,兩次訪問間隔的最大時間。僅在緩存項為非永久時有效。0表示不限閑置時間,默認(rèn)為0 ? ? ?? ?timeToLiveSeconds:設(shè)置一個緩存項在過期前的生存時間。即從緩存項創(chuàng)建到過期的最大時間。僅在緩存項為非永久時有效。0表示不限生存時間,默認(rèn)為0 ? ? ?? ?overflowToDisk:當(dāng)內(nèi)存中對象數(shù)量達(dá)到maxEntriesLocalHeap時,Ehcache將會對象寫到磁盤中 ? ? ?? ?copyOnRead:當(dāng)緩存項被讀出時,是否返回一份它的拷貝(返回對象是緩存中對象的拷貝)。默認(rèn)false ? ? ?? ?copyOnWrite:當(dāng)緩存項被寫入時,是否寫入一份它的拷貝(寫入緩存的是寫入對象的拷貝)。默認(rèn)false ? ? ?? ?memoryStoreEvictionPolicy:當(dāng)緩存項達(dá)到maxEntriesLocalHeap限制時,剔除緩存項的策略。默認(rèn)為LRU(Least Recently Used)。 ? ? ?? ?其他的策略有:FIFO(First In First Out)和LFU(Less Frequently Used) ?? ?--> ? ? ? ? <cache name="cmApplyInfoDataCache" maxEntriesLocalHeap="3600" timeToIdleSeconds="20" timeToLiveSeconds="86400" ? ? ? ? ? ?eternal="false" overflowToDisk="false" copyOnRead="true" copyOnWrite="true" memoryStoreEvictionPolicy="LRU"> ? ? ? ? <searchable/> ? ? ? ? <persistence strategy="none"/> ? ? </cache> ? </ehcache>
⑤測試EhCache緩存 java代碼實現(xiàn)
?@RequestMapping("/testSpringEhCache.action") ? ? @ResponseBody ? ? public Map<String, Object> testSpringEhCache(HttpServletRequest request) { ? ? ? ? Map<String, Object> params = baseController.getParams(request); ? ? ? ? String supplierCode = MapUtils.getString(params, "supplierCode", ""); ? ? ? ? String productCode = MapUtils.getString(params, "productCode", ""); ? ? ? ? ? CmpProductSingleCommonEntity entity = orderDataTempService.queryProductSingleCommon(supplierCode, productCode); ? ? ? ? return CmUtils.convertDTOToMap(entity); ? ? } ?@Override ? ? @Cacheable(value = "cmApplyInfoDataCache", key = "'cmp_cmApplyInfo_cache_key_'+#supplierCode+'_'+#productCode") ? ? public CmpProductSingleCommonEntity queryProductSingleCommon(String supplierCode, String productCode) { ? ? ? ? return cmpProductSingleCommonDAO.queryProductSingleCommon(supplierCode, productCode); ? ? }
5. Spring緩存標(biāo)簽
實現(xiàn)原理:
Spring對緩存的支持類似于對事務(wù)的支持。
首先使用注解標(biāo)記方法,相當(dāng)于定義了切點,然后使用Aop技術(shù)在這個方法的調(diào)用前、調(diào)用后獲取方法的入?yún)⒑头祷刂?,進而實現(xiàn)了緩存的邏輯。
①@Cacheable標(biāo)簽
表明所修飾的方法是可以緩存的:當(dāng)?shù)谝淮握{(diào)用這個方法時,它的結(jié)果會被緩存下來,在緩存的有效時間內(nèi),以后訪問這個方法都直接返回緩存結(jié)果,不再執(zhí)行方法中的代碼段。
這個注解可以用condition屬性來設(shè)置條件,如果不滿足條件,就不使用緩存能力,直接執(zhí)行方法。
可以使用key屬性來指定key的生成規(guī)則。
@Cacheable 支持如下幾個參數(shù):
value
:緩存位置名稱,不能為空,如果使用EHCache,就是ehcache.xml中聲明的cache的name, 指明將值緩存到哪個Cache中key
:緩存的key,默認(rèn)為空,既表示使用方法的參數(shù)類型及參數(shù)值作為key,支持SpEL,如果要引用參數(shù)值使用井號加參數(shù)名,如:#userId,
一般來說,我們的更新操作只需要刷新緩存中某一個值,所以定義緩存的key值的方式就很重要,最好是能夠唯一,因為這樣可以準(zhǔn)確的清除掉特定的緩存,而不會影響到其它緩存值 ,
本例子中使用實體加冒號再加ID組合成鍵的名稱,如"user:1"、"order:223123"等
condition
:觸發(fā)條件,只有滿足條件的情況才會加入緩存,默認(rèn)為空,既表示全部都加入緩存,支持SpEL
舉例如下:
入?yún)閱蝹€字符串的場景:
// 將緩存保存到名稱為UserCache中,鍵為"user:"字符串加上userId值,如 'user:1'? ? ? ? @Cacheable(value = "UserCache", key = "'user:' + #userId") ? ? public User findById(String userId) { ? ? ? ? return ?new User("1", "mengdee"); ? ? }?
入?yún)槎鄠€字符串的場景:
@Cacheable(value = "cmApplyInfoDataCache", key = "'cmp_cmApplyInfo_cache_key_'+#supplierCode+'_'+#productCode") ? ? public CmpProductSingleCommonEntity queryProductSingleCommon(String supplierCode, String productCode) { ? ? ? ? return cmpProductSingleCommonDAO.queryProductSingleCommon(supplierCode, productCode); ? ? }
入?yún)镸ap場景:
? ?@Cacheable(value="supplierInfoDataCache", key = "'params:'+#supplierCode") ? ? public List<Map<String, Object>> queryDataList(Map<String, Object> params) { ? ? ? ? return cmpProductSingleCommonDAO.querySupplierIsPublishCmBySupplierCode(params); ? ? }
②@CacheEvict標(biāo)簽
與@Cacheable功能相反,@CacheEvict表明所修飾的方法是用來刪除失效或無用的緩存數(shù)據(jù)。
@CacheEvict 支持如下幾個參數(shù):
value
:緩存位置名稱,不能為空,同上key
:緩存的key,默認(rèn)為空,同上condition
:觸發(fā)條件,只有滿足條件的情況才會清除緩存,默認(rèn)為空,支持SpELallEntries
:true表示清除value中的全部緩存,默認(rèn)為false
//清除掉UserCache中某個指定key的緩存 ? ? @CacheEvict(value="UserCache",key="'user:' + #userId") ? ? public void removeUser(User user) { ? ? ? ? System.out.println("UserCache"+user.getUserId()); ? ? } ? ? ? //清除掉UserCache中全部的緩存 ? ? @CacheEvict(value="UserCache", allEntries=true) ? ? public final void setReservedUsers(String[] reservedUsers) { ? ? ? ?System.out.println("UserCache deleteall"); ? ? }
6. ehcache.xml 配置說明
name
緩存區(qū)名稱,用以區(qū)別緩存區(qū),必須唯一
maxEntriesLocalHeap
設(shè)置緩存在本地內(nèi)存中最大緩存項數(shù)量,0表示無限,等效于舊版本中的maxElementsInMemory屬性
eternal
設(shè)置緩存項是否為永久的。如果設(shè)置為true,緩存項的過期設(shè)置將被忽略,緩存項永不過期
timeToIdleSeconds
設(shè)置一個緩存項在過期前的閑置時間。即一個緩存項在其過期前,兩次訪問間隔的最大時間。僅在緩存項為非永久時有效。0表示不限閑置時間,默認(rèn)為0
timeToLiveSeconds
設(shè)置一個緩存項在過期前的生存時間。即從緩存項創(chuàng)建到過期的最大時間。僅在緩存項為非永久時有效。0表示不限生存時間,默認(rèn)為0
overflowToDisk
當(dāng)內(nèi)存中對象數(shù)量達(dá)到maxEntriesLocalHeap時,Ehcache將會對象寫到磁盤中
copyOnRead
當(dāng)緩存項被讀出時,是否返回一份它的拷貝(返回對象是緩存中對象的拷貝)。默認(rèn)false
copyOnWrite
當(dāng)緩存項被寫入時,是否寫入一份它的拷貝(寫入緩存的是寫入對象的拷貝)。默認(rèn)false
memoryStoreEvictionPolicy
當(dāng)緩存項達(dá)到maxEntriesLocalHeap限制時,剔除緩存項的策略。默認(rèn)為LRU(Least Recently Used)。
其他的策略有:FIFO(First In First Out)和LFU(Less Frequently Used)
實例:
? ?<cache name="cmApplyInfoDataCache" maxEntriesLocalHeap="3600" timeToIdleSeconds="20" timeToLiveSeconds="86400" ? ? ? ? ? ?eternal="false" overflowToDisk="false" copyOnRead="true" copyOnWrite="true" memoryStoreEvictionPolicy="LRU"> ? ? ? ? <searchable/> ? ? ? ? <persistence strategy="none"/> ? ? </cache>
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java為什么使用BlockingQueue解決競態(tài)條件問題面試精講
這篇文章主要為大家介紹了java為什么使用BlockingQueue解決競態(tài)條件問題面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-10-10Jdbctemplate多數(shù)據(jù)源配置方法詳解
這篇文章主要介紹了Jdbctemplate多數(shù)據(jù)源配置方法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06Struts1教程之ActionMapping_動力節(jié)點Java學(xué)院整理
這篇文章主要介紹了Struts1教程之ActionMapping,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09