控制器可以增加对 HTTP 缓存的明确支持。我们推荐这样做,因为资源的 lastModified 或 ETag 值需要在与条件请求头进行比较之前进行计算。控制器可以为 ResponseEntity 添加 ETag 头和 Cache-Control 设置,如下例所示:

    1. @GetMapping("/book/{id}")
    2. public ResponseEntity<Book> showBook(@PathVariable Long id) {
    3. Book book = findBook(id);
    4. String version = book.getVersion();
    5. return ResponseEntity
    6. .ok()
    7. .cacheControl(CacheControl.maxAge(30, TimeUnit.DAYS))
    8. .eTag(version) // lastModified 也是可用的
    9. .body(book);
    10. }

    如果与条件请求头的比较表明内容没有改变,前面的例子会发送一个 304(NOT_MODIFIED)响应,并有一个空的正文。否则,ETag 和 Cache-Control 头信息将被添加到响应中。

    你也可以在控制器中对条件请求头进行检查,如下面的例子所示:

    1. @RequestMapping
    2. public String myHandleMethod(WebRequest request, Model model) {
    3. // 特定的应用计算,比如可以用文件的 哈希值,或则数据库中存储的版本字段,或则文件的修改时间等,都可以用来做 eTag
    4. long eTag = ...
    5. if (request.checkNotModified(eTag)) {
    6. // 响应会被设置为 304(NOT_MODIFIED),不需要进一步处理
    7. return null;
    8. }
    9. // 继续进行请求处理。
    10. model.addAttribute(...);
    11. return "myViewName";
    12. }

    有三种变体用于根据 eTag 值、lastModified 值或两者检查条件性请求。对于有条件的 GET 和 HEAD 请求,你可以将响应设置为 304(NOT_MODIFIED)。对于有条件的 POST、PUT 和 DELETE 请求,你可以将响应设置为 412(PRECONDITION_FAILED),以防止并发的修改。