日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

基于Spring的Web缓存

發(fā)布時(shí)間:2025/4/16 javascript 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于Spring的Web缓存 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

緩存的基本思想其實(shí)是以空間換時(shí)間。我們知道,IO的讀寫速度相對內(nèi)存來說是非常比較慢的,通常一個(gè)web應(yīng)用的瓶頸就出現(xiàn)在磁盤IO的讀寫上。那么,如果我們在內(nèi)存中建立一個(gè)存儲區(qū),將數(shù)據(jù)緩存起來,當(dāng)瀏覽器端由請求到達(dá)的時(shí)候,直接從內(nèi)存中獲取相應(yīng)的數(shù)據(jù),這樣一來可以降低服務(wù)器的壓力,二來,可以提高請求的響應(yīng)速度,提升用戶體驗(yàn)。

緩存的分類

  • 數(shù)據(jù)庫數(shù)據(jù)緩存

一般來說,web應(yīng)用業(yè)務(wù)邏輯業(yè)務(wù)邏輯比較復(fù)雜,數(shù)據(jù)庫繁多,要獲取某個(gè)完整的數(shù)據(jù),往往要多次讀取數(shù)據(jù)庫,或者使用極其復(fù)雜效率較低的SQL查詢語句。為了提高查詢的性能,將查詢后的數(shù)據(jù)放到內(nèi)存中進(jìn)行緩存,下次查詢時(shí),直接從內(nèi)存緩存直接返回,提高響應(yīng)效率。

  • 應(yīng)用層緩存

應(yīng)用層緩存主要針對某個(gè)業(yè)務(wù)方法進(jìn)行緩存,有些業(yè)務(wù)對象邏輯比較復(fù)雜,,可能涉及到多次數(shù)據(jù)庫讀寫或者其他消耗較高的操作,應(yīng)用層緩存可以將復(fù)雜的業(yè)務(wù)邏輯解放出來,降低服務(wù)器壓力。

  • 頁面緩存

除了IO外,web應(yīng)用的另一大瓶頸就是頁面模板的渲染。每次請求都需要從業(yè)務(wù)邏輯層獲取相應(yīng)的model,并將其渲染成對應(yīng)的HTML。一般來說,web應(yīng)用讀取數(shù)據(jù)的需求比更新數(shù)據(jù)的需求大很多,大多數(shù)情況下,某個(gè)請求返回的HTML是一樣的,因此直接將HTML緩存起來也是緩存的一個(gè)主流做法。

  • 代理服務(wù)器緩存

代理服務(wù)器是瀏覽器和源服務(wù)器之間的中間服務(wù)器,瀏覽器先向這個(gè)中間服務(wù)器發(fā)起Web請求,經(jīng)過處理后(比如權(quán)限驗(yàn)證,緩存匹配等),再將請求轉(zhuǎn)發(fā)到源服務(wù)器。代理服務(wù)器緩存的運(yùn)作原理跟瀏覽器的運(yùn)作原理差不多,只是規(guī)模更大。可以把它理解為一個(gè)共享緩存,不只為一個(gè)用戶服務(wù),一般為大量用戶提供服務(wù),因此在減少相應(yīng)時(shí)間和帶寬使用方面很有效,同一個(gè)副本會(huì)被重用多次。

  • CDN緩存

CDN( Content delivery networks )緩存,也叫網(wǎng)關(guān)緩存、反向代理緩存。瀏覽器先向CDN網(wǎng)關(guān)發(fā)起Web請求,網(wǎng)關(guān)服務(wù)器后面對應(yīng)著一臺或多臺負(fù)載均衡源服務(wù)器,會(huì)根據(jù)它們的負(fù)載請求,動(dòng)態(tài)將請求轉(zhuǎn)發(fā)到合適的源服務(wù)器上。雖然這種架構(gòu)負(fù)載均衡源服務(wù)器之間的緩存沒法共享,但卻擁有更好的處擴(kuò)展性。

基于spring的緩存

