# 1.8 HTTP Caching

HTTP缓存可以显着提高Web应用程序的性能。 HTTP缓存围绕Cache-Control响应标头以及随后的条件请求标头（例如Last-Modified和ETag）。 缓存控制为私有（例如浏览器）和公共（例如代理）缓存提供有关如何缓存和重用响应的建议。 ETag标头用于发出条件请求，如果内容未更改，则可能导致没有主体的304（NOT\_MODIFIED）。 ETag可以看作是Last-Modified头的更复杂的后继者。

本节描述了Spring Web MVC中与HTTP缓存相关的选项。

## 1.8.1 CacheControl

CacheControl支持配置与Cache-Control标头相关的设置，并在许多地方作为参数被接受：

* WebContentInterceptor
* WebContentGenerator
* 控制器
* 静态资源

尽管RFC 7234描述了Cache-Control响应标头的所有可能的指令，但CacheControl类型采用了面向用例的方法，着重于常见方案：

```java
// 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属性（以秒为单位定义），该属性的工作方式如下：

* -1值不会生成Cache-Control响应标头。
* 值为0可以防止使用“ Cache-Control：无存储”指令进行缓存。
* n> 0值通过使用'Cache-Control：max-age = n'指令将给定响应缓存n秒。

## 1.8.2 控制器

控制器可以添加对HTTP缓存的显式支持。 我们建议您这样做，因为需要先计算资源的lastModified或ETag值，然后才能将其与条件请求标头进行比较。 控制器可以将ETag标头和Cache-Control设置添加到ResponseEntity，如以下示例所示：

```java
@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标头将添加到响应中。

您还可以在控制器中针对条件请求标头进行检查，如以下示例所示：

```java
@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），以防止并发修改。

## 1.8.3 Static Resources

您应该将静态资源与Cache-Control和条件响应标头一起提供，以实现最佳性能。 请参阅有关配置静态资源的部分。

## 1.8.4 ETag Filter

您可以使用ShallowEtagHeaderFilter添加从响应内容计算得出的“shallow” eTag值，从而节省带宽，但不节省CPU时间。 请参阅浅ETag。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flydean.com/spring-framework-documentation5/webservlet/1.spring-web-mvc/1.8http-caching.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
