From 1466169dc087bbff62124251c4255abde5f8f642 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 20 Aug 2015 10:33:04 +0200 Subject: [PATCH] Register ResourceUrlEncodingFilter only if necessary Previously, `ResourceUrlEncodingFilter` was registered even if the resource chain handling was disabled (which is the default). We now take care of registering it only if the resource chain handling is enabled. Closes gh-3353 --- .../thymeleaf/ThymeleafAutoConfiguration.java | 2 + .../velocity/VelocityAutoConfiguration.java | 2 + .../ConditionalOnEnabledResourceChain.java | 39 ++++++++ .../web/OnEnabledResourceChainCondition.java | 47 ++++++++++ .../autoconfigure/web/ResourceProperties.java | 4 +- .../web/WebMvcAutoConfiguration.java | 4 +- .../ThymeleafAutoConfigurationTests.java | 12 ++- .../VelocityAutoConfigurationTests.java | 10 +- ...onditionalOnEnabledResourceChainTests.java | 92 +++++++++++++++++++ 9 files changed, 206 insertions(+), 6 deletions(-) create mode 100644 spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChain.java create mode 100644 spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/OnEnabledResourceChainCondition.java create mode 100644 spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChainTests.java 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 3c7f4080c96..385de509558 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 @@ -33,6 +33,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.template.TemplateLocation; +import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain; import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ApplicationContext; @@ -232,6 +233,7 @@ public class ThymeleafAutoConfiguration { @Bean @ConditionalOnMissingBean + @ConditionalOnEnabledResourceChain public ResourceUrlEncodingFilter resourceUrlEncodingFilter() { return new ResourceUrlEncodingFilter(); } 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 b9bc294021b..e9ed1172fdf 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 @@ -33,6 +33,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebAppli import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.template.TemplateLocation; +import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain; import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.view.velocity.EmbeddedVelocityViewResolver; @@ -137,6 +138,7 @@ public class VelocityAutoConfiguration { @Bean @ConditionalOnMissingBean + @ConditionalOnEnabledResourceChain public ResourceUrlEncodingFilter resourceUrlEncodingFilter() { return new ResourceUrlEncodingFilter(); } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChain.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChain.java new file mode 100644 index 00000000000..079cd985fdd --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChain.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-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.boot.autoconfigure.web; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Conditional; + +/** + * {@link Conditional} that checks whether or not the Spring resource handling chain is + * enabled. Matches if {@link ResourceProperties.Chain#getEnabled()} is {@code true}. + * + * @author Stephane Nicoll + * @since 1.3.0 + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Conditional(OnEnabledResourceChainCondition.class) +public @interface ConditionalOnEnabledResourceChain { +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/OnEnabledResourceChainCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/OnEnabledResourceChainCondition.java new file mode 100644 index 00000000000..83e0da38b3e --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/OnEnabledResourceChainCondition.java @@ -0,0 +1,47 @@ +/* + * Copyright 2012-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.boot.autoconfigure.web; + +import org.springframework.boot.autoconfigure.condition.ConditionOutcome; +import org.springframework.boot.autoconfigure.condition.SpringBootCondition; +import org.springframework.boot.bind.PropertySourcesPropertyValues; +import org.springframework.boot.bind.RelaxedDataBinder; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.type.AnnotatedTypeMetadata; + +/** + * {@link Condition} that checks whether or not the Spring resource handling chain is + * enabled. + * + * @author Stephane Nicoll + */ +class OnEnabledResourceChainCondition extends SpringBootCondition { + + @Override + public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { + ConfigurableEnvironment environment = (ConfigurableEnvironment) context.getEnvironment(); + ResourceProperties resourceProperties = new ResourceProperties(); + RelaxedDataBinder binder = new RelaxedDataBinder(resourceProperties, "spring.resources"); + binder.bind(new PropertySourcesPropertyValues(environment.getPropertySources())); + + Boolean match = resourceProperties.getChain().getEnabled(); + return new ConditionOutcome(match, "Resource chain is " + (match ? "enabled" : "disabled" + ")")); + } + +} 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 d0278cd1177..deb2114f1f0 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 @@ -173,7 +173,9 @@ public class ResourceProperties implements ResourceLoaderAware { private final Strategy strategy = new Strategy(); public Boolean getEnabled() { - return this.enabled; + return Boolean.TRUE.equals(this.enabled) + || getStrategy().getFixed().isEnabled() + || getStrategy().getContent().isEnabled(); } public void setEnabled(boolean enabled) { 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 4046d089eec..42aa4d0eb80 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 @@ -256,9 +256,7 @@ public class WebMvcAutoConfiguration { private void registerResourceChain(ResourceHandlerRegistration registration) { ResourceProperties.Chain properties = this.resourceProperties.getChain(); - if (Boolean.TRUE.equals(properties.getEnabled()) - || properties.getStrategy().getFixed().isEnabled() - || properties.getStrategy().getContent().isEnabled()) { + if (properties.getEnabled()) { configureResourceChain(properties, registration.resourceChain(properties.isCache())); } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfigurationTests.java index 761680083fd..57acc8da3cb 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfigurationTests.java @@ -196,10 +196,20 @@ public class ThymeleafAutoConfigurationTests { } @Test - public void registerResourceHandlingFilter() throws Exception { + public void registerResourceHandlingFilterDisabledByDefault() throws Exception { this.context.register(ThymeleafAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); this.context.refresh(); + assertEquals(0, this.context.getBeansOfType(ResourceUrlEncodingFilter.class).size()); + } + + @Test + public void registerResourceHandlingFilterOnlyIfResourceChainIsEnabled() throws Exception { + this.context.register(ThymeleafAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.resources.chain.enabled:true"); + this.context.refresh(); assertNotNull(this.context.getBean(ResourceUrlEncodingFilter.class)); } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/velocity/VelocityAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/velocity/VelocityAutoConfigurationTests.java index 0949d649a81..6738ca12c67 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/velocity/VelocityAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/velocity/VelocityAutoConfigurationTests.java @@ -49,6 +49,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; @@ -56,6 +57,7 @@ import static org.junit.Assert.assertThat; * Tests for {@link VelocityAutoConfiguration}. * * @author Andy Wilkinson + * @author Stephane Nicoll */ public class VelocityAutoConfigurationTests { @@ -189,8 +191,14 @@ public class VelocityAutoConfigurationTests { } @Test - public void registerResourceHandlingFilter() throws Exception { + public void registerResourceHandlingFilterDisabledByDefault() throws Exception { registerAndRefreshContext(); + assertEquals(0, this.context.getBeansOfType(ResourceUrlEncodingFilter.class).size()); + } + + @Test + public void registerResourceHandlingFilterOnlyIfResourceChainIsEnabled() throws Exception { + registerAndRefreshContext("spring.resources.chain.enabled:true"); assertNotNull(this.context.getBean(ResourceUrlEncodingFilter.class)); } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChainTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChainTests.java new file mode 100644 index 00000000000..e097d96590c --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChainTests.java @@ -0,0 +1,92 @@ +/* + * Copyright 2012-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.boot.autoconfigure.web; + +import org.junit.After; +import org.junit.Test; + +import org.springframework.boot.test.EnvironmentTestUtils; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests for {@link ConditionalOnEnabledResourceChain}. + * + * @author Stephane Nicoll + */ +public class ConditionalOnEnabledResourceChainTests { + + private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + + @After + public void closeContext() { + this.context.close(); + } + + @Test + public void disabledByDefault() { + load(); + assertFalse(this.context.containsBean("foo")); + } + + @Test + public void disabledExplicitly() { + load("spring.resources.chain.enabled:false"); + assertFalse(this.context.containsBean("foo")); + } + + @Test + public void enabledViaMainEnabledFlag() { + load("spring.resources.chain.enabled:true"); + assertTrue(this.context.containsBean("foo")); + } + + @Test + public void enabledViaFixedStrategyFlag() { + load("spring.resources.chain.strategy.fixed.enabled:true"); + assertTrue(this.context.containsBean("foo")); + } + + @Test + public void enabledViaContentStrategyFlag() { + load("spring.resources.chain.strategy.content.enabled:true"); + assertTrue(this.context.containsBean("foo")); + } + + + private void load(String... environment) { + this.context.register(Config.class); + EnvironmentTestUtils.addEnvironment(this.context, environment); + this.context.refresh(); + } + + @Configuration + static class Config { + + @Bean + @ConditionalOnEnabledResourceChain + public String foo() { + return "foo"; + } + + } + +}