spring作為一個(gè)成熟的java web 框架,自身有一套完善的緩存機(jī)制,同時(shí),spring還未其他緩存的實(shí)現(xiàn)提供了擴(kuò)展。接下來,讓我們在一個(gè)簡單的學(xué)生管理系統(tǒng)中嘗試spring的數(shù)據(jù)庫緩存、應(yīng)用層緩存、頁面緩存的實(shí)現(xiàn)。

基于spring的Web緩存

源程序簡介

本節(jié)課我們來看看一個(gè)簡單的學(xué)生管理系統(tǒng),改系統(tǒng)使用了Spring+JPA+EhCache的架構(gòu)對數(shù)據(jù)庫進(jìn)行了緩存。大家可以直接下載源碼進(jìn)行學(xué)習(xí)。

數(shù)據(jù)庫準(zhǔn)備

測試程序使用了mysql作為數(shù)據(jù)庫,安裝好mysql后,建立一個(gè)空白的 數(shù)據(jù)庫,例如cache。

建好數(shù)據(jù)庫后,修改src/main/resources/application.properties的數(shù)據(jù)庫配置

spring.datasource.url=jdbc:mysql://localhost/cache?useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=

利用maven啟動(dòng)程序

該系統(tǒng)利用maven作為構(gòu)建工具,如果對maven沒有了解的同學(xué)可以自行了解一下,我們會(huì)利用maven進(jìn)行整個(gè)項(xiàng)目的構(gòu)建以及運(yùn)行。因此需要大家下載安裝maven。

安裝完成后,打開命令行,進(jìn)入程序所在目錄,輸入以下命令:

mvn spring-boot:run

打開瀏覽器,訪問以下http://localhost:8111/blogs即可看到最初的博客列表頁面

直接運(yùn)行?com.tmy.App.java

如果你成功的將項(xiàng)目作為一個(gè)maven項(xiàng)目導(dǎo)入進(jìn)eclipse,直接運(yùn)行com.tmy.App.java也可以將項(xiàng)目啟動(dòng)起來。

注意,如果希望將項(xiàng)目導(dǎo)入進(jìn)eclipse,需要為eclipse添加maven插件,否則會(huì)出現(xiàn)依賴的類找不到的問題。

頁面列表

以下是程序所提供的所有頁面以及相關(guān)說明:

http://localhost:8111/blogs //沒有加緩存的博客列表頁面 http://localhost:8111/blogs/dao //添加了數(shù)據(jù)層緩存 http://localhost:8111/blogs/service?test=test //添加了服務(wù)層緩存 http://localhost:8111/blogs/service/update?test=test //更新服務(wù)層緩存 http://localhost:8111/blogs/service/evict?test=test //刪除服務(wù)層緩存 http://localhost:8111/blogs/service/test?test=test //刪除服務(wù)層緩存的同時(shí)更新緩存 http://localhost:8111/blogs/page //添加了頁面緩存 http://localhost:8111/blogs/page/update //清空頁面緩存 http://localhost:8111/blogs/page/delete //清空頁面緩存

涉及到的技術(shù)

  • maven

maven是目前主流java的構(gòu)建工具之一,如果對maven沒有了解的同學(xué)可以自行了解一下,接下來我們會(huì)利用maven進(jìn)行整個(gè)項(xiàng)目的構(gòu)建以及運(yùn)行。

  • spring boot

spring boot是spring的一個(gè)子項(xiàng)目,其目的是spring應(yīng)用的初始搭建以及開發(fā)過程,如果你想自己搭建一個(gè)基于spring的應(yīng)用,強(qiáng)烈建議學(xué)習(xí)一下在《java web 全棧開發(fā)》這門課程,教你如何從對spring零基礎(chǔ)到搭建好一個(gè)完整的spring web應(yīng)用。這里,我們只需知道m(xù)vn spring-boot:run命令可以將系統(tǒng)run起來即可。

  • Spring

Spring作為目前主流的java web框架,大家應(yīng)該都很了解,這里不做過多介紹。

  • JPA

