javascript
Spring MVC 中的http Caching
文章目錄
- 過(guò)期時(shí)間
- Last-Modified
- ETag
- Spring ETag filter
Spring MVC 中的http Caching
Cache 是HTTP協(xié)議中的一個(gè)非常重要的功能,使用Cache可以大大提高應(yīng)用程序的性能,減少數(shù)據(jù)的網(wǎng)絡(luò)傳輸。
通常來(lái)說(shuō)我們會(huì)對(duì)靜態(tài)資源比如:圖片,CSS,JS文件等做緩存。同樣的我們可以使用HTTP Cache配合Spring MVC來(lái)做動(dòng)態(tài)資源的緩存。
那么什么時(shí)候使用動(dòng)態(tài)資源的緩存呢?
只有當(dāng)這個(gè)資源不經(jīng)常更新或者你確切的知道該資源什么時(shí)候更新的時(shí)候就可以使用HTTP Cache了。
HTTP Cache是通過(guò)請(qǐng)求頭來(lái)實(shí)現(xiàn)的,主要有三種方式:過(guò)期時(shí)間,最后更新時(shí)間和Etag。
其中過(guò)期時(shí)間是客戶端驗(yàn)證,最后更新時(shí)間和Etag是服務(wù)器端驗(yàn)證。
過(guò)期時(shí)間
過(guò)期時(shí)間又有兩種方式,分別是Cache-Control和Expires頭。
在Cache-Control中,我們可以設(shè)置它的maxAge,超出該時(shí)間后,該資源才會(huì)被再次請(qǐng)求。如下所示:
@GetMapping("/{id}") ResponseEntity<Product> getProduct(@PathVariable long id) {// …CacheControl cacheControl = CacheControl.maxAge(30, TimeUnit.MINUTES);return ResponseEntity.ok().cacheControl(cacheControl).body(product); }我們也可以在Head中設(shè)置Expires屬性。Expires的時(shí)間需要是標(biāo)準(zhǔn)時(shí)間格式,如下:
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同時(shí)出現(xiàn),則會(huì)優(yōu)先使用 Cache-Control。
Last-Modified
它的驗(yàn)證邏輯是這樣的,客戶端會(huì)根據(jù)上次請(qǐng)求得到的Last-Modified設(shè)置它的If-Modified-Since,服務(wù)器端接收到了這個(gè)屬性之后可以跟之前的進(jìn)行比較,如果相同則可以返回一個(gè)空的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的時(shí)間只能精確到秒,如果還需要更細(xì)粒度的話,就需要用到ETag了。
ETag可以看成當(dāng)前時(shí)刻某個(gè)資源的唯一標(biāo)記,你可以取該資源的hash值作為ETag。
下面是它的一種實(shí)現(xiàn):
@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提供了一個(gè)ShallowEtagHeaderFilter來(lái)根據(jù)返回的內(nèi)容自動(dòng)為你生成Etag。
@Bean public FilterRegistrationBean filterRegistrationBean () {ShallowEtagHeaderFilter eTagFilter = new ShallowEtagHeaderFilter();FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(eTagFilter);registration.addUrlPatterns("/*");return registration; }請(qǐng)注意, ETag計(jì)算可能會(huì)影響性能。
更多教程請(qǐng)參考 flydean的博客
超強(qiáng)干貨來(lái)襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的Spring MVC 中的http Caching的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: scala教程之:可见性规则
- 下一篇: 新版gitbook导出pdf