From ef41dcf6878d4063f10cfa946bcf079b2bf71eb4 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 11 Jun 2018 16:38:19 -0400 Subject: [PATCH] Add HTTP caching to WebFlux section Issue: SPR-16395 --- src/docs/asciidoc/web/webflux.adoc | 118 +++++++++++++++++++++++++++++ src/docs/asciidoc/web/webmvc.adoc | 4 + 2 files changed, 122 insertions(+) diff --git a/src/docs/asciidoc/web/webflux.adoc b/src/docs/asciidoc/web/webflux.adoc index 60818c5b58..2e41f4c5e7 100644 --- a/src/docs/asciidoc/web/webflux.adoc +++ b/src/docs/asciidoc/web/webflux.adoc @@ -2540,6 +2540,124 @@ include::webflux-view.adoc[leveloffset=+1] +[[webflux-caching]] +== HTTP Caching +[.small]#<># + +HTTP caching can significantly improve the performance of a web application. HTTP caching +revolves around the "Cache-Control" response header and subsequently conditional request +headers such as "Last-Modified" and "ETag". "Cache-Control" advises private (e.g. browser) +and public (e.g. proxy) caches how to cache and re-use responses. An "ETag" header is used +to make a conditional request that may result in a 304 (NOT_MODIFIED) without a body, +if the content has not changed. "ETag" can be seen as a more sophisticated successor to +the `Last-Modified` header. + +This section describes HTTP caching related options available in Spring Web MVC. + + + +[[webflux-caching-cachecontrol]] +=== `CacheControl` +[.small]#<># + +{api-spring-framework}/http/CacheControl.html[`CacheControl`] provides support for +configuring settings related to the "Cache-Control" header and is accepted as an argument +in a number of places: + +* <> +* <> + +While https://tools.ietf.org/html/rfc7234#section-5.2.2[RFC 7234] describes all possible +directives for the "Cache-Control" response header, the `CacheControl` type takes a +use case oriented approach focusing on the common scenarios: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // 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(); +---- + + + +[[webflux-caching-etag-lastmodified]] +=== Controllers +[.small]#<># + +Controllers can add explicit support for HTTP caching. This is recommended since the +lastModified or ETag value for a resource needs to be calculated before it can be compared +against conditional request headers. A controller can add an ETag and "Cache-Control" +settings to a `ResponseEntity`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @GetMapping("/book/{id}") + public ResponseEntity 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); + } +---- + +This will send an 304 (NOT_MODIFIED) response with an empty body, if the comparison +to the conditional request headers indicates the content has not changed. Otherwise the +"ETag" and "Cache-Control" headers will be added to the response. + +The check against conditional request headers can also be made in the controller: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping + public String myHandleMethod(ServerWebExchange exchange, Model model) { + + long eTag = ... <1> + + if (exchange.checkNotModified(eTag)) { + return null; <2> + } + + model.addAttribute(...); <3> + return "myViewName"; + } +---- + +<1> Application-specific calculation. +<2> Response has been set to 304 (NOT_MODIFIED), no further processing. +<3> Continue with request processing. + +There are 3 variants for checking conditional requests against eTag values, lastModified +values, or both. For conditional "GET" and "HEAD" requests, the response may be set to +304 (NOT_MODIFIED). For conditional "POST", "PUT", and "DELETE", the response would be set +to 409 (PRECONDITION_FAILED) instead to prevent concurrent modification. + + + +[[webflux-caching-static-resources]] +=== Static resources +[.small]#<># + +Static resources should be served with a "Cache-Control" and conditional response headers +for optimal performance. See section on configuring <>. + + + + [[webflux-config]] == WebFlux Config [.small]#<># diff --git a/src/docs/asciidoc/web/webmvc.adoc b/src/docs/asciidoc/web/webmvc.adoc index b7f02719e0..d966b8100d 100644 --- a/src/docs/asciidoc/web/webmvc.adoc +++ b/src/docs/asciidoc/web/webmvc.adoc @@ -3708,6 +3708,7 @@ http://hdiv.org/[HDIV] is another web security framework that integrates with Sp [[mvc-caching]] == HTTP Caching +[.small]#<># HTTP caching can significantly improve the performance of a web application. HTTP caching revolves around the "Cache-Control" response header and subsequently conditional request @@ -3723,6 +3724,7 @@ This section describes HTTP caching related options available in Spring Web MVC. [[mvc-caching-cachecontrol]] === `CacheControl` +[.small]#<># {api-spring-framework}/http/CacheControl.html[`CacheControl`] provides support for configuring settings related to the "Cache-Control" header and is accepted as an argument @@ -3764,6 +3766,7 @@ works as follows: [[mvc-caching-etag-lastmodified]] === Controllers +[.small]#<># Controllers can add explicit support for HTTP caching. This is recommended since the lastModified or ETag value for a resource needs to be calculated before it can be compared @@ -3823,6 +3826,7 @@ to 409 (PRECONDITION_FAILED) instead to prevent concurrent modification. [[mvc-caching-static-resources]] === Static resources +[.small]#<># Static resources should be served with a "Cache-Control" and conditional response headers for optimal performance. See section on configuring <>. -- GitLab