JPA全稱Java Persistence API,JPA通過JDK 5.0注解或XML描述對象-關(guān)系表的映射關(guān)系,并將運(yùn)行期的實(shí)體對象持久化到數(shù)據(jù)庫中。本門課程主要講基于spring的數(shù)據(jù)庫緩存,對于JPA的內(nèi)容不做過多的涉及。

  • EhCache

EhCache 是一個(gè)純Java的進(jìn)程內(nèi)緩存框架,具有快速、精干等特點(diǎn)。我們的學(xué)生管理系統(tǒng)將利用EhCache對數(shù)據(jù)庫層進(jìn)行緩存。

配置EhCache

對EhCache的依賴

上一節(jié)我們講到很多技術(shù),這里我們主要的依賴是指對EhCache的依賴,需要在Spring項(xiàng)目中引入EhCache,在pom.xml中加入以下代碼即可:

<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> </dependency>

配置CacheManager

添加ehcache配置文件

在src/main/resources下添加文件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" name="CM1" updateCheck="false" maxBytesLocalHeap="16M"> <diskStore path="/data/app/cache/ehcache"/> <defaultCache eternal="false" overflowToDisk="false" maxElementsInMemory="10000" timeToIdleSeconds="3600" timeToLiveSeconds="36000" /> </ehcache>

encache可以對以下參數(shù)進(jìn)行配置:

  • name

緩存名稱

  • maxElementsInMemory

內(nèi)存中最大緩存對象數(shù)

  • maxElementsOnDisk

硬盤中最大緩存對象數(shù),若是0表示無窮大

  • eternal

true表示對象永不過期,此時(shí)會(huì)忽略timeToIdleSeconds和timeToLiveSeconds屬性,默認(rèn)為false

  • overflowToDisk

true表示當(dāng)內(nèi)存緩存的對象數(shù)目達(dá)到了maxElementsInMemory界限后,會(huì)把溢出的對象寫到硬盤緩存中。注意:如果緩存的對象要寫入到硬盤中的話,則該對象必須實(shí)現(xiàn)了Serializable接口才行。

  • diskSpoolBufferSizeMB

磁盤緩存區(qū)大小,默認(rèn)為30MB。每個(gè)Cache都應(yīng)該有自己的一個(gè)緩存區(qū)。

  • diskPersistent

是否緩存虛擬機(jī)重啟期數(shù)據(jù)

  • diskExpiryThreadIntervalSeconds

磁盤失效線程運(yùn)行時(shí)間間隔,默認(rèn)為120秒

  • timeToIdleSeconds

設(shè)定允許對象處于空閑狀態(tài)的最長時(shí)間,以秒為單位。當(dāng)對象自從最近一次被訪問后,如果處于空閑狀態(tài)的時(shí)間超過了timeToIdleSeconds屬性值,這個(gè)對象就會(huì)過期,EHCache將把它從緩存中清空。只有當(dāng)eternal屬性為false,該屬性才有效。如果該屬性值為0,則表示對象可以無限期地處于空閑狀態(tài)

  • timeToLiveSeconds

設(shè)定對象允許存在于緩存中的最長時(shí)間,以秒為單位。當(dāng)對象自從被存放到緩存中后,如果處于緩存中的時(shí)間超過了 timeToLiveSeconds屬性值,這個(gè)對象就會(huì)過期,EHCache將把它從緩存中清除。只有當(dāng)eternal屬性為false,該屬性才有效。如果該屬性值為0,則表示對象可以無限期地存在于緩存中。timeToLiveSeconds必須大于timeToIdleSeconds屬性,才有意義

  • memoryStoreEvictionPolicy

當(dāng)達(dá)到maxElementsInMemory限制時(shí),Ehcache將會(huì)根據(jù)指定的策略去清理內(nèi)存。可選策略有:LRU(最近最少使用,默認(rèn)策略)、FIFO(先進(jìn)先出)、LFU(最少訪問次數(shù))。

添加cacheManager

