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 WebFlux.
Control de caché
CacheControl
proporciona soporte para configurar opciones asociadas con el encabezado Cache-Control
y se acepta como argumento en varios lugares:
-
Controladores
-
Recursos estáticos
Aunque RFC 7234 describe todas las directivas posibles para Cache-Control
tipo de encabezado de respuesta CacheControl
adopta un enfoque basado en casos de uso que se centra en escenarios comunes:
// Almacenamiento en caché durante una hora - "Cache-Control: max-age=3600"
CacheControl ccCacheOneHour = CacheControl.maxAge(1, TimeUnit.HOURS);
/// Impedir 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
// "Control de caché: max-age=864000, público, sin transformación"
CacheControl ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic();
// Almacenamiento en caché durante una hora - "Cache-Control: max-age=3600"
val ccCacheOneHour = CacheControl.maxAge(1, TimeUnit.HOURS)
/// Impedir 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
// "Control de caché: max-age=864000, público, sin transformación"
val ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic()
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:
@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)
}
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:
@RequestMapping
public Cadena myHandleMethod(Intercambio ServerWebExchange, modelo modelo) {
long eTag = ...
if (exchange.checkNotModified(eTag)) {
retorno nulo;
}
modelo.addAttribute(...);
return "myViewName";
}
- Cálculo específico de la aplicación.
- La respuesta se estableció en 304 (NOT_MODIFIED). No se produce ningún procesamiento adicional.
- Continuar procesando la solicitud.
@RequestMapping
diversión myHandleMethod (intercambio: ServerWebExchange, modelo: Modelo): ¿Cadena? {
val Etiqueta electrónica: Largo = ...
if (exchange.checkNotModified(eTag)) {
retorno nulo
}
model.addAttribute(...)
retorno "myViewName"
}
- Cálculo específico de la aplicación.
- La respuesta se estableció en 304 (NOT_MODIFIED). No se produce ningún procesamiento adicional.
- 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. Consulte la sección sobre configuración de recursos estáticos.
GO TO FULL VERSION