HTTP-кэширование может значительно повысить производительность веб-приложения. HTTP-кэширование строится вокруг заголовка ответа Cache-Control
и, впоследствии, условных заголовков запроса, таких как Last-Modified
и ETag
. Cache-Control
указывает приватным (например, браузеру) и публичным (например, прокси) кэшам, как кэшировать и повторно использовать ответы. Заголовок ETag
используется для условного запроса, который может привести к ответу 304 (NOT_MODIFIED) без тела, если содержимое не изменилось. ETag
можно считать более совершенным преемником заголовка Last-Modified
.
В этом разделе описаны опции, связанные с HTTP-кэшированием, которые доступны в Spring WebFlux.
CacheControl
CacheControl
предоставляет средства поддержки для конфигурирования параметров, связанных с заголовком Cache-Control
, и принимается в качестве аргумента в ряде мест:
-
Контроллеры
-
Статические ресурсы
Наряду с тем, что RFC 7234 описывает все возможные директивы для заголовка ответа Cache-Control
, тип CacheControl
использует подход, ориентированный на конкретные случаи использования, который фокусируется на общих сценариях:
// Кэширование в течение часа - "Cache-Control: max-age=3600"
CacheControl ccCacheOneHour = CacheControl.maxAge(1, TimeUnit.HOURS);
/// Предотвращение кэширования - "Cache-Control: no-store"
CacheControl ccNoStore = CacheControl.noStore();
// Кэширование в течение десяти дней в публичных и приватных кэшах,
// публичный кэш не должен преобразовывать ответ
// "Cache-Control: max-age=864000, public, no-transform"
CacheControl ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic();
// Кэширование в течение часа - "Cache-Control: max-age=3600"
val ccCacheOneHour = CacheControl.maxAge(1, TimeUnit.HOURS)
/// Предотвращение кэширования - "Cache-Control: no-store"
val ccNoStore = CacheControl.noStore()
// Кэширование в течение десяти дней в публичных и приватных кэшах,
// публичный кэш не должен преобразовывать ответ
// "Cache-Control: max-age=864000, public, no-transform"
val ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic()
Контроллеры
Контроллеры могут добавлять явную поддержку 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);
}
@GetMapping("/book/{id}")
fun showBook(@PathVariable id: Long): ResponseEntity<Book> {
val book = findBook(id)
val 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(ServerWebExchange exchange, Model model) {
long eTag = ...
if (exchange.checkNotModified(eTag)) {
return null;
}
model.addAttribute(...);
return "myViewName";
}
- Вычисление для конкретного приложения.
- Ответ был установлен на 304 (NOT_MODIFIED). Дальнейшая обработка не происходит.
- Продолжаем обработку запроса.
@RequestMapping
fun myHandleMethod(exchange: ServerWebExchange, model: Model): String? {
val eTag: Long = ...
if (exchange.checkNotModified(eTag)) {
return null
}
model.addAttribute(...)
return "myViewName"
}
- Вычисление для конкретного приложения.
- Ответ был установлен на 304 (NOT_MODIFIED). Дальнейшая обработка не происходит.
- Продолжаем обработку запроса.
Существует три варианта проверки условных запросов на соответствие значениям eTag
, значениям lastModified
или обоим. Для условных запросов GET
и HEAD
можно установить ответ на 304 (NOT_MODIFIED). Для условных POST
, PUT
и DELETE
вы можете вместо этого установить ответ на 412 (PRECONDITION_FAILED), чтобы предотвратить одновременную модификацию.
Статические ресурсы
Для оптимальной производительности статические ресурсы следует обрабатывать с использованием Cache-Control
и условных заголовков ответа. См. раздел о конфигурировании статических ресурсов.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