首先,我們要通過@EnableCaching標(biāo)注將Spring通過標(biāo)注進(jìn)行緩存管理的功能打開,以方便我們之后通過標(biāo)注添加數(shù)據(jù)庫緩存。

然后,為CacheConfiguration添加@Configuration標(biāo)注,打開CacheConfiguration內(nèi)@Bean的功能。

生成一個(gè)CacheManager的實(shí)例。

最后,在web app銷毀的時(shí)候銷毀cacheManager。

@Configuration @EnableCaching public class CacheConfiguration { private net.sf.ehcache.CacheManager cacheManager; @PreDestroy public void destroy() { cacheManager.shutdown(); } @Bean public CacheManager cacheManager() { cacheManager = net.sf.ehcache.CacheManager.create(); EhCacheCacheManager ehCacheManager = new EhCacheCacheManager(); ehCacheManager.setCacheManager(cacheManager); return ehCacheManager; } }

數(shù)據(jù)層緩存實(shí)現(xiàn)

添加ehcache設(shè)置

首先,我們需要在EhCache中設(shè)置一塊區(qū)域來存放緩存,在src/main/resources/ehcache.xml中添加如下配置:

<cache name="com.tmy.model.User"></cache> <cache name="com.tmy.model.Blog"></cache>

Hibernate的一級緩存和二級緩存

Hibernate提供了兩級緩存,第一級是Session的緩存。由于Session對象的生命周期通常對應(yīng)一個(gè)數(shù)據(jù)庫事務(wù)或者一個(gè)應(yīng)用事務(wù),因此它的緩存是事務(wù)范圍的緩存。第一級緩存是必需的,hibernate會(huì)默認(rèn)提供好。

第二級緩存是一個(gè)可插拔的的緩存插件,它是由SessionFactory負(fù)責(zé)管理。由于SessionFactory對象的生命周期和應(yīng)用程序的整個(gè)過程對應(yīng),因此第二級緩存是進(jìn)程范圍或者集群范圍的緩存。這個(gè)緩存中存放的對象的松散數(shù)據(jù)第二級緩存是可選的,可以在每個(gè)類或每個(gè)集合的粒度上配置第二級緩存。

打開二級緩存

我們可以通過為entry對象添加標(biāo)注的方式打開二級緩存:

@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

二級緩存一共有以下5種策略:

  • CacheConcurrencyStrategy.NONE

不使用緩存,默認(rèn)的緩存策略

  • CacheConcurrencyStrategy.READ_ONLY

只讀模式,在此模式下,如果對數(shù)據(jù)進(jìn)行更新操作,會(huì)有異常

  • CacheConcurrencyStrategy.READ_WRITE

讀寫模式在更新緩存的時(shí)候會(huì)把緩存里面的數(shù)據(jù)換成一個(gè)鎖,其它事務(wù)如果去取相應(yīng)的緩存數(shù)據(jù),發(fā)現(xiàn)被鎖了,直接就去數(shù)據(jù)庫查詢

  • CacheConcurrencyStrategy.NONSTRICT_READ_WRITE

不嚴(yán)格的讀寫模式則不會(huì)的緩存數(shù)據(jù)加鎖

  • CacheConcurrencyStrategy.TRANSACTIONAL

事務(wù)模式指緩存支持事務(wù),當(dāng)事務(wù)回滾時(shí),緩存也能回滾

指定cache region factory

然后,在src/main/resources/application.properties中為cache指定一個(gè)factory:

spring.jpa.properties. =org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory

性能對比

第一次訪問

第一次訪問http://localhost:8111/blogs時(shí),waiting也就是服務(wù)器響應(yīng)的時(shí)間為2.82秒,耗時(shí)較多。

注意:這里消耗2.82秒的原因是:在Blog對象中添加了對成員creator添加了@ManyToOne的標(biāo)注,因此,當(dāng)通過JPA獲取blog對象后,JPA還會(huì)請求一次SQL查詢,去user表中獲取user信息,將user填充進(jìn)來,而為了效果更加明顯,系統(tǒng)在添加測試數(shù)據(jù)時(shí)為每個(gè)blog都添加了不同的user,導(dǎo)致sql請求大大增加,處理時(shí)間也大大增加

