CodeGym /Cursos Java /Módulo 5. Spring /almacenamiento en caché HTTP

almacenamiento en caché HTTP

Módulo 5. Spring
Nivel 9 , Lección 14
Disponible

El almacenamiento en caché HTTP puede mejorar significativamente el rendimiento de una aplicación web. El almacenamiento en caché HTTP se basa en el encabezado de respuesta Cache-Control y posteriormente en los encabezados de solicitud condicionales (como Last-Modified y ETag). Cache-Control le dice a las cachés privadas (por ejemplo, el navegador) y públicas (por ejemplo, el proxy) cómo almacenar en caché y reutilizar las respuestas. El encabezado ETag se utiliza para una solicitud condicional, que puede resultar en una respuesta 304 (NOT_MODIFIED) sin cuerpo si el contenido no ha cambiado. ETag puede considerarse un sucesor más avanzado del encabezado Last-Modified.

Esta sección describe las opciones relacionadas con el almacenamiento en caché HTTP disponibles en Spring Web MVC.

Control de caché

CacheControl proporciona soporte para configurar opciones asociadas con el encabezado Cache-Control y se acepta como argumento en varios lugares:

Mientras que RFC 7234 describe todas las directivas posibles para la respuesta del encabezado Cache-Control, escriba CacheControl adopta un enfoque basado en casos de uso que se centra en escenarios comunes:

Java
// Almacenamiento en caché durante una hora - "Cache-Control: max-age=3600"
CacheControl ccCacheOneHour = CacheControl.maxAge(1, TimeUnit.HOURS);
// Evitar el almacenamiento en caché - "Cache-Control: no-store".
CacheControl ccNoStore = CacheControl.noStore();
// Almacenamiento en caché durante diez días en cachés públicos y privados,
// el caché público no debería convertir la respuesta
// "Cache-Control: max-age=864000, public, no-transform"
CacheControl ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic();
Kotlin
// Almacenamiento en caché durante una hora - "Cache-Control: max-age=3600"
val ccCacheOneHour = CacheControl.maxAge(1, TimeUnit.HOURS)
// Evitar el almacenamiento en caché - "Cache-Control: no-store".
val ccNoStore = CacheControl.noStore()
// Almacenamiento en caché durante diez días en cachés públicos y privados,
// el caché público no debería convertir la respuesta
// "Cache-Control: max-age=864000, public, no-transform"
val ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic()

WebContentGenerator también acepta una propiedad cachePeriod más simple (definida en segundos) que funciona así:

  • El valor -1 no genera un encabezado de respuesta Cache-Control.

  • El valor 0 evita el almacenamiento en caché utilizando la directiva "Cache-Control: no-store".

  • Cuando el valor es n > 0 La respuesta proporcionada se almacena en caché durante n segundos usando la directiva "Cache-Control: max-age=n".

Controladores

Los controladores pueden agregar soporte explícito para el almacenamiento en caché HTTP. Recomendamos hacer esto porque el valor lastModified o ETag para un recurso debe calcularse antes de poder compararlo con los encabezados de solicitud condicionales. El controlador puede agregar el encabezado ETag y los parámetros Cache-Control a ResponseEntity, como se muestra en el siguiente ejemplo:

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 también está disponible
            .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 también está disponible
            .body(book)
}

En el ejemplo anterior, se envía una respuesta 304 (NOT_MODIFIED) con un cuerpo vacío si una comparación con los encabezados de solicitud condicional indica que el contenido no ha cambiado. De lo contrario, los encabezados ETag y Cache-Control se agregan a la respuesta.

También puede verificar los encabezados de solicitud condicionales en el controlador, como se muestra en el siguiente ejemplo:

Java
@RequestMapping
public String myHandleMethod(WebRequest request, Model model) {
    long eTag = ...
    if (request.checkNotModified(eTag)) {
        return null; 
    }
    model.addAttribute(...); 
    return "myViewName";
}
  1. Cálculo específico de la aplicación.
  2. La respuesta se estableció en 304 (NOT_MODIFIED): no se permite ningún procesamiento adicional.
  3. Continuar procesando la solicitud.
Kotlin
@RequestMapping
fun myHandleMethod(request: WebRequest, model: Model): String? {
    val eTag: Long = ...
    if (request.checkNotModified(eTag)) {
        return null 
    }
    model[...] = ... 
    return "myViewName"
}
  1. Cálculo específico de la aplicación.
  2. La respuesta se estableció en 304 (NOT_MODIFIED): no se permite ningún procesamiento adicional.
  3. Continuar procesando la solicitud.

Hay tres opciones para verificar las solicitudes condicionales con los valores de eTag, los valores de lastModified o ambos. Para solicitudes condicionales GET y HEAD, puede establecer la respuesta en 304 (NOT_MODIFIED). Para POST, PUT y DELETE condicionales, puede establecer la respuesta en 412 (PRECONDITION_FAILED) para evitar modificaciones simultáneas.

Recursos estáticos

Para un rendimiento óptimo, los recursos estáticos deben manejarse mediante Cache-Control y encabezados de respuesta condicionales.

Filtro ETag

ShallowEtagHeaderFilter se puede utilizar para agregar valores de eTag "superficiales" que se calculan a partir del contenido de la respuesta y, por lo tanto, ahorran ancho de banda pero no tiempo de CPU.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION