真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

在SpringBoot中實(shí)現(xiàn)HTTP緩存的方法

緩存是HTTP協(xié)議的一個強(qiáng)大功能,但由于某些原因,它主要用于靜態(tài)資源,如圖像,CSS樣式表或JavaScript文件,但是,HTTP緩存不僅限于這些,還可以將其用于動態(tài)計算的資源。

創(chuàng)新互聯(lián)為客戶提供專業(yè)的成都網(wǎng)站設(shè)計、做網(wǎng)站、程序、域名、空間一條龍服務(wù),提供基于WEB的系統(tǒng)開發(fā). 服務(wù)項(xiàng)目涵蓋了網(wǎng)頁設(shè)計、網(wǎng)站程序開發(fā)、WEB系統(tǒng)開發(fā)、微信二次開發(fā)、成都做手機(jī)網(wǎng)站等網(wǎng)站方面業(yè)務(wù)。

通過少量工作,您可以加快應(yīng)用程序并改善整體用戶體驗(yàn)。在本文中,您將學(xué)習(xí) 如何使用內(nèi)置的HTTP響應(yīng)緩存機(jī)制來實(shí)現(xiàn)緩存SpringBoot控制器的結(jié)果 。

1.如何以及何時使用HTTP響應(yīng)緩存?

您可以在應(yīng)用程序的多個層上進(jìn)行緩存。數(shù)據(jù)庫具有其緩存存儲,Web客戶端也在其需要重用的信息。HTTP協(xié)議負(fù)責(zé)網(wǎng)絡(luò)通信。緩存機(jī)制允許我們通過減少客戶端和服務(wù)器之間傳輸?shù)臄?shù)據(jù)量來優(yōu)化網(wǎng)絡(luò)流量。

何時優(yōu)化: 當(dāng)Web資源不經(jīng)常更改或您確切知道何時更新時,就可以使用HTTP緩存進(jìn)行優(yōu)化。一旦確定了HTTP緩存的競爭者,就需要選擇合適的方法來管理緩存的驗(yàn)證。 HTTP協(xié)議定義了幾個請求和響應(yīng)標(biāo)頭,您可以使用它們來控制客戶端何時清除緩存 。

選擇適當(dāng)?shù)腍TTP標(biāo)頭取決于您要優(yōu)化的特定情況。但是無論用例如何,我們可以根據(jù)緩存的驗(yàn)證發(fā)生在哪里進(jìn)行緩存管理選項(xiàng)的劃分。

2.客戶端緩存驗(yàn)證

當(dāng)您知道請求的資源在給定的時間內(nèi)不會更改時,服務(wù)器可以將此類信息作為響應(yīng)標(biāo)頭發(fā)送到客戶端?;谠撔畔?,客戶端決定是否應(yīng)該再次獲取資源或重用先前下載的資源。

有兩種可能的選項(xiàng)可以描述客戶端何時應(yīng)該再次獲取資源并刪除存儲的緩存值。所以讓我們看看他們是如何運(yùn)行的。

HTTP緩存在固定的時間內(nèi)有效:如果要 阻止客戶端在指定時間內(nèi)重新獲取資源,則應(yīng)該使用 Cache-Control 標(biāo)頭,可以在其中指定應(yīng)該重新獲取所獲取數(shù)據(jù)的時間。

通過將標(biāo)頭的值設(shè)置為 max-age = , 可以通知客戶端多長時間不再需要再次獲取資源。 緩存值的有效性與請求的時間有關(guān)。

為了設(shè)置在Spring的控制器中的HTTP標(biāo)頭,就要在RESTContoller用 ResponseEntity 包裝類 。

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

HTTP標(biāo)頭的值只是一個常規(guī)字符串,但是 Cache-Control Spring為我們提供了一個特殊的構(gòu)建器類,它可以防止我們犯下像拼寫錯誤這樣的小錯誤。

HTTP緩存有效到固定日期:有時您知道資源何時會發(fā)生變化。對于公布的數(shù)據(jù)而言,這是常見的情況,如天氣預(yù)報或昨天交易時段計算的股市指標(biāo)。 資源的確切到期日期可以向客戶端公開。 應(yīng)該使用 Expires HTTP標(biāo)頭。應(yīng)使用標(biāo)準(zhǔn)化數(shù)據(jù)格式 之一格式化日期值。

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