多次訪問未緩存頁面

多次訪問http://localhost:8111/blogs后,服務(wù)器響應(yīng)時(shí)間大大減少,基本保持在700毫秒左右:

這是因?yàn)閙ysql實(shí)際上幫我們做了緩存的工作,因此,多次訪問后,服務(wù)器響應(yīng)時(shí)間會(huì)大大減少。如果大家有興趣,可以自行搜索mysql緩存相關(guān)的內(nèi)容。

多次訪問已緩存頁面

那么,在多次訪問http://localhost:8111/blogs/dao后,訪問時(shí)間基本保持在100多毫秒,比沒有緩存的頁面效率高了5倍左右,比第一次訪問效率高了20倍以上。

服務(wù)層緩存實(shí)現(xiàn)

Spring緩存的相關(guān)標(biāo)注

Spring 提供了一套標(biāo)注來保住我們快速的實(shí)現(xiàn)緩存系統(tǒng):

  • @Cacheable?觸發(fā)添加緩存的方法
  • @CacheEvict?觸發(fā)刪除緩存的方法
  • @CachePut?在不干涉方法執(zhí)行的情況下更新緩存
  • @Caching?組織多個(gè)緩存標(biāo)注的標(biāo)注
  • @CacheConfig?在class的層次共享緩存的設(shè)置

接下來我們來看緩存的具體實(shí)現(xiàn)。

添加ehcache設(shè)置

和數(shù)據(jù)層緩存一樣,需要在內(nèi)存中設(shè)置一塊區(qū)域來存放service的緩存,在src/main/resources/ehcache.xml中添加如下配置:

<cache name="com.tmy.service.allBlogs"></cache>

為某個(gè)方法添加緩存

首先,在BlogWithCacheService上添加@CacheConfig(cacheNames = "com.tmy.service.allBlogs")標(biāo)注,表明在BlogWithCacheService中的方法的緩存都是放在com.tmy.service.allBlogs區(qū)域中。

在需要緩存的方法上添加@Cacheable標(biāo)注:

@Cacheable(key = "#justTest") public List<BlogWithoutCache> findAll(String justTest){ return blogRepository.findAll(); }

當(dāng)?shù)谝淮握{(diào)用該方法后,其返回值就會(huì)添加進(jìn)緩存當(dāng)中,當(dāng)?shù)诙握{(diào)用時(shí)就能直接從緩存中獲取對象了。為了測試緩存功能,我們?yōu)閒indAll方法添加了一個(gè)參數(shù),這里我們將這個(gè)參數(shù)作為緩存的key。除了用參數(shù)之外,Spring還提供了其他解析方式來生成key:

  • 被調(diào)用方法的名稱?#root.methodName
  • 被調(diào)用的方法?#root.method.name
  • 被調(diào)用的目標(biāo)對象?#root.target
  • 被調(diào)用的對象的類名?#root.targetClass
  • 被調(diào)用方法的參數(shù)?#root.args[0]
  • 被調(diào)用方法所用的緩存?#root.caches[0].name
  • 被調(diào)用方法的參數(shù)名?#arg
  • 調(diào)用后的結(jié)果(該參數(shù)只在unless參數(shù)或者@CachePut標(biāo)注中才能使用)?#result

更新緩存

添加進(jìn)緩存后,在update方法中添加@CachePut標(biāo)注可以更新相應(yīng)的緩存,同樣,我們還是使用傳進(jìn)來的參數(shù)來更新相應(yīng)的緩存:

@CachePut(key = "#justTest") public List<BlogWithoutCache> updateAll(String justTest){ BlogWithoutCache blog = new BlogWithoutCache(); blog.setContent("這是不存在的博客"); blog.setTitle("謹(jǐn)慎使用這個(gè)方法"); return Lists.newArrayList(blog); }

刪除緩存

