1616
1717package org .springframework .boot .autoconfigure .web ;
1818
19+ import java .util .concurrent .TimeUnit ;
20+
21+ import javax .annotation .PostConstruct ;
22+
1923import 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.
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 )
3138public 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}
0 commit comments