HTTP缓存可以显着提高Web应用程序的性能。 HTTP缓存围绕Cache-Control响应标头以及随后的条件请求标头(例如Last-Modified和ETag)。 缓存控制为私有(例如浏览器)和公共(例如代理)缓存提供有关如何缓存和重用响应的建议。 ETag标头用于发出条件请求,如果内容未更改,则可能导致没有主体的304(NOT_MODIFIED)。 ETag可以看作是Last-Modified头的更复杂的后继者。
本节描述了Spring Web MVC中与HTTP缓存相关的选项。
CacheControl支持配置与Cache-Control标头相关的设置,并在许多地方作为参数被接受:
尽管RFC 7234描述了Cache-Control响应标头的所有可能的指令,但CacheControl类型采用了面向用例的方法,着重于常见方案:
// Cache for an hour - "Cache-Control: max-age=3600"
CacheControl ccCacheOneHour = CacheControl.maxAge(1, TimeUnit.HOURS);
// Prevent caching - "Cache-Control: no-store"
CacheControl ccNoStore = CacheControl.noStore();
// Cache for ten days in public and private caches,
// public caches should not transform the response
// "Cache-Control: max-age=864000, public, no-transform"
CacheControl ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic();
WebContentGenerator还接受一个更简单的cachePeriod属性(以秒为单位定义),该属性的工作方式如下:
控制器可以添加对HTTP缓存的显式支持。 我们建议您这样做,因为需要先计算资源的lastModified或ETag值,然后才能将其与条件请求标头进行比较。 控制器可以将ETag标头和Cache-Control设置添加到ResponseEntity,如以下示例所示:
@GetMapping("/book/{id}")
public ResponseEntity<Book> showBook(@PathVariable Long id) {
Book book = findBook(id);
String version = book.getVersion();
return ResponseEntity
.ok()
.cacheControl(CacheControl.maxAge(30, TimeUnit.DAYS))
.eTag(version) // lastModified is also available
.body(book);
}
如果与条件请求标头的比较表明内容未更改,则前面的示例发送带有空主体的304(NOT_MODIFIED)响应。 否则,ETag和Cache-Control标头将添加到响应中。
您还可以在控制器中针对条件请求标头进行检查,如以下示例所示:
@RequestMapping
public String myHandleMethod(WebRequest webRequest, Model model) {
long eTag = ...
if (request.checkNotModified(eTag)) {
return null;
}
model.addAttribute(...);
return "myViewName";
}
可以使用三种变体来检查针对eTag值,lastModified值或两者的条件请求。 对于有条件的GET和HEAD请求,可以将响应设置为304(NOT_MODIFIED)。 对于条件POST,PUT和DELETE,您可以将响应设置为409(PRECONDITION_FAILED),以防止并发修改。
您应该将静态资源与Cache-Control和条件响应标头一起提供,以实现最佳性能。 请参阅有关配置静态资源的部分。
您可以使用ShallowEtagHeaderFilter添加从响应内容计算得出的“shallow” eTag值,从而节省带宽,但不节省CPU时间。 请参阅浅ETag。