在某些情況下,我們還需要?jiǎng)h除緩存,@CacheEvict可以干這件事情:

@CacheEvict(key = "#justTest") public void evictAll(String justTest){ }

組織多種緩存操作

如果你想在一個(gè)方法中同時(shí)對緩存做多種操作,Spring支持使用@Caching來組織這些操作:

@Caching(evict = @CacheEvict(key="#justTest"), put = @CachePut(key="test")) public List<BlogWithoutCache> testForCaching(String justTest){ BlogWithoutCache blog = new BlogWithoutCache(); blog.setContent("這是不存在的博客"); blog.setTitle("謹(jǐn)慎使用這個(gè)方法"); return Lists.newArrayList(blog); }

性能對比

多次訪問service層緩存頁面

在多次訪問http://localhost:8111/blogs/service?test=test后,服務(wù)器的訪問時(shí)間基本保持在100毫秒以下,根據(jù)上次實(shí)驗(yàn)可以發(fā)現(xiàn),其效率甚至比加了數(shù)據(jù)層緩存后還要高。

更新緩存

更新緩存前,訪問http://localhost:8111/blogs/service?test=test頁面,看下以下博客:

訪問http://localhost:8111/blogs/service/update?test=test更新緩存,再次訪問http://localhost:8111/blogs/service?test=test,將發(fā)現(xiàn)數(shù)據(jù)庫沒有變化,但是返回的博客列表發(fā)生了變化:

刪除緩存

現(xiàn)在緩存對象已經(jīng)被玩壞了,讓我們訪問http://localhost:8111/blogs/service/evict?test=test緩存的對象給刪掉,再次訪問http://localhost:8111/blogs/service/update?test=test,我們發(fā)現(xiàn)博客列表重新變?yōu)檎_的列表,同時(shí)服務(wù)器響應(yīng)時(shí)間變成和沒有做緩存時(shí)一致:

頁面緩存的實(shí)現(xiàn)

添加緩存空間

同樣,第一件事情讓我們添加一下緩存的空間:

<cache name="com.tmy.mapper.allBlogs"></cache>

PageCachingFilter

ehcache為我們提供了幾個(gè)緩存頁面的filter,使用這些filter實(shí)現(xiàn)緩存:

  • SimplePageCachingFilter

最基本的頁面緩存filter實(shí)現(xiàn),其滿足大部分頁面緩存的需求,該filter只緩存頁面,不會(huì)修改herder的 ETag、Last-Modified、Expires屬性

  • SimplePageCachingFilterWithBlankPageProblem

當(dāng)response沒有提交時(shí)寫入緩存,否則不寫緩存,該緩存可能導(dǎo)致空白頁的錯(cuò)誤,需要特別注意!

  • SimplePageFragmentCachingFilter

專門針對那些不獨(dú)立存在,只是被include到其他頁面的頁面緩存

  • SimpleCachingHeadersPageCachingFilter

SimplePageCachingFilter的擴(kuò)展,會(huì)填寫herder的 ETag、Last-Modified、Expires屬性,可以進(jìn)一步減少瀏覽器的訪問次數(shù)

自定義的PageCachingFilter

以上filter會(huì)在filter初始化的時(shí)候通過FilterConfig對緩存進(jìn)行初始化,為了在SpringBoot中方便的通過注解去實(shí)例化這些Filter,我們將CacheName的獲取做一個(gè)定制:

public class CustomPageCachingFilter extends SimpleCachingHeadersPageCachingFilter { private final String customCacheName; public CustomPageCachingFilter(String name){ this.customCacheName = name; } @Override protected String getCacheName() { return customCacheName; } }

這樣,我們就能很方便的注入cacheName了。

EhCache只提供了添加緩存的Filter,但是并沒有提供刪除緩存的Filter,沒關(guān)系,讓我們來自己實(shí)現(xiàn)一個(gè):

