Spring中使用ehcache緩存的方法及原理詳解
ehcache簡(jiǎn)介
為什么使用ehcache
(1)速度快。
(2)輕量,很小的jar包,Ehcache 2.2.3才668kb。
(3)和spring集成,通過注解就可以實(shí)現(xiàn)本地緩存,使用簡(jiǎn)單。
(4)具有很強(qiáng)的靈活性,提供了LRU、LFU和FIFO緩存淘汰算法,Ehcache 1.2引入了最近最少使用、最久未使用和先進(jìn)先 出緩存淘汰算法, 構(gòu)成了完整的緩存淘汰算法。
(5)提供內(nèi)存和磁盤存儲(chǔ),Ehcache和大多數(shù)緩存解決方案一樣,提供高性能的內(nèi)存和磁盤存儲(chǔ)。在VM重啟后,持久化到 磁盤的存儲(chǔ)可以復(fù)原數(shù)據(jù)。
使用案例
配置
pom.xml中添加ehcache依賴包
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.9.1</version> </dependency>
ehcache文件配置:
<?xml version="1.0" encoding="UTF-8"?> <ehcache updateCheck="false"> <diskStore path="java.io.tmpdir" /> <!-- name:緩存名稱。 maxElementsInMemory:緩存最大個(gè)數(shù)。 eternal:對(duì)象是否永久有效,一但設(shè)置了, timeout將不起作用。 timeToIdleSeconds:設(shè)置對(duì)象在失效前的允許閑置時(shí)間(單位:秒)。 僅當(dāng)eternal=false對(duì)象 不是永久有效時(shí)使用,可選屬性,默認(rèn)值是0,也就是可閑置時(shí)間無(wú)窮大。 timeToLiveSeconds:設(shè)置對(duì)象在失效前允許存活時(shí)間(單位:秒)。最大時(shí)間介于創(chuàng)建時(shí)間和 失效時(shí)間之間。 僅當(dāng)eternal=false對(duì)象不是永久有效時(shí)使用,默認(rèn)是0.,也就是對(duì)象存活時(shí)間無(wú)窮大。 overflowToDisk:當(dāng)內(nèi)存中對(duì)象數(shù)量達(dá)到maxElementsInMemory時(shí),Ehcache將會(huì)對(duì)象寫到磁盤中。 diskSpoolBufferSizeMB:這個(gè)參數(shù)設(shè)置DiskStore(磁盤緩存)的緩存區(qū)大小。默認(rèn)是30MB。 每個(gè)Cache都應(yīng)該有自己的一個(gè)緩沖區(qū)。 maxElementsOnDisk:硬盤最大緩存?zhèn)€數(shù)。 diskPersistent:是否緩存虛擬機(jī)重啟期數(shù)據(jù) Whether the disk store persists between restarts of the Virtual Machine. The default value is false. diskExpiryThreadIntervalSeconds:磁盤失效線程運(yùn)行時(shí)間間隔,默認(rèn)是120秒。 memoryStoreEvictionPolicy:當(dāng)達(dá)到maxElementsInMemory限制時(shí),Ehcache將會(huì)根據(jù)指定的 策略去清理內(nèi)存。 默認(rèn)策略是LRU(最近最少使用)。你可以設(shè)置為FIFO(先進(jìn)先出)或是LFU(較少使用)。 clearOnFlush:內(nèi)存數(shù)量最大時(shí)是否清除。 --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="60" timeToLiveSeconds="60" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> <cache name="applicationCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="150" timeToLiveSeconds="600" overflowToDisk="false" diskPersistent="false" diskExpiryThreadIntervalSeconds="1" /> <cache name="indexCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="60" timeToLiveSeconds="600" overflowToDisk="false" diskPersistent="false" diskExpiryThreadIntervalSeconds="1" /> </ehcache>
spring文件中的配置
<cache:annotation-driven cache-manager="ehcacheManager"/> <!-- cacheManager工廠類,指定ehcache.xml的位置 --> <beans:bean id="ehcacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <beans:property name="configLocation" value="classpath:config/ehcache.xml" /> </beans:bean> <!-- 聲明cacheManager --> <beans:bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <beans:property name="cacheManager" ref="ehcacheManagerFactory" /> <beans:property name="transactionAware" value="true" /> </beans:bean>
此處的transactionAware表示是否事務(wù)環(huán)繞的,如果值是true,則如果事務(wù)回滾,緩存也回滾,默認(rèn)false。
項(xiàng)目中的使用
例子,通過簡(jiǎn)單的配置即可實(shí)現(xiàn)緩存效果
@Override @Cacheable("applicationCache") public Map<String, Object> getAppDetailById(long appId) { byte[] app = redisTemplate.getRaw(String.format(CacheKeys.APP_DETAIL_BY_ID, appId)); if (null == app) { return Collections.EMPTY_MAP; } try { return CompressUtil.deCompress(app, appId); } catch (IOException t) { throw new FlymeTVServiceException(Errors.ServiceErrors.DE_COMPRESS_ERROR, new Object[] { "appId:" + appId }); } } @Cacheable(value = "categoryCache", key = "#categoryId + #sortType + #start + #max") @Override public MultiPage<Map<String, Object>> getCategoryApps(int categoryId, int sortType, int start, int max) { MultiPage<Map<String, Object>> result = new MultiPage<Map<String, Object>>(); String key = String.format(CacheKeys.CATEGORY_APPS, categoryId, sortType); List<String> appIds = redisTemplate.lrange(key, start, max + BACKUP_APP_SIZE); ..... return result; }
注解接口介紹如下:
public @interface Cacheable { //緩存的名字,可以把數(shù)據(jù)寫到多個(gè)緩存 String[] value(); //緩存key,如果不指定將使用默認(rèn)的KeyGenerator生成 String key() default ""; //滿足緩存條件的數(shù)據(jù)才會(huì)放入緩存,condition在調(diào)用方法之前和之后都會(huì)判斷 String condition() default ""; //用于否決緩存更新的,不像condition,該表達(dá)只在方法執(zhí)行之后判斷,此時(shí)可以拿到返回值result進(jìn)行判斷了 String unless() default ""; }
例子,java代碼如下
@Cacheable(value = "user", key = "#id", condition = "#id lt 10") public User conditionFindById(final Long id)
根據(jù)運(yùn)行流程,如下@Cacheable將在執(zhí)行方法之前( #result還拿不到返回值)判斷condition,如果返回true,則查緩存。
Key生成器
如果在Cache注解上沒有指定key的話@Cacheable(“applicationCache”),會(huì)使用KeyGenerator進(jìn)行生成一個(gè)key: java代碼
public interface KeyGenerator { Object generate(Object target, Method method, Object... params); }
默認(rèn)提供了DefaultKeyGenerator生成器
public Object generate(Object target, Method method, Object[] params) { if (params.length == 1) { return params[0] == null ? Integer.valueOf(53) : params[0]; } if (params.length == 0) { return Integer.valueOf(0); } int hashCode = 17; for (Object object : params) { hashCode = 31 * hashCode + (object == null ? 53 : object.hashCode()); } return Integer.valueOf(hashCode); }
新增和刪除注解
@CachePut 應(yīng)用到寫數(shù)據(jù)的方法上,如新增/修改方法,調(diào)用方法時(shí)會(huì)自動(dòng)把相應(yīng)的數(shù)據(jù)放入緩存: java代碼
@CachePut(value = "user", key = "#user.id") public User save(User user) { users.add(user); return user; }
即調(diào)用該方法時(shí),會(huì)把user.id作為key,返回值作為value放入緩存; 接口介紹,java代碼:
public @interface CachePut { //緩存的名字,可以把數(shù)據(jù)寫到多個(gè)緩存 String[] value(); //緩存key,如果不指定將使用默認(rèn)的KeyGenerator生成 String key() default ""; //滿足緩存條件的數(shù)據(jù)才會(huì)放入緩存,condition在調(diào)用方法之前和之后都會(huì)判斷 String condition() default ""; //用于否決緩存更新的,不像condition,該表達(dá)只在方法執(zhí)行之后判斷,此時(shí)可以拿到返回值result進(jìn)行判斷了 String unless() default ""; }
例子,java代碼
@CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'") public User conditionSave2(final User user)
根據(jù)運(yùn)行流程,如下@CachePut將在執(zhí)行完方法后(#result就能拿到返回值了)判斷unless,如果返回false,則放入緩存;(即跟condition相反)
到此這篇關(guān)于Spring中使用ehcache緩存的方法及原理詳解的文章就介紹到這了,更多相關(guān)Spring使用ehcache緩存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 9中如何對(duì)IntegerCache進(jìn)行修改詳解
這篇文章主要給大家介紹了關(guān)于Java 9中如何對(duì)IntegerCache進(jìn)行修改的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或使用java9具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起看看吧。2017-12-12java Disruptor構(gòu)建高性能內(nèi)存隊(duì)列使用詳解
這篇文章主要為大家介紹了java Disruptor構(gòu)建高性能內(nèi)存隊(duì)列使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12詳解Spring注入集合(數(shù)組、List、Map、Set)類型屬性
這篇文章主要介紹了詳解Spring注入集合(數(shù)組、List、Map、Set)類型屬性,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01java正則表達(dá)式提取數(shù)字的方法實(shí)例
這篇文章主要介紹了java正則表達(dá)式提取數(shù)字的方法,還有去除字符串?dāng)?shù)字的方法,大家參考使用吧2013-12-12SpringMVC中使用@PathVariable綁定路由中的數(shù)組的方法
這篇文章主要介紹了SpringMVC中使用@PathVariable綁定路由中的數(shù)組的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07SpringBoot整合Echarts實(shí)現(xiàn)數(shù)據(jù)大屏
這篇文章給大家介紹了三步實(shí)現(xiàn)SpringBoot全局日志記錄,整合Echarts實(shí)現(xiàn)數(shù)據(jù)大屏,文中通過代碼示例給大家介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2024-03-03詳解SpringCloud微服務(wù)架構(gòu)之Hystrix斷路器
本篇文章主要介紹了詳解SpringCloud微服務(wù)架構(gòu)之Hystrix斷路器,Hystrix是一個(gè)庫(kù),通過添加延遲容差和容錯(cuò)邏輯來幫助您控制這些分布式服務(wù)之間的交互,有興趣的可以了解一下2018-01-01解決BeanUtils.copyProperties無(wú)法成功封裝的問題
這篇文章主要介紹了解決BeanUtils.copyProperties無(wú)法成功封裝的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06