幸運(yùn)的是,Java附帶了第一個這些格式的預(yù)定義格式化程序。可以在下面找到將標(biāo)題設(shè)置為當(dāng)天結(jié)束的示例。

@GetMapping("/forecast")
ResponseEntity 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);
}

請注意, HTTP日期格式需要有關(guān)時區(qū)的信息 。這就是上面的例子使用 ZonedDateTime的原因 。如果您嘗試使用 LocalDateTime ,則最終會在運(yùn)行時出現(xiàn)以下錯誤消息:

java.time.temporal.UnsupportedTemporalTypeException:不支持的字段:OffsetSeconds

如果響應(yīng)中存在 Cache-Control 和 Expires 標(biāo)頭,則客戶端僅使用 Cache-Control 。

3.服務(wù)器端緩存驗(yàn)證

在基于用戶輸入的動態(tài)生成的內(nèi)容中,更常見的是服務(wù)器不知道何時將改變所請求的資源。在這種情況下,客戶端可以使用先前獲取的數(shù)據(jù),但首先,它需要詢問服務(wù)器該數(shù)據(jù)是否仍然有效。

自第一次握手以來資源是否被修改?如果跟蹤Web資源的修改日期,則可以將此類日期作為響應(yīng)的一部分公開給客戶端。在下一個請求中,客戶端將此日期發(fā)送回服務(wù)器,以便它可以驗(yàn)證自上一個請求以來資源是否已被修改。如果資源未更改,則服務(wù)器不必再次重新發(fā)送數(shù)據(jù)。相反,它使用304 HTTP代碼響應(yīng),沒有任何有效負(fù)載。

要公開資源的修改日期,您應(yīng)該設(shè)置 Last-Modified 標(biāo)頭。Spring的ResponseEntity構(gòu)建器有一個名為 lastModified() [url=https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/ResponseEntity.HeadersBuilder.html#lastModified-long-]的特殊方法[/url],它可以幫助您以正確的格式分配值。你會在一分鐘內(nèi)看到這一點(diǎn)。

但 在發(fā)送完整響應(yīng)之前,應(yīng)檢查客戶端是否 在請求中 包含 If-Modified-Since 標(biāo)頭??蛻舳烁鶕?jù) Last-Modified 標(biāo)頭的值設(shè)置其值,該標(biāo)頭是與此特定資源的先前響應(yīng)一起發(fā)送的。

如果 If-Modified-Since 標(biāo)頭的值與所請求資源的修改日期匹配,則可以節(jié)省一些帶寬并使用空主體響應(yīng)客戶端。

Spring再次提供了一個輔助方法,簡化了上述日期的比較。這個名為 checkNotModified()的 方法可以在 WebRequest 包裝器類中找到,您可以將其作為輸入添加到控制器的方法中。

讓我們仔細(xì)看看完整的例子。

@GetMapping("/{id}")
ResponseEntity 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);
}

首先,我們獲取所請求的資源并訪問其修改日期。我們將日期轉(zhuǎn)換為自格林威治標(biāo)準(zhǔn)時間1970年1月1日以來的毫秒數(shù),因?yàn)檫@是Spring框架期望的格式。

然后,我們將日期與 If-Modified-Since 標(biāo)頭的值進(jìn)行比較,并在正匹配上返回一個空。否則,服務(wù)器發(fā)送具有 Last-Modified 標(biāo)頭的適當(dāng)值的完整響應(yīng)主體。

憑借所有這些知識,您幾乎可以涵蓋所有常見的緩存設(shè)置選項(xiàng)。但是有一個更重要的機(jī)制你應(yīng)該知道的是......

使用ETag進(jìn)行資源版本控制

到目前為止,我們定義了有效期的精確度,精確度為1秒。但是如果你需要 更好的精度而不僅僅是一秒 呢?這就是ETag的用武之地。

可以將ETag定義為唯一的字符串值,該值在該時間點(diǎn)明確地標(biāo)識資源。 通常,服務(wù)器根據(jù)給定資源的屬性計算ETag,或者,如果可用,則計算其最新修改日期。

客戶端和服務(wù)器之間的通信流程與修改日期檢查的情況幾乎相同。只有標(biāo)題的名稱和值不同。

服務(wù)器在名為 ETag 的標(biāo)題中設(shè)置ETag值。當(dāng)客戶端再次訪問資源時,它應(yīng)該在名為 If-None-Match 的頭中發(fā)送其值。如果該值與資源的新計算的ETag匹配,則服務(wù)器可以使用空內(nèi)容和HTTP代碼304進(jìn)行響應(yīng)。

在Spring中,您可以實(shí)現(xiàn)ETag服務(wù)器流程,如下所示:

@GetMapping("/{id}")
ResponseEntity 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);
}

與前一個樣本幾乎相同,并且修改日期檢查。我們只是使用不同的值進(jìn)行比較(以及MD5算法來計算ETag)。 請注意, WebRequest 有一個重載的 checkNotModified() 方法來處理表示為字符串的ETag。

如果 Last-Modified 和 ETag 工作幾乎相同,為什么我們需要兩者嗎?

Last-Modified vs ETag

正如我已經(jīng)提到的, Last-Modified 標(biāo)頭 不太精確, 因?yàn)樗哂幸幻氲木?。為了獲得更高的精度,請選擇 ETag 。

當(dāng)您不跟蹤 資源 的修改日期 時,您也被迫使用 ETag 。服務(wù)器可以根據(jù)資源的屬性計算其值。將其視為對象的哈希碼。

如果資源具有其修改日期并且您可以使用一秒精度,請使用 Last-Modified 標(biāo)頭。為什么?因?yàn)?ETag計算可能是一項(xiàng)昂貴的操作 。

順便提一下,值得一提的是HTTP協(xié)議沒有指定用于計算ETag的算法。選擇算法時,您應(yīng)該關(guān)注它的速度。

本文重點(diǎn)介紹緩存GET請求,但您應(yīng)該知道服務(wù)器可以使用 ETag 來同步更新操作。

Spring ETag過濾器

因?yàn)镋Tag只是內(nèi)容的字符串表示,所以服務(wù)器可以使用響應(yīng)的字節(jié)表示來計算其值。意思是 你可以實(shí)際將ETag分配給任何響應(yīng)。

Spring框架為您提供了ETag響應(yīng)過濾器實(shí)現(xiàn) ,它可以為您完成。您所要做的就是在應(yīng)用程序中配置過濾器。

在Spring應(yīng)用程序中添加HTTP過濾器的最簡單方法是通過配置類中的 FilterRegistrationBean 。

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

在這種情況下,對 addUrlPatterns() 的調(diào)用是多余的,因?yàn)槟J(rèn)情況下所有路徑都匹配。我把它放在這里證明你可以控制Spring應(yīng)該添加ETag值的資源。

除了ETag生成之外,過濾器還會在可能的情況下響應(yīng)HTTP 304和空體內(nèi)容。

但要注意。

ETag計算可能很昂貴。 對于某些應(yīng)用程序啟用此過濾器實(shí)際上可能會導(dǎo)致弊大于利。在使用之前考慮一下您的解決方案。

結(jié)論

現(xiàn)在您已了解如何使用HTTP緩存優(yōu)化應(yīng)用程序,哪種方法最適合您,因?yàn)閼?yīng)用程序有不同的需求。

您了解到客戶端緩存驗(yàn)證是最有效的方法,因?yàn)椴簧婕皵?shù)據(jù)傳輸。在適用時,您應(yīng)該始終支持客戶端緩存驗(yàn)證。

我們還討論了服務(wù)器端驗(yàn)證并比較了 Last-Modified 和 ETag 標(biāo)頭。最后,您了解了如何在Spring應(yīng)用程序中設(shè)置全局ETag過濾器。

總結(jié)

以上所述是小編給大家介紹的在Spring Boot中實(shí)現(xiàn)HTTP緩存的方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對創(chuàng)新互聯(lián)網(wǎng)站的支持!


文章標(biāo)題:在SpringBoot中實(shí)現(xiàn)HTTP緩存的方法
鏈接地址:http://weahome.cn/article/jpsdjh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部