JavaRush /Курсы /Spring /HTTP-кэширование

HTTP-кэширование

Spring
4 уровень , 27 лекция
Открыта

HTTP-кэширование может значительно повысить производительность веб-приложения. HTTP-кэширование строится вокруг заголовка ответа Cache-Control и, впоследствии, условных заголовков запроса (таких как Last-Modified и ETag). Cache-Control указывает приватным (например, браузеру) и публичным (например, прокси) кэшам, как кэшировать и повторно использовать ответы. Заголовок ETag используется для условного запроса, который может привести к ответу 304 (NOT_MODIFIED) без тела, если содержимое не изменилось. ETag можно считать более совершенным преемником заголовка Last-Modified.

В этом разделе описаны опции, связанные с HTTP-кэшированием, которые доступны в Spring Web MVC.

CacheControl

CacheControl предоставляет средства поддержки для конфигурирования параметров, связанных с заголовком Cache-Control, и принимается в качестве аргумента в ряде мест:

В то время как RFC 7234 описывает все возможные директивы для заголовка ответа Cache-Control, тип CacheControl использует подход, ориентированный на конкретные случаи использования, который фокусируется на общих сценариях:

Java
// Кэширование в течение часа - "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();
Kotlin
// Кэширование в течение часа - "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()

WebContentGenerator также принимает более простое свойство cachePeriod (определенное в секундах), которое работает следующим образом:

  • Значение -1 не генерирует заголовок ответа Cache-Control.

  • Значение 0 предотвращает кэширование при помощи директивы "Cache-Control: no-store".

  • При значении n > 0 предоставленный ответ кэшируется на n секунд при помощи директивы "Cache-Control: max-age=n".

Контроллеры

Контроллеры могут добавлять явную поддержку 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);
}
Kotlin
@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.

Вы также можете осуществить проверку на условные заголовки запроса в контроллере, как показано в следующем примере:

Java
@RequestMapping
public String myHandleMethod(WebRequest request, Model model) {
    long eTag = ... 
    if (request.checkNotModified(eTag)) {
        return null; 
    }
    model.addAttribute(...); 
    return "myViewName";
}
  1. Вычисление для конкретного приложения.
  2. Ответ был установлен на 304 (NOT_MODIFIED) – дальнейшая обработка запрещена.
  3. Продолжаем обработку запроса.
Kotlin
@RequestMapping
fun myHandleMethod(request: WebRequest, model: Model): String? {
    val eTag: Long = ... 
    if (request.checkNotModified(eTag)) {
        return null 
    }
    model[...] = ... 
    return "myViewName"
}
  1. Вычисление для конкретного приложения.
  2. Ответ был установлен на 304 (NOT_MODIFIED) – дальнейшая обработка запрещена.
  3. Продолжаем обработку запроса.

Существует три варианта проверки условных запросов на соответствие значениям eTag, значениям lastModified или обоим. Для условных запросов GET и HEAD можно установить ответ на 304 (NOT_MODIFIED). Для условных POST, PUT и DELETE вы можете вместо этого установить ответ на 412 (PRECONDITION_FAILED), чтобы предотвратить одновременную модификацию.

Статические ресурсы

Для оптимальной производительности статические ресурсы следует обрабатывать с использованием Cache-Control и условных заголовков ответа.

Фильтр ETag

ShallowEtagHeaderFilter можно использовать для добавления "поверхностных" значений eTag, которые вычисляются из содержимого ответа и, таким образом, экономят пропускную способность, но не процессорное время.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