SpringBoot2.0實現靜態資源版本控制

寫在最前面

猶記畢業第一年時,公司每次發佈完成後,都會在一個羣裏通知【版本更新,各部門清理緩存,有問題及時反饋】之類的話。歸根結底就是資源緩存的問題,瀏覽器會將請求到的靜態資源,如JS、CSS等文件緩存到用戶本地,當用戶再次訪問時就不須要再次請求這些資源了,以此也是提高了用戶體驗。可是也正是由於這些資源緩存,致使客戶端的靜態文件每每不是當前最新版本。後來有同事增長了時間戳、隨機數等,確實這也解決了客戶端緩存的問題,可是卻又帶來了新的麻煩,致使每次訪問都要請求服務器,無形中增長了服務器的壓力。html

那麼有什麼辦法可讓客戶端當須要更新時纔去請求,不需更新就不請求嗎?固然有,實現方式不少種,像前端實現,webjars實現等均可以,可是麻煩仍是麻煩,太燒腦。介紹一種Spring自身提供的方式,也是我目前所應用的方式,ResourceUrlProvider前端

ResourceUrlProvider的實現效果有兩種,你們能夠在後文中看到。java

第一種、MD5實現

首先在application.yml或者application.properties中增長配置文件web

spring: 
  resources:
    chain:
      strategy:
        content:
          enabled: true
          paths: /**

其次,若是您恰巧和我同樣使用Thymeleaf做爲模板引擎,則能夠和我同樣使用@bean語法直接從模板訪問ResourceUrlProvider bean。
spring

    <script th:src="${@mvcResourceUrlProvider.getForLookupPath('/mods/admin/login.js')}"></script>

若是您使用的模板引擎沒法直接訪問Spring bean,則能夠將ResourceUrlProvider 添加到Spring中。使用ControllerAdvice,代碼以下:api

@ControllerAdvice
public class ControllerConfig {

    @Autowired
    ResourceUrlProvider resourceUrlProvider;

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

}

而後在頁面上經過下述代碼引用:瀏覽器

<script th:src="${urls.getForLookupPath('/mods/admin/login.js')}"></script>

此方法應適用於支持方法調用的全部模板引擎。spring-mvc

下面咱們來看看具體的實現效果吧,前臺訪問後html頁面顯示爲:緩存

<script src="/mods/admin/login-96d770c87905659930c9786eaa08d710.js"></script>

注意:若是你的js文件沒有修改,或者修改沒重啓,MD5的值可能不會改變,當你重啓服務後你會看到你修改事後的文件MD5也隨之改變了。服務器

簡單看了下源代碼,MD5的計算是經過 ContentVersionStrategy 這個類實現的VersionStrategy實現根據資源的內容計算MD5哈希值,並將其附加到文件名後面,也就是你不改變內容MD5值是不會變的哦,一度讓我覺得這種方法有BUG(。•ˇ‸ˇ•。)

第二種、版本號實現

一樣在application.yml或者application.properties中增長配置文件

spring: 
  resources:
    chain:
      strategy:
        fixed:
          enabled: true
          paths: /mods/admin/*.js
          version: 20181128

後續操做同上,此時咱們看下頁面顯示的效果:

<script src="/20181128/mods/admin/login.js"></script>

在文件路徑的最前面增長了版本號,當咱們每次修改只須要更新版本號的設置,客戶端就會自動請求最新的數據了。

一樣的看了下此VersionStrategy的實現是FixedVersionStrategy類,來使固定版本字符串做爲資源路徑的前綴。

總結

相比其餘方式的靜態資源控制,這種方式是我目前發現最簡便的了,尤爲是在SpringBoot項目中的使用。在這兩種方式中,我更傾向於方法一的MD5方式,可讓咱們沒必要太過於關注靜態資源問題。固然上述講的兩個實現類,在傳統SpringMVC項目中也是有的,因此傳統項目也是可使用的,具體的使用方法你們能夠研究研究。

隨筆小記,喜歡幫忙點個贊吧。實現思路來自Michael Scharhag:https://www.mscharhag.com/spring/resource-versioning-with-spring-mvc

相關文章
相關標籤/搜索