最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在Spring Boot中實現(xiàn)HTTP緩存的方法

 更新時間:2018年10月30日 16:52:40   作者:banq  
緩存是HTTP協(xié)議的一個強大功能,但由于某些原因,它主要用于靜態(tài)資源,如圖像,CSS樣式表或JavaScript文件。本文重點給大家介紹在Spring Boot中實現(xiàn)HTTP緩存的方法,感興趣的朋友跟隨小編一起看看吧

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

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

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

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

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

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

2.客戶端緩存驗證

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

要公開資源的修改日期,您應(yīng)該設(shè)置 Last-Modified 標頭。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)看到這一點。

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

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

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

讓我們仔細看看完整的例子。

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

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

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

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

使用ETag進行資源版本控制

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

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

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

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

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

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

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

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

Last-Modified vs ETag

正如我已經(jīng)提到的, Last-Modified 標頭 不太精確, 因為它具有一秒的精度。為了獲得更高的精度,請選擇 ETag 。

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

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

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

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

Spring ETag過濾器

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

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

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

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

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

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

但要注意。

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

結(jié)論

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

您了解到客戶端緩存驗證是最有效的方法,因為不涉及數(shù)據(jù)傳輸。在適用時,您應(yīng)該始終支持客戶端緩存驗證。

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

總結(jié)

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

相關(guān)文章

  • Java多線程中sleep和wait區(qū)別

    Java多線程中sleep和wait區(qū)別

    本文主要介紹了Java多線程中sleep和wait區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • spring boot整合CAS配置詳解

    spring boot整合CAS配置詳解

    這篇文章主要介紹了spring boot整合CAS配置詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • Json讀寫本地文件實現(xiàn)代碼

    Json讀寫本地文件實現(xiàn)代碼

    今天沒事研究了下Gson,寫了個工具類,需要的朋友可以參考下
    2014-03-03
  • 使用jd-gui反編譯修改jar包里的.class并重新生成新jar問題

    使用jd-gui反編譯修改jar包里的.class并重新生成新jar問題

    這篇文章主要介紹了使用jd-gui反編譯修改jar包里的.class并重新生成新jar問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java?流處理之收集器詳解

    Java?流處理之收集器詳解

    這篇文章主要介紹了Java?流處理之收集器,本文以記錄?Record?為例,結(jié)合示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • java中mybatis和hibernate的用法總結(jié)

    java中mybatis和hibernate的用法總結(jié)

    在本篇文章里小編給大家整理的是一篇關(guān)于java中mybatis和hibernate的用法總結(jié)內(nèi)容,有興趣的朋友們可以學習參考下。
    2021-01-01
  • Mybatis動態(tài)SQL實例詳解

    Mybatis動態(tài)SQL實例詳解

    這篇文章主要給大家介紹了關(guān)于Mybatis動態(tài)SQL的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • SptingBoot過濾器Filter的使用詳解

    SptingBoot過濾器Filter的使用詳解

    這篇文章主要介紹了SptingBoot過濾器Filter的使用詳解,Filter屬于Servlet規(guī)范,并不是Spring獨有的,Filter主要用于攔截請求,做一些業(yè)務(wù)邏輯操作,然后可以決定請求是否可以繼續(xù)往下分發(fā),落到其他的Filter或者對應(yīng)的Servlet,需要的朋友可以參考下
    2023-09-09
  • Java實現(xiàn)鼠標模擬與鍵盤映射

    Java實現(xiàn)鼠標模擬與鍵盤映射

    這篇文章主要為大家詳細介紹了Java實現(xiàn)鼠標模擬與鍵盤映射,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • 基于spring mvc請求controller訪問方式

    基于spring mvc請求controller訪問方式

    這篇文章主要介紹了spring mvc請求controller訪問方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評論

凉山| 秭归县| 交城县| 腾冲县| 济宁市| 革吉县| 扎兰屯市| 阿巴嘎旗| 横山县| 皮山县| 葵青区| 勐海县| 四会市| 绥中县| 乐东| 新密市| 安宁市| 黄陵县| 密山市| 罗甸县| 新乐市| 枣庄市| 昌黎县| 南投县| 卢氏县| 交口县| 合江县| 交城县| 锦屏县| 东台市| 四子王旗| 平凉市| 罗山县| 福贡县| 宿迁市| 望谟县| 巴林左旗| 九龙县| 阿勒泰市| 绵竹市| 富蕴县|