HTTP瀏覽器緩存
對(duì)這部分知識(shí)不太熟悉的,可以先看一下這篇文章:HTTP瀏覽器緩存機(jī)制
配置文件yml配置
spring: resources: static-locations: classpath:/static/,classpath:/views/,classpath:/templates/ chain: strategy: #MD5實(shí)現(xiàn) content: enabled: true paths: /** #版本號(hào)管理(與MD5實(shí)現(xiàn)方式同時(shí)存在時(shí),需要指定不同的路徑,來分別實(shí)現(xiàn)對(duì)應(yīng)的文件管理) #fixed: # 開啟版本控制策略,默認(rèn)為false #enabled: true #paths: /**,/v1.0.0/** #version: v1.0.0 cache: true compressed: false enabled: true #緩存 cache: cachecontrol: cache-public: true # 緩存有效期 24小時(shí) max-age: 24h # 資源緩存時(shí)間,單位天,7天 period: 7d
瀏覽器緩存的過程:
1、當(dāng)?shù)谝淮卧L問時(shí),所有的靜態(tài)資源文件沒有緩存,需要請(qǐng)求服務(wù)下載對(duì)應(yīng)的文件
2、當(dāng)?shù)诙雾撁婕虞d時(shí),因?yàn)槲覀冮_啟了緩存,瀏覽器會(huì)判斷是否有緩存
3、有緩存,需要判斷,緩存是否過期,過期時(shí)間就是通過配置緩存有效期:max-age: 24h,實(shí)現(xiàn)的
4、如果沒有過期,則靜態(tài)文件直接讀取瀏覽器緩存,不會(huì)向服務(wù)器重新訪問資源
5、如果沒有緩存或者緩存已經(jīng)過期,則需要請(qǐng)求服務(wù)器,并通過判斷Last-Modified:響應(yīng)資源的最后修改時(shí)間,是否更新,如果沒有更新,返回304狀態(tài),讀取瀏覽器緩存
6、如果更新了,則說明該文件的再服務(wù)器端已經(jīng)發(fā)生了改變,瀏覽器需要重新加載更新該文件
7、至此一個(gè)完整的瀏覽器緩存加載頁面靜態(tài)資源的過程就算完成了
8、當(dāng)瀏覽器向服務(wù)器請(qǐng)求后,無論是沒有更新,返回304,還是有更新,重新加載文件,新一輪的緩存有效期生成,也就是之前過期的有效期,現(xiàn)在又重新開始計(jì)算時(shí)間,此時(shí)再訪問靜態(tài)文件,會(huì)直接讀取緩存,直到緩存再次過期,再進(jìn)行下一次的循環(huán)。
9、我的配置中沒有使用Etag,因?yàn)樗枰芏嗟膍d5運(yùn)算,消耗較多的內(nèi)存,我覺得我的系統(tǒng)暫時(shí)可以不需要這一層
靜態(tài)資源版本控制
Spring 默認(rèn)提供了靜態(tài)資源版本映射的支持。
當(dāng)我們的資源內(nèi)容發(fā)生改變時(shí),由于瀏覽器緩存,用戶本地的資源還是舊資源,為了防止這種情況發(fā)生導(dǎo)致的問題。我們可能會(huì)選擇在資源文件后面加上參數(shù)“版本號(hào)”或其他方式。
時(shí)間戳實(shí)現(xiàn)
在htnl中一如靜態(tài)文件時(shí),加一個(gè)時(shí)間戳的后綴,每次加載時(shí)間戳是不一樣的,這樣能保證瀏覽器每次都向服務(wù)器重新請(qǐng)求加載
<script> document.write('<script type="text/javascript" src="script/basicschema/common.js?v=' + Date.now() + '"><\/script>'); </script> <script> document.write('<script type="text/javascript" src="script/basicschema/basicdata/energyUnit.js?v=' + Date.now() + '"><\/script>'); </script>
MD5實(shí)現(xiàn)
首先在application.yml配置(在最上邊的配置文件內(nèi)容中已經(jīng)有了)
spring: resources: chain: strategy: #MD5實(shí)現(xiàn) content: enabled: true paths: /**
其次,如果您恰巧和我一樣使用Thymeleaf作為模板引擎,則可以和我一樣使用@bean語法直接從模板訪問ResourceUrlProvider bean。
<script th:src="@{ ${@mvcResourceUrlProvider.getForLookupPath('/script/basicschema/common.js')}}"></script> <script th:src="@{ ${@mvcResourceUrlProvider.getForLookupPath('/script/basicschema/benchmark/benchmarkItem.js')}}"></script>
注意:如果你的js文件沒有修改,或者修改沒重啟,MD5的值可能不會(huì)改變,當(dāng)你重啟服務(wù)后你會(huì)看到你修改過后的文件MD5也隨之改變了。
簡(jiǎn)單看了下源代碼,MD5的計(jì)算是通過 ContentVersionStrategy 這個(gè)類實(shí)現(xiàn)的。此VersionStrategy實(shí)現(xiàn)根據(jù)資源的內(nèi)容計(jì)算MD5哈希值,并將其附加到文件名后面,也就是你不改變內(nèi)容MD5值是不會(huì)變的
這種方式類似于Etag的方式,只不過,我們可以自主控制對(duì)哪些文件進(jìn)行md5計(jì)算。
問題:使用ControllerAdvice這種方式,我嘗試了以后,不能用,html中使用urls,報(bào)錯(cuò),不識(shí)別,不知道什么原因,(有知道原因的可以告知一下)代碼如下:
代碼如下:
@ControllerAdvice public class ControllerConfig { @Autowired ResourceUrlProvider resourceUrlProvider; @ModelAttribute("urls") public ResourceUrlProvider urls() { return this.resourceUrlProvider; } }
<script type="text/javascript" th:src="@{${urls.getForLookupPath('/script/basicschema/benchmark/benchmarkItem.js') }}"></script>
這樣寫,就不行,頁面會(huì)報(bào)錯(cuò),不識(shí)別urls
版本號(hào)實(shí)現(xiàn)
在application.yml或者application.properties中增加配置文件
spring: resources: static-locations: classpath:/static/,classpath:/views/,classpath:/templates/ chain: strategy: #版本號(hào)管理(與MD5實(shí)現(xiàn)方式同時(shí)存在時(shí),需要指定不同的路徑,來分別實(shí)現(xiàn)對(duì)應(yīng)的文件管理) fixed: enabled: true paths: paths: /**,/v1.0.0/** version: v1.0.0
其次,如果您恰巧和我一樣使用Thymeleaf作為模板引擎,則可以和我一樣使用@bean語法直接從模板訪問ResourceUrlProvider bean。
<script th:src="@{ ${@mvcResourceUrlProvider.getForLookupPath('/script/basicschema/common.js')}}"></script> <script th:src="@{ ${@mvcResourceUrlProvider.getForLookupPath('/script/basicschema/benchmark/benchmarkItem.js')}}"></script>
正常來說,配置了相應(yīng)的映射路徑,則系統(tǒng)便會(huì)在文件路徑最前面加上相應(yīng)的版本號(hào),當(dāng)我們每次修改只需要更新版本號(hào)的設(shè)置,客戶端就會(huì)自動(dòng)請(qǐng)求最新的數(shù)據(jù)了。
同樣的看了下此VersionStrategy的實(shí)現(xiàn)是FixedVersionStrategy類,來使固定版本字符串作為資源路徑的前綴。
如圖,文件的路徑最前面會(huì)加上對(duì)應(yīng)的版本號(hào)
總結(jié)
通過以上的配置,我們就可以做到即可以對(duì)一些第三方或者不會(huì)變的靜態(tài)文件進(jìn)行緩存,減少每次加載文件的訪問量,又可以對(duì)一些需要經(jīng)常更改和變化的文件實(shí)現(xiàn)了單獨(dú)的控制,保證他可以及時(shí)更新,而不會(huì)一直是緩存文件。
當(dāng)然不知道是不是因?yàn)橛玫氖荢pringBoot2.x的原因,從網(wǎng)上翻閱資料查到的一些實(shí)現(xiàn)方式,在我的系統(tǒng)里似乎有些方法和配置不好用,如果知道問題在哪的朋友,還望指點(diǎn)迷津。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/xue317378914/article/details/106638326