From a6ccb4a6e02c4216e31023e4d719b1e3549a23c7 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Sun, 28 Jun 2015 06:20:33 -0700 Subject: [PATCH] Polish Polish resource handling chain support. Make sure that the chain is enabled automatically if at least one strategy is enabled. See gh-1604 --- .../thymeleaf/ThymeleafAutoConfiguration.java | 1 + .../velocity/VelocityAutoConfiguration.java | 1 + .../autoconfigure/web/ResourceProperties.java | 28 +++++++--- .../web/WebMvcAutoConfiguration.java | 3 +- .../web/WebMvcAutoConfigurationTests.java | 56 ++++++++++++++----- .../appendix-application-properties.adoc | 2 +- .../main/asciidoc/spring-boot-features.adoc | 5 +- 7 files changed, 71 insertions(+), 25 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java index d91ce5c73d..a390a70fab 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java @@ -57,6 +57,7 @@ import com.github.mxab.thymeleaf.extras.dataattribute.dialect.DataAttributeDiale * @author Dave Syer * @author Andy Wilkinson * @author Stephane Nicoll + * @author Brian Clozel */ @Configuration @EnableConfigurationProperties(ThymeleafProperties.class) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/velocity/VelocityAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/velocity/VelocityAutoConfiguration.java index 134553c286..1b95e95014 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/velocity/VelocityAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/velocity/VelocityAutoConfiguration.java @@ -51,6 +51,7 @@ import org.springframework.web.servlet.view.velocity.VelocityViewResolver; * {@link EnableAutoConfiguration Auto-configuration} for Velocity. * * @author Andy Wilkinson + * @author Brian Clozel * @since 1.1.0 */ @Configuration diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java index 64a4b069b1..98a30adfde 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.web; +import javax.annotation.PostConstruct; + import org.springframework.boot.context.properties.ConfigurationProperties; /** @@ -40,6 +42,15 @@ public class ResourceProperties { private final Chain chain = new Chain(); + + @PostConstruct + public void setUpDefaults() { + if (this.chain.enabled == null && (this.chain.strategy.content.enabled + || this.chain.strategy.fixed.enabled)) { + this.chain.enabled = true; + } + } + public Integer getCachePeriod() { return this.cachePeriod; } @@ -66,9 +77,10 @@ public class ResourceProperties { public static class Chain { /** - * Enable the Spring Resource Handling chain. + * Enable the Spring Resource Handling chain. Disabled by default unless + * at least one strategy has been enabled. */ - private boolean enabled = false; + private Boolean enabled; /** * Enable caching in the Resource chain. @@ -80,9 +92,9 @@ public class ResourceProperties { */ private boolean html5AppCache = false; - private Strategy strategy = new Strategy(); + private final Strategy strategy = new Strategy(); - public boolean isEnabled() { + public Boolean getEnabled() { return enabled; } @@ -116,9 +128,9 @@ public class ResourceProperties { */ public static class Strategy { - private Fixed fixed = new Fixed(); + private final Fixed fixed = new Fixed(); - private Content content = new Content(); + private final Content content = new Content(); public Fixed getFixed() { return fixed; @@ -137,7 +149,7 @@ public class ResourceProperties { /** * Enable the content Version Strategy. */ - private boolean enabled = false; + private boolean enabled; /** * Comma-separated list of patterns to apply to the Version Strategy. @@ -169,7 +181,7 @@ public class ResourceProperties { /** * Enable the fixed Version Strategy. */ - private boolean enabled = false; + private boolean enabled; /** * Comma-separated list of patterns to apply to the Version Strategy. diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java index e12d5f7297..2b44dd0bcc 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java @@ -55,6 +55,7 @@ import org.springframework.format.Formatter; import org.springframework.format.FormatterRegistry; import org.springframework.format.datetime.DateFormatter; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.validation.DefaultMessageCodesResolver; import org.springframework.validation.MessageCodesResolver; @@ -274,7 +275,7 @@ public class WebMvcAutoConfiguration { private void registerResourceChain(ResourceHandlerRegistration registration) { ResourceProperties.Chain chainProperties = this.resourceProperties.getChain(); - if (chainProperties.isEnabled()) { + if (ObjectUtils.nullSafeEquals(chainProperties.getEnabled(), Boolean.TRUE)) { ResourceChainRegistration chain = registration.resourceChain(chainProperties.isCache()); boolean hasFixedVersionConfigured = chainProperties.getStrategy().getFixed().isEnabled(); boolean hasContentVersionConfigured = chainProperties.getStrategy().getContent().isEnabled(); diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java index 07b510543c..72359abc91 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java @@ -169,12 +169,8 @@ public class WebMvcAutoConfigurationTests { @Test public void resourceHandlerChainEnabled() throws Exception { - this.context = new AnnotationConfigEmbeddedWebApplicationContext(); - EnvironmentTestUtils.addEnvironment(this.context, "spring.resources.chain.enabled:true"); - this.context.register(Config.class, WebMvcAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class); - this.context.refresh(); + load("spring.resources.chain.enabled:true"); + assertThat(getResourceResolvers("/webjars/**").size(), equalTo(2)); assertThat(getResourceTransformers("/webjars/**").size(), equalTo(1)); assertThat(getResourceResolvers("/**").size(), equalTo(2)); @@ -185,21 +181,55 @@ public class WebMvcAutoConfigurationTests { assertThat(getResourceTransformers("/**"), contains(instanceOf(CachingResourceTransformer.class))); } + @Test + public void resourceHandlerFixedStrategyEnabled() throws Exception { + load("spring.resources.chain.strategy.fixed.enabled:true", + "spring.resources.chain.strategy.fixed.version:test", + "spring.resources.chain.strategy.fixed.paths:/**/*.js"); + + assertThat(getResourceResolvers("/webjars/**").size(), equalTo(3)); + assertThat(getResourceTransformers("/webjars/**").size(), equalTo(2)); + assertThat(getResourceResolvers("/**").size(), equalTo(3)); + assertThat(getResourceTransformers("/**").size(), equalTo(2)); + + assertThat(getResourceResolvers("/**"), contains(instanceOf(CachingResourceResolver.class), + instanceOf(VersionResourceResolver.class), + instanceOf(PathResourceResolver.class))); + assertThat(getResourceTransformers("/**"), contains(instanceOf(CachingResourceTransformer.class), + instanceOf(CssLinkResourceTransformer.class))); + VersionResourceResolver resolver = (VersionResourceResolver) getResourceResolvers("/**").get(1); + assertThat(resolver.getStrategyMap().get("/**/*.js"), instanceOf(FixedVersionStrategy.class)); + } + + @Test + public void resourceHandlerContentStrategyEnabled() throws Exception { + load("spring.resources.chain.strategy.content.enabled:true", + "spring.resources.chain.strategy.content.paths:/**,/*.png"); + + assertThat(getResourceResolvers("/webjars/**").size(), equalTo(3)); + assertThat(getResourceTransformers("/webjars/**").size(), equalTo(2)); + assertThat(getResourceResolvers("/**").size(), equalTo(3)); + assertThat(getResourceTransformers("/**").size(), equalTo(2)); + + assertThat(getResourceResolvers("/**"), contains(instanceOf(CachingResourceResolver.class), + instanceOf(VersionResourceResolver.class), + instanceOf(PathResourceResolver.class))); + assertThat(getResourceTransformers("/**"), contains(instanceOf(CachingResourceTransformer.class), + instanceOf(CssLinkResourceTransformer.class))); + VersionResourceResolver resolver = (VersionResourceResolver) getResourceResolvers("/**").get(1); + assertThat(resolver.getStrategyMap().get("/*.png"), instanceOf(ContentVersionStrategy.class)); + } + @Test public void resourceHandlerChainCustomized() throws Exception { - this.context = new AnnotationConfigEmbeddedWebApplicationContext(); - EnvironmentTestUtils.addEnvironment(this.context, - "spring.resources.chain.enabled:true", "spring.resources.chain.cache:false", + load("spring.resources.chain.enabled:true", "spring.resources.chain.cache:false", "spring.resources.chain.strategy.content.enabled:true", "spring.resources.chain.strategy.content.paths:/**,/*.png", "spring.resources.chain.strategy.fixed.enabled:true", "spring.resources.chain.strategy.fixed.version:test", "spring.resources.chain.strategy.fixed.paths:/**/*.js", "spring.resources.chain.html5AppCache:true"); - this.context.register(Config.class, WebMvcAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class); - this.context.refresh(); + assertThat(getResourceResolvers("/webjars/**").size(), equalTo(2)); assertThat(getResourceTransformers("/webjars/**").size(), equalTo(2)); assertThat(getResourceResolvers("/**").size(), equalTo(2)); diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 4738d18eb4..580a4e3e45 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -129,7 +129,7 @@ content into your application; rather pick only the properties that you need. # SPRING RESOURCES HANDLING ({sc-spring-boot-autoconfigure}/web/ResourceProperties.{sc-ext}[ResourceProperties]) spring.resources.cache-period= # cache timeouts in headers sent to browser spring.resources.add-mappings=true # if default mappings should be added - spring.resources.chain.enabled=false # enable the Spring Resource Handling chain + spring.resources.chain.enabled=false # enable the Spring Resource Handling chain (enabled automatically if at least a strategy is enabled) spring.resources.chain.cache=false # enable in-memory caching of resource resolution spring.resources.chain.html5AppCache=false # enable HTML5 appcache manifest rewriting spring.resources.chain.strategy.content.enabled=false # enable a content version strategy diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index cc605e54ec..e53095a316 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -1193,7 +1193,6 @@ for all static resources, effectively adding a content hash in URLs, such as [source,properties,indent=0,subs="verbatim,quotes,attributes"] ---- - spring.resources.chain.enabled=true spring.resources.chain.strategy.content.enabled=true spring.resources.chain.strategy.content.paths=/** ---- @@ -1210,7 +1209,6 @@ A "fixed" strategy will add a static version string in the URL, without changing [source,properties,indent=0,subs="verbatim,quotes,attributes"] ---- - spring.resources.chain.enabled=true spring.resources.chain.strategy.content.enabled=true spring.resources.chain.strategy.content.paths=/** spring.resources.chain.strategy.fixed.enabled=true @@ -1225,9 +1223,12 @@ the content one ` See {sc-spring-boot-autoconfigure}/web/ResourceProperties.{sc-ext}[`ResourceProperties`] for more of the supported options. +[TIP] +==== This feature has been thoroughly described in a dedicated https://spring.io/blog/2014/07/24/spring-framework-4-1-handling-static-web-resources[blog post] and in Spring Framework's {spring-reference}/#mvc-config-static-resources[reference documentation]. +==== [[boot-features-spring-mvc-template-engines]]