Spring MVC 中的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计算可能会影响性能。

更多教程请参考 flydean的博客

Spring MVC 中的http Caching的更多相关文章

  1. Spring mvc中@RequestMapping 6个基本用法

    Spring mvc中@RequestMapping 6个基本用法 spring mvc中的@RequestMapping的用法.  1)最基本的,方法级别上应用,例如: Java代码 @Reques ...

  2. spring mvc中使用freemark的一点心得

    参考文档: FreeMarker标签与使用 连接http://blog.csdn.net/nengyu/article/details/6829244 freemarker学习笔记--指令参考: ht ...

  3. Http请求中Content-Type讲解以及在Spring MVC中的应用

    引言: 在Http请求中,我们每天都在使用Content-type来指定不同格式的请求信息,但是却很少有人去全面了解content-type中允许的值有多少,这里将讲解Content-Type的可用值 ...

  4. Spring mvc中@RequestMapping 6个基本用法小结(转载)

    小结下spring mvc中的@RequestMapping的用法. 1)最基本的,方法级别上应用,例如: @RequestMapping(value="/departments" ...

  5. Spring MVC中处理静态资源的多种方法

    处理静态资源,我想这可能是框架搭建完成之后Web开发的”头等大事“了. 因为一个网站的显示肯定会依赖各种资源:脚本.图片等,那么问题来了,如何在页面中请求这些静态资源呢? 还记得Spring MVC中 ...

  6. Spring MVC 中的基于注解的 Controller【转】

    原文地址:http://my.oschina.net/abian/blog/128028 终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 H ...

  7. spring mvc中的文件上传

    使用commons-fileupload上传文件所需要的架包有:commons-fileupload 和common-io两个架包支持,可以到Apache官网下砸. 在配置文件spring-mvc.x ...

  8. spring mvc中的valid

    当你希望在spring mvc中直接校验表单参数时,你可以采用如下操作: 声明Validator的方式: 1.为每一个Controller声明一个Validator @Controller publi ...

  9. spring mvc中的@PathVariable(转)

    鸣谢:http://jackyrong.iteye.com/blog/2059307 ------------------------------------------------ spring m ...

随机推荐

  1. C++中的各种进制转换函数汇总

    C++中的各种进制转换函数汇总 1.在C中,按指定进制格式输出如下: #include <iostream> #include <cstdio> using namespace ...

  2. ANTLR随笔(二)

    安装ANTLR 作者的电脑是MAC的操作系统macOS Catalina 10.15.2. 安装步骤后linux操作的系统的一样, Windows系统大致步骤一样,但是环境变量等配置有差别,作者很久没 ...

  3. jmeter术语

    1.负载:模拟业务请求操作对服务器造成压力的过程 2.性能测试(performance testing):模拟用户负载来测试系统在负载情况下,系统的响应时间.吞吐量等指标是否满足性能要求 3.负载测试 ...

  4. Oracle 12C安装教程

    Oracle 12C安装教程 由 Alma 创建, 最后一次修改 2018-06-04 10:32:31 Oracle 12c,全称Oracle Database 12c,是Oracle 11g的升级 ...

  5. var、let和const的区别详解

      let 和 const 是 ECMAScript6 新推出的特性,其中 let 是能够替代 var 的"标准",所以我们探讨 var.let 和 const 的区别,首先应该知 ...

  6. 微信小程序之界面交互反馈

    交互反馈就是在用户出发某事件之后,给用户一个反馈信息,这要是一个很友好的习惯. 在小程序中是通过一下几种方式实现的: 1.wx.showToast()方法 showToast: function (p ...

  7. Python设计模式(8)-抽象工厂

    # coding=utf-8 这种方式反倒把事情做复杂了 可取之处在于有了更高层次的抽象 class IEmployee: def insert_employee(self): pass class ...

  8. go1.13errors的用法

    go1.13errors的用法 前言 基本用法 fmt.Errorf Unwrap errors.Is As 扩展 参考 go1.13errors的用法 前言 go 1.13发布了error的一些新的 ...

  9. 宏定义#define和内联函数inline的区别

    1 宏定义在预编译的时候进行字符串替换.内联函数在编译的时候进行函数展开. 2 宏定义没有类型检查.内联函数会进行参数列表.返回值等类型检查.

  10. AJ学IOS 之CoreLocation反地理编码小Demo输入经纬度得到城市

    AJ分享,必须精品 一:效果 输入经纬度,可以得到相应的地名 二:思路 跟地里编码差不多 1.获取用户输入的经纬度 2.根据用户输入的经纬度创建CLLocation对象 3.根据CLLocation对 ...