天天看點

SpringBoot2.x配置靜态檔案緩存

HTTP浏覽器緩存

對這部分知識不太熟悉的,可以先看一下這篇文章:HTTP浏覽器緩存機制

配置檔案yml配置

spring:
 resources:
   static-locations: classpath:/static/,classpath:/views/,classpath:/templates/
   chain:
      strategy:
        #MD5實作
        content:
          enabled: true
          paths: /**
        #版本号管理(與MD5實作方式同時存在時,需要指定不同的路徑,來分别實作對應的檔案管理)
        #fixed:
          # 開啟版本控制政策,預設為false
          #enabled: true
          #paths: /**,/v1.0.0/**
          #version: v1.0.0
      cache: true
      compressed: false
      enabled: true
    #緩存
   cache:
      cachecontrol:
        cache-public: true
        # 緩存有效期 24小時
        max-age: 24h
      # 資源緩存時間,機關天,7天
      period: 7d

           

浏覽器緩存的過程:

SpringBoot2.x配置靜态檔案緩存
  1. 當第一次通路時,所有的靜态資源檔案沒有緩存,需要請求服務下載下傳對應的檔案
  2. 當第二次頁面加載時,因為我們開啟了緩存,浏覽器會判斷是否有緩存
  3. 有緩存,需要判斷,緩存是否過期,過期時間就是通過配置緩存有效期:

    max-age: 24h

    ,實作的
  4. 如果沒有過期,則靜态檔案直接讀取浏覽器緩存,不會向伺服器重新通路資源
    SpringBoot2.x配置靜态檔案緩存
  5. 如果沒有緩存或者緩存已經過期,則需要請求伺服器,并通過判斷Last-Modified:響應資源的最後修改時間,是否更新,如果沒有更新,傳回304狀态,讀取浏覽器緩存
    SpringBoot2.x配置靜态檔案緩存
  6. 如果更新了,則說明該檔案的再伺服器端已經發生了改變,浏覽器需要重新加載更新該檔案
  7. 至此一個完整的浏覽器緩存加載頁面靜态資源的過程就算完成了
  8. 當浏覽器向伺服器請求後,無論是沒有更新,傳回304,還是有更新,重新加載檔案,新一輪的緩存有效期生成,也就是之前過期的有效期,現在又重新開始計算時間,此時再通路靜态檔案,會直接讀取緩存,直到緩存再次過期,再進行下一次的循環。
  9. 我的配置中沒有使用Etag,因為它需要很多的md5運算,消耗較多的記憶體,我覺得我的系統暫時可以不需要這一層

靜态資源版本控制

Spring 預設提供了靜态資源版本映射的支援。

當我們的資源内容發生改變時,由于浏覽器緩存,使用者本地的資源還是舊資源,為了防止這種情況發生導緻的問題。我們可能會選擇在資源檔案後面加上參數“版本号”或其他方式。

時間戳實作

在htnl中一如靜态檔案時,加一個時間戳的字尾,每次加載時間戳是不一樣的,這樣能保證浏覽器每次都向伺服器重新請求加載

<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>
           
SpringBoot2.x配置靜态檔案緩存

MD5實作

首先在application.yml配置(在最上邊的配置檔案内容中已經有了)

spring:
 resources:
   chain:
      strategy:
        #MD5實作
        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>
           
SpringBoot2.x配置靜态檔案緩存

注意:如果你的js檔案沒有修改,或者修改沒重新開機,MD5的值可能不會改變,當你重新開機服務後你會看到你修改過後的檔案MD5也随之改變了。

簡單看了下源代碼,MD5的計算是通過 ContentVersionStrategy 這個類實作的。此VersionStrategy實作根據資源的内容計算MD5哈希值,并将其附加到檔案名後面,也就是你不改變内容MD5值是不會變的

這種方式類似于Etag的方式,隻不過,我們可以自主要制對哪些檔案進行md5計算。

問題:使用ControllerAdvice這種方式,我嘗試了以後,不能用,html中使用urls,報錯,不識别,不知道什麼原因,(有知道原因的可以告知一下)代碼如下:

@ControllerAdvice
public class ControllerConfig {
    @Autowired
    ResourceUrlProvider resourceUrlProvider;

    @ModelAttribute("urls")
    public ResourceUrlProvider urls() {
        return this.resourceUrlProvider;
    }
}
           

這樣寫,就不行,頁面會報錯,不識别urls

版本号實作

在application.yml或者application.properties中增加配置檔案

spring:
 resources:
   static-locations: classpath:/static/,classpath:/views/,classpath:/templates/
   chain:
      strategy:
        #版本号管理(與MD5實作方式同時存在時,需要指定不同的路徑,來分别實作對應的檔案管理)
        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>
           

正常來說,配置了相應的映射路徑,則系統便會在檔案路徑最前面加上相應的版本号,當我們每次修改隻需要更新版本号的設定,用戶端就會自動請求最新的資料了。

同樣的看了下此VersionStrategy的實作是FixedVersionStrategy類,來使固定版本字元串作為資源路徑的字首。

SpringBoot2.x配置靜态檔案緩存

如圖,檔案的路徑最前面會加上對應的版本号

總結

通過以上的配置,我們就可以做到即可以對一些第三方或者不會變的靜态檔案進行緩存,減少每次加載檔案的通路量,又可以對一些需要經常更改和變化的檔案實作了單獨的控制,保證他可以及時更新,而不會一直是緩存檔案。

當然不知道是不是因為用的是SpringBoot2.x的原因,從網上翻閱資料查到的一些實作方式,在我的系統裡似乎有些方法和配置不好用,如果知道問題在哪的朋友,還望指點迷津。