Improve HTTP caching flexiblity
This commit improves HTTP caching defaults and flexibility in
Spring MVC.
1) Better default caching headers
The `WebContentGenerator` abstract class has been updated with
better HTTP defaults for HTTP caching, in line with current
browsers and proxies implementation (wide support of HTTP1.1, etc);
depending on the `setCacheSeconds` value:
* sends "Cache-Control: max-age=xxx" for caching responses and
do not send a "must-revalidate" value by default.
* sends "Cache-Control: no-store" or "Cache-Control: no-cache"
in order to prevent caching
Other methods used to set specific header such as
`setUseExpiresHeader` or `setAlwaysMustRevalidate` are now deprecated
in favor of `setCacheControl` for better flexibility.
Using one of the deprecated methods re-enables previous HTTP caching
behavior.
This change is applied in many Handlers, since
`WebContentGenerator` is extended by `AbstractController`,
`WebContentInterceptor`, `ResourceHttpRequestHandler` and others.
2) New CacheControl builder class
This new class brings more flexibility and allows developers
to set custom HTTP caching headers.
Several strategies are provided:
* `CacheControl.maxAge(int)` for caching responses with a
"Cache-Control: max-age=xxx" header
* `CacheControl.noStore()` prevents responses from being cached
with a "Cache-Control: no-store" header
* `CacheControl.noCache()` forces caches to revalidate the cached
response before reusing it, with a "Cache-Control: no-store" header.
From that point, it is possible to chain method calls to craft a
custom CacheControl instance:
```
CacheControl cc = CacheControl.maxAge(1, TimeUnit.HOURS)
.cachePublic().noTransform();
```
3) Configuring HTTP caching in Resource Handlers
On top of the existing ways of configuring caching mechanisms,
it is now possible to use a custom `CacheControl` to serve
resources:
```
@Configuration
public class MyWebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
CacheControl cc = CacheControl.maxAge(1, TimeUnit.HOURS);
registry.addResourceHandler("/resources/**)
.addResourceLocations("classpath:/resources/")
.setCacheControl(cc);
}
}
```
or
```
<mvc:resources mapping="/resources/**" location="classpath:/resources/">
<mvc:cachecontrol max-age="3600" cache-public="true"/>
</mvc:resources>
```
Issue: SPR-2779, SPR-6834, SPR-7129, SPR-9543, SPR-10464
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.http;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public class CacheControlTests {
|
||||
|
||||
private static final String CACHE_CONTROL_HEADER = "Cache-Control";
|
||||
|
||||
@Test
|
||||
public void emptyCacheControl() throws Exception {
|
||||
CacheControl cc = CacheControl.empty();
|
||||
assertThat(cc.getHeaderValue(), Matchers.nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maxAge() throws Exception {
|
||||
CacheControl cc = CacheControl.maxAge(1, TimeUnit.HOURS);
|
||||
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maxAgeAndDirectives() throws Exception {
|
||||
CacheControl cc = CacheControl.maxAge(3600, TimeUnit.SECONDS).cachePublic().noTransform();
|
||||
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600, no-transform, public"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maxAgeAndSMaxAge() throws Exception {
|
||||
CacheControl cc = CacheControl.maxAge(1, TimeUnit.HOURS).sMaxAge(30, TimeUnit.MINUTES);
|
||||
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600, s-maxage=1800"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noCachePrivate() throws Exception {
|
||||
CacheControl cc = CacheControl.noCache().cachePrivate();
|
||||
assertThat(cc.getHeaderValue(), Matchers.equalTo("no-cache, private"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noStore() throws Exception {
|
||||
CacheControl cc = CacheControl.noStore();
|
||||
assertThat(cc.getHeaderValue(), Matchers.equalTo("no-store"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user