SpringMVC中的http Caching的具體使用

Cache 是HTTP協議中的一個非常重要的功能,使用Cache可以大大提高應用程序的性能,減少數據的網絡傳輸。

通常來說我們會對靜態資源比如:圖片,CSS,JS文件等做緩存。同樣的我們可以使用HTTP Cache配合Spring MVC來做動態資源的緩存。

那麼什麼時候使用動態資源的緩存呢?

隻有當這個資源不經常更新或者你確切的知道該資源什麼時候更新的時候就可以使用HTTP Cache瞭。

HTTP Cache是通過請求頭來實現的,主要有三種方式:過期時間,最後更新時間和Etag。

其中過期時間是客戶端驗證,最後更新時間和Etag是服務器端驗證。

過期時間

過期時間又有兩種方式,分別是Cache-Control和Expires頭。

在Cache-Control中,我們可以設置它的maxAge,超出該時間後,該資源才會被再次請求。如下所示:

@GetMapping("/{id}")
ResponseEntity<Product> getProduct(@PathVariable long id) {
   // …
   CacheControl cacheControl = CacheControl.maxAge(30, TimeUnit.MINUTES);
   return ResponseEntity.ok()
           .cacheControl(cacheControl)
           .body(product);
}

我們也可以在Head中設置Expires屬性。Expires的時間需要是標準時間格式,如下:

Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov  6 08:49:37 1994       ; ANSI C’s asctime() format

如果要在java中使用,參考如下的例子:

@GetMapping("/forecast")
ResponseEntity<Forecast> getTodaysForecast() {
   // ...
   ZonedDateTime expiresDate = ZonedDateTime.now().with(LocalTime.MAX);
   String expires = expiresDate.format(DateTimeFormatter.RFC_1123_DATE_TIME);
   return ResponseEntity.ok()
           .header(HttpHeaders.EXPIRES, expires)
           .body(weatherForecast);
}

如果Cache-Control和Expires同時出現,則會優先使用 Cache-Control。

Last-Modified

它的驗證邏輯是這樣的,客戶端會根據上次請求得到的Last-Modified設置它的If-Modified-Since,服務器端接收到瞭這個屬性之後可以跟之前的進行比較,如果相同則可以返回一個空的body。如下所示:

@GetMapping("/{id}")
ResponseEntity<Product> getProduct(@PathVariable long id, WebRequest request) {
   Product product = repository.find(id);
   long modificationDate = product.getModificationDate()
           .toInstant().toEpochMilli();
 
   if (request.checkNotModified(modificationDate)) {
       return null;
   }
 
   return ResponseEntity.ok()
           .lastModified(modificationDate)
           .body(product);
}

ETag

Last-Modified的時間隻能精確到秒,如果還需要更細粒度的話,就需要用到ETag瞭。

ETag可以看成當前時刻某個資源的唯一標記,你可以取該資源的hash值作為ETag。

下面是它的一種實現:

@GetMapping("/{id}")
ResponseEntity<Product> getProduct(@PathVariable long id, WebRequest request) {
   Product product = repository.find(id);
   String modificationDate = product.getModificationDate().toString();
   String eTag = DigestUtils.md5DigestAsHex(modificationDate.getBytes());
 
   if (request.checkNotModified(eTag)) {
       return null;
   }
 
   return ResponseEntity.ok()
           .eTag(eTag)
           .body(product);
}

Spring ETag filter

Spring提供瞭一個ShallowEtagHeaderFilter來根據返回的內容自動為你生成Etag。

@Bean
public FilterRegistrationBean filterRegistrationBean () {
   ShallowEtagHeaderFilter eTagFilter = new ShallowEtagHeaderFilter();
   FilterRegistrationBean registration = new FilterRegistrationBean();
   registration.setFilter(eTagFilter);
   registration.addUrlPatterns("/*");
   return registration;
}

請註意, ETag計算可能會影響性能。

到此這篇關於SpringMVC中的http Caching的具體使用的文章就介紹到這瞭,更多相關SpringMVC http Caching內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: