Skip to content

Commit 1099731

Browse files
author
tinexw
committed
Set CacheControl for static resources from properties file
1 parent 7d5f3a3 commit 1099731

File tree

4 files changed

+369
-14
lines changed

4 files changed

+369
-14
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java

Lines changed: 229 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@
1616

1717
package org.springframework.boot.autoconfigure.web;
1818

19+
import java.util.concurrent.TimeUnit;
20+
21+
import javax.annotation.PostConstruct;
22+
1923
import org.springframework.boot.context.properties.ConfigurationProperties;
24+
import org.springframework.boot.context.properties.NestedConfigurationProperty;
25+
import org.springframework.util.Assert;
2026

2127
/**
2228
* Properties used to configure resource handling.
@@ -25,14 +31,15 @@
2531
* @author Brian Clozel
2632
* @author Dave Syer
2733
* @author Venil Noronha
34+
* @author Kristine Jetzke
2835
* @since 1.1.0
2936
*/
3037
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
3138
public class ResourceProperties {
3239

3340
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
3441
"classpath:/META-INF/resources/", "classpath:/resources/",
35-
"classpath:/static/", "classpath:/public/" };
42+
"classpath:/static/", "classpath:/public/"};
3643

3744
/**
3845
* Locations of static resources. Defaults to classpath:[/META-INF/resources/,
@@ -41,10 +48,17 @@ public class ResourceProperties {
4148
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
4249

4350
/**
44-
* Cache period for the resources served by the resource handler, in seconds.
51+
* Cache period for the resources served by the resource handler, in seconds. Either
52+
* {@link #cachePeriod} or {@link #cacheControl} can be set.
4553
*/
4654
private Integer cachePeriod;
4755

56+
/**
57+
* Cache control headers. Either {@link #cachePeriod} or {@link #cacheControl} can be set.
58+
*/
59+
@NestedConfigurationProperty
60+
private CacheControl cacheControl;
61+
4862
/**
4963
* Enable default resource handling.
5064
*/
@@ -77,6 +91,15 @@ public void setCachePeriod(Integer cachePeriod) {
7791
this.cachePeriod = cachePeriod;
7892
}
7993

94+
public CacheControl getCacheControl() {
95+
return this.cacheControl;
96+
}
97+
98+
public void setCacheControl(CacheControl cacheControl) {
99+
this.cacheControl = cacheControl;
100+
}
101+
102+
80103
public boolean isAddMappings() {
81104
return this.addMappings;
82105
}
@@ -89,6 +112,36 @@ public Chain getChain() {
89112
return this.chain;
90113
}
91114

115+
public org.springframework.http.CacheControl createCacheControl() {
116+
if (this.cachePeriod != null) {
117+
return org.springframework.http.CacheControl.maxAge(this.cachePeriod, TimeUnit.SECONDS);
118+
}
119+
if (this.cacheControl != null) {
120+
return CacheControl.createCacheControl(this.cacheControl);
121+
}
122+
return null;
123+
}
124+
125+
@PostConstruct
126+
public void checkIncompatibleCacheOptions() {
127+
Assert.state(this.cachePeriod == null || this.cacheControl == null,
128+
"Only one of cache-period or cache-control may be set.");
129+
if (this.cacheControl != null) {
130+
if (this.cacheControl.getMaxAge() != null) {
131+
Assert.state(!Boolean.TRUE.equals(this.cacheControl.getNoCache()), "no-cache may not be set if max-age is set.");
132+
Assert.state(!Boolean.TRUE.equals(this.cacheControl.getNoStore()), "no-store may not be set if max-age is set.");
133+
}
134+
if (this.cacheControl.getNoCache() != null) {
135+
Assert.state(this.cacheControl.getMaxAge() == null, "max-age may not be set if no-cache is set.");
136+
Assert.state(!Boolean.TRUE.equals(this.cacheControl.getNoStore()), "no-store may not be set if no-cache is set.");
137+
}
138+
if (this.cacheControl.getNoStore() != null) {
139+
Assert.state(this.cacheControl.getMaxAge() == null, "max-age may not be set if no-store is set.");
140+
Assert.state(!Boolean.TRUE.equals(this.cacheControl.getNoCache()), "no-cache may not be set if no-store is set.");
141+
}
142+
}
143+
}
144+
92145
/**
93146
* Configuration for the Spring Resource Handling chain.
94147
*/
@@ -121,8 +174,9 @@ public static class Chain {
121174
/**
122175
* Return whether the resource chain is enabled. Return {@code null} if no
123176
* specific settings are present.
124-
* @return whether the resource chain is enabled or {@code null} if no specified
125-
* settings are present.
177+
*
178+
* @return whether the resource chain is enabled or {@code null} if no specified settings are
179+
* present.
126180
*/
127181
public Boolean getEnabled() {
128182
return getEnabled(getStrategy().getFixed().isEnabled(),
@@ -200,7 +254,7 @@ public static class Content {
200254
/**
201255
* Comma-separated list of patterns to apply to the Version Strategy.
202256
*/
203-
private String[] paths = new String[] { "/**" };
257+
private String[] paths = new String[]{"/**"};
204258

205259
public boolean isEnabled() {
206260
return this.enabled;
@@ -233,7 +287,7 @@ public static class Fixed {
233287
/**
234288
* Comma-separated list of patterns to apply to the Version Strategy.
235289
*/
236-
private String[] paths = new String[] { "/**" };
290+
private String[] paths = new String[]{"/**"};
237291

238292
/**
239293
* Version string to use for the Version Strategy.
@@ -266,4 +320,173 @@ public void setVersion(String version) {
266320

267321
}
268322

323+
/**
324+
* Configuration for the Cache Control header.
325+
*/
326+
327+
public static class CacheControl {
328+
329+
private Long maxAge;
330+
331+
private Boolean noCache;
332+
333+
private Boolean noStore;
334+
335+
private Boolean mustRevalidate;
336+
337+
private Boolean noTransform;
338+
339+
private Boolean cachePublic;
340+
341+
private Boolean cachePrivate;
342+
343+
private Boolean proxyRevalidate;
344+
345+
private Long staleWhileRevalidate;
346+
347+
private Long staleIfError;
348+
349+
private Long sMaxAge;
350+
351+
public Long getMaxAge() {
352+
return this.maxAge;
353+
}
354+
355+
public void setMaxAge(Long maxAge) {
356+
this.maxAge = maxAge;
357+
}
358+
359+
public Boolean getNoCache() {
360+
return this.noCache;
361+
}
362+
363+
public void setNoCache(Boolean noCache) {
364+
this.noCache = noCache;
365+
}
366+
367+
public Boolean getNoStore() {
368+
return this.noStore;
369+
}
370+
371+
public void setNoStore(Boolean noStore) {
372+
this.noStore = noStore;
373+
}
374+
375+
public Boolean getMustRevalidate() {
376+
return this.mustRevalidate;
377+
}
378+
379+
public void setMustRevalidate(Boolean mustRevalidate) {
380+
this.mustRevalidate = mustRevalidate;
381+
}
382+
383+
public Boolean getNoTransform() {
384+
return this.noTransform;
385+
}
386+
387+
public void setNoTransform(Boolean noTransform) {
388+
this.noTransform = noTransform;
389+
}
390+
391+
public Boolean getCachePublic() {
392+
return this.cachePublic;
393+
}
394+
395+
public void setCachePublic(Boolean cachePublic) {
396+
this.cachePublic = cachePublic;
397+
}
398+
399+
public Boolean getCachePrivate() {
400+
return this.cachePrivate;
401+
}
402+
403+
public void setCachePrivate(Boolean cachePrivate) {
404+
this.cachePrivate = cachePrivate;
405+
}
406+
407+
public Boolean getProxyRevalidate() {
408+
return this.proxyRevalidate;
409+
}
410+
411+
public void setProxyRevalidate(Boolean proxyRevalidate) {
412+
this.proxyRevalidate = proxyRevalidate;
413+
}
414+
415+
public Long getStaleWhileRevalidate() {
416+
return this.staleWhileRevalidate;
417+
}
418+
419+
public void setStaleWhileRevalidate(Long staleWhileRevalidate) {
420+
this.staleWhileRevalidate = staleWhileRevalidate;
421+
}
422+
423+
public Long getStaleIfError() {
424+
return this.staleIfError;
425+
}
426+
427+
public void setStaleIfError(Long staleIfError) {
428+
this.staleIfError = staleIfError;
429+
}
430+
431+
public Long getsMaxAge() {
432+
return this.sMaxAge;
433+
}
434+
435+
public void setsMaxAge(Long sMaxAge) {
436+
this.sMaxAge = sMaxAge;
437+
}
438+
439+
static org.springframework.http.CacheControl createCacheControl(CacheControl cacheControlProperties) {
440+
org.springframework.http.CacheControl cacheControl;
441+
if (cacheControlProperties.getMaxAge() != null) {
442+
cacheControl = org.springframework.http.CacheControl.maxAge(cacheControlProperties.getMaxAge(), TimeUnit.SECONDS);
443+
}
444+
else if (Boolean.TRUE.equals(cacheControlProperties.getNoCache())) {
445+
cacheControl = org.springframework.http.CacheControl.noCache();
446+
}
447+
else if (Boolean.TRUE.equals(cacheControlProperties.getNoStore())) {
448+
cacheControl = org.springframework.http.CacheControl.noStore();
449+
}
450+
else {
451+
cacheControl = org.springframework.http.CacheControl.empty();
452+
}
453+
if (Boolean.TRUE.equals(cacheControlProperties.getMustRevalidate())) {
454+
cacheControl = cacheControl.mustRevalidate();
455+
}
456+
if (Boolean.TRUE.equals(cacheControlProperties.getNoTransform())) {
457+
cacheControl = cacheControl.noTransform();
458+
}
459+
if (Boolean.TRUE.equals(cacheControlProperties.getCachePublic())) {
460+
cacheControl = cacheControl.cachePublic();
461+
}
462+
if (Boolean.TRUE.equals(cacheControlProperties.getCachePrivate())) {
463+
cacheControl = cacheControl.cachePrivate();
464+
}
465+
if (Boolean.TRUE.equals(cacheControlProperties.getProxyRevalidate())) {
466+
cacheControl = cacheControl.proxyRevalidate();
467+
}
468+
if (cacheControlProperties.getStaleWhileRevalidate() != null) {
469+
cacheControl = cacheControl.staleWhileRevalidate(
470+
cacheControlProperties.getStaleWhileRevalidate(),
471+
TimeUnit.SECONDS);
472+
}
473+
if (cacheControlProperties.getStaleIfError() != null) {
474+
cacheControl = cacheControl.staleIfError(
475+
cacheControlProperties.getStaleIfError(),
476+
TimeUnit.SECONDS);
477+
}
478+
if (cacheControlProperties.getsMaxAge() != null) {
479+
cacheControl = cacheControl.sMaxAge(
480+
cacheControlProperties.getsMaxAge(),
481+
TimeUnit.SECONDS);
482+
}
483+
return cacheControl;
484+
}
485+
486+
487+
488+
489+
}
490+
491+
269492
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import org.springframework.format.Formatter;
7373
import org.springframework.format.FormatterRegistry;
7474
import org.springframework.format.datetime.DateFormatter;
75+
import org.springframework.http.CacheControl;
7576
import org.springframework.http.HttpHeaders;
7677
import org.springframework.http.MediaType;
7778
import org.springframework.http.converter.HttpMessageConverter;
@@ -132,6 +133,7 @@
132133
* @author Sébastien Deleuze
133134
* @author Eddú Meléndez
134135
* @author Stephane Nicoll
136+
* @author Kristine Jetzke
135137
*/
136138
@Configuration
137139
@ConditionalOnWebApplication(type = Type.SERVLET)
@@ -305,21 +307,21 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) {
305307
logger.debug("Default resource handling disabled");
306308
return;
307309
}
308-
Integer cachePeriod = this.resourceProperties.getCachePeriod();
310+
CacheControl cacheControl = this.resourceProperties.createCacheControl();
309311
if (!registry.hasMappingForPattern("/webjars/**")) {
310312
customizeResourceHandlerRegistration(
311313
registry.addResourceHandler("/webjars/**")
312314
.addResourceLocations(
313315
"classpath:/META-INF/resources/webjars/")
314-
.setCachePeriod(cachePeriod));
316+
.setCacheControl(cacheControl));
315317
}
316318
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
317319
if (!registry.hasMappingForPattern(staticPathPattern)) {
318320
customizeResourceHandlerRegistration(
319321
registry.addResourceHandler(staticPathPattern)
320322
.addResourceLocations(getResourceLocations(
321323
this.resourceProperties.getStaticLocations()))
322-
.setCachePeriod(cachePeriod));
324+
.setCacheControl(cacheControl));
323325
}
324326
}
325327

0 commit comments

Comments
 (0)