public class ClearPageCachingFilter implements Filter { private final CacheManager cacheManager; private final String customCacheName; public ClearPageCachingFilter(String name){ this.customCacheName = name; cacheManager = CacheManager.getInstance(); assert cacheManager != null; } @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Ehcache ehcache = cacheManager.getEhcache(customCacheName); ehcache.removeAll(); } @Override public void destroy() {} }

現(xiàn)實(shí)情況URL的設(shè)計(jì)是極其復(fù)雜的,我們在這里就簡單粗暴的將所有cache直接刪除,如果緩存設(shè)計(jì)的比較好,最好可以通過ehcache.remove(key);的方式對cache進(jìn)行管理。

添加Filter

我們目前使用標(biāo)注的方式對Filter以及Filter mapping進(jìn)行管理,目前我們只緩存/blogs/page這一個(gè)頁面:

@Configuration @AutoConfigureAfter(CacheConfiguration.class) public class PageCacheConfiguration { @Bean public FilterRegistrationBean registerBlogsPageFilter(){ CustomPageCachingFilter customPageCachingFilter = new CustomPageCachingFilter("com.tmy.mapper.allBlogs"); FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(customPageCachingFilter); filterRegistrationBean.setUrlPatterns(Lists.newArrayList("/blogs/page")); return filterRegistrationBean; } @Bean public FilterRegistrationBean registerClearBlogsPageFilter(){ ClearPageCachingFilter clearPageCachingFilter = new ClearPageCachingFilter("com.tmy.mapper.allBlogs"); FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(clearPageCachingFilter); filterRegistrationBean.setUrlPatterns(Lists.newArrayList("/blogs/page/update", "/blogs/page/delete")); return filterRegistrationBean; } }

從以上配置可以看出,我們?yōu)?blogs/page注冊了一個(gè)添加緩存的Filter,/blogs/page請求將被緩存到內(nèi)存當(dāng)中。同時(shí),為/blogs/page/update以及/blogs/page/delete注冊了清空緩存的Filter,當(dāng)訪問這兩個(gè)url時(shí),將清空所有的緩存。

性能對比

訪問被緩存的頁面

訪問http://localhost:8111/blogs/page,刷新,我們可以看到,服務(wù)器的響應(yīng)時(shí)間只需要4毫秒,是mysql緩存、數(shù)據(jù)層緩存、服務(wù)層緩存當(dāng)中最好的。

清空緩存后第一次訪問

我們可以將以上幾種緩存結(jié)合起來一起使用,http://localhost:8111/blogs/page,該請求已經(jīng)結(jié)合了以上三種緩存的實(shí)現(xiàn)。因此,當(dāng)我們訪問http://localhost:8111/blogs/page/update清空頁面緩存時(shí),再次訪問http://localhost:8111/blogs/page也只需要100多毫秒,此時(shí)頁面緩存沒有命中,但是service層緩存命中。

總結(jié)

就實(shí)踐看來,數(shù)據(jù)層緩存、服務(wù)層緩存、頁面緩存一層比一層更加高效,但是由于其實(shí)現(xiàn)越來越復(fù)雜,需要考慮的情況也越來越多,因此,其設(shè)計(jì)也越來越復(fù)雜。

從服務(wù)層緩存的實(shí)現(xiàn)@CachePut實(shí)現(xiàn)來看,在這一層需要我們配置的東西越來越多,已經(jīng)有很大可能出現(xiàn)數(shù)據(jù)不一致的現(xiàn)象。而頁面緩存的復(fù)雜性相對服務(wù)層緩存又高了一個(gè)層級,因此在針對緩存進(jìn)行設(shè)計(jì)的時(shí)候,不僅僅考慮緩存所帶來的性能提升,還要考慮到更新緩存所帶來的性能損失。而且在實(shí)踐當(dāng)中,不是數(shù)據(jù)層緩存、服務(wù)層緩存、頁面緩存越多越好,需要根據(jù)實(shí)際情況做出選擇。

轉(zhuǎn)載于:https://www.cnblogs.com/duyinqiang/p/5696473.html

總結(jié)

以上是生活随笔為你收集整理的基于Spring的Web缓存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。