Commit 1c0cce44 authored by Phillip Webb's avatar Phillip Webb

Add spring.resources.add-mappings property

Add `spring.resources.add-mappings` allowing users to configure if
resource mappings should be added or not.

Fixes gh-804
parent 4b51b6f9
/*
* Copyright 2012-2014 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.context.properties.ConfigurationProperties;
/**
* Properties used to configure resource handling.
*
* @author Phillip Webb
* @since 1.1.0
*/
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {
private Integer cachePeriod;
private boolean addMappings = true;
public Integer getCachePeriod() {
return this.cachePeriod;
}
public void setCachePeriod(Integer cachePeriod) {
this.cachePeriod = cachePeriod;
}
public boolean isAddMappings() {
return this.addMappings;
}
public void setAddMappings(boolean addMappings) {
this.addMappings = addMappings;
}
}
...@@ -38,6 +38,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; ...@@ -38,6 +38,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
...@@ -114,6 +115,7 @@ public class WebMvcAutoConfiguration { ...@@ -114,6 +115,7 @@ public class WebMvcAutoConfiguration {
} }
public static String DEFAULT_PREFIX = ""; public static String DEFAULT_PREFIX = "";
public static String DEFAULT_SUFFIX = ""; public static String DEFAULT_SUFFIX = "";
@Bean @Bean
...@@ -126,6 +128,7 @@ public class WebMvcAutoConfiguration { ...@@ -126,6 +128,7 @@ public class WebMvcAutoConfiguration {
// on the classpath // on the classpath
@Configuration @Configuration
@EnableWebMvc @EnableWebMvc
@EnableConfigurationProperties(ResourceProperties.class)
public static class WebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter { public static class WebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter {
private static Log logger = LogFactory.getLog(WebMvcConfigurerAdapter.class); private static Log logger = LogFactory.getLog(WebMvcConfigurerAdapter.class);
...@@ -136,8 +139,8 @@ public class WebMvcAutoConfiguration { ...@@ -136,8 +139,8 @@ public class WebMvcAutoConfiguration {
@Value("${spring.view.suffix:}") @Value("${spring.view.suffix:}")
private String suffix = ""; private String suffix = "";
@Value("${spring.resources.cachePeriod:}") @Autowired
private Integer cachePeriod; private ResourceProperties resourceProperties = new ResourceProperties();
@Value("${spring.mvc.message-codes-resolver.format:}") @Value("${spring.mvc.message-codes-resolver.format:}")
private DefaultMessageCodesResolver.Format messageCodesResolverFormat = null; private DefaultMessageCodesResolver.Format messageCodesResolverFormat = null;
...@@ -242,15 +245,21 @@ public class WebMvcAutoConfiguration { ...@@ -242,15 +245,21 @@ public class WebMvcAutoConfiguration {
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Integer cachePeriod = this.resourceProperties.getCachePeriod();
if (!registry.hasMappingForPattern("/webjars/**")) { if (!registry.hasMappingForPattern("/webjars/**")) {
registry.addResourceHandler("/webjars/**") registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/") .addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(this.cachePeriod); .setCachePeriod(cachePeriod);
} }
if (!registry.hasMappingForPattern("/**")) { if (!registry.hasMappingForPattern("/**")) {
registry.addResourceHandler("/**") registry.addResourceHandler("/**")
.addResourceLocations(RESOURCE_LOCATIONS) .addResourceLocations(RESOURCE_LOCATIONS)
.setCachePeriod(this.cachePeriod); .setCachePeriod(cachePeriod);
} }
} }
......
...@@ -155,6 +155,19 @@ public class WebMvcAutoConfigurationTests { ...@@ -155,6 +155,19 @@ public class WebMvcAutoConfigurationTests {
equalTo((Resource) new ClassPathResource("/foo/"))); equalTo((Resource) new ClassPathResource("/foo/")));
} }
@Test
public void resourceHandlerMappingDisabled() throws Exception {
this.context = new AnnotationConfigEmbeddedWebApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.resources.add-mappings:false");
this.context.register(Config.class, WebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
Map<String, List<Resource>> mappingLocations = getMappingLocations();
assertThat(mappingLocations.size(), equalTo(0));
}
@Test @Test
public void noLocaleResolver() throws Exception { public void noLocaleResolver() throws Exception {
this.context = new AnnotationConfigEmbeddedWebApplicationContext(); this.context = new AnnotationConfigEmbeddedWebApplicationContext();
...@@ -195,7 +208,8 @@ public class WebMvcAutoConfigurationTests { ...@@ -195,7 +208,8 @@ public class WebMvcAutoConfigurationTests {
HttpMessageConvertersAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
FormattingConversionService cs = this.context.getBean(FormattingConversionService.class); FormattingConversionService cs = this.context
.getBean(FormattingConversionService.class);
Date date = new DateTime(1988, 6, 25, 20, 30).toDate(); Date date = new DateTime(1988, 6, 25, 20, 30).toDate();
// formatting cs should use simple toString() // formatting cs should use simple toString()
assertThat(cs.convert(date, String.class), equalTo(date.toString())); assertThat(cs.convert(date, String.class), equalTo(date.toString()));
...@@ -205,13 +219,15 @@ public class WebMvcAutoConfigurationTests { ...@@ -205,13 +219,15 @@ public class WebMvcAutoConfigurationTests {
public void overrideDateFormat() throws Exception { public void overrideDateFormat() throws Exception {
this.context = new AnnotationConfigEmbeddedWebApplicationContext(); this.context = new AnnotationConfigEmbeddedWebApplicationContext();
// set fixed date format // set fixed date format
EnvironmentTestUtils.addEnvironment(this.context, "spring.mvc.date-format:dd*MM*yyyy"); EnvironmentTestUtils.addEnvironment(this.context,
"spring.mvc.date-format:dd*MM*yyyy");
this.context.register(AllResources.class, Config.class, this.context.register(AllResources.class, Config.class,
WebMvcAutoConfiguration.class, WebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
FormattingConversionService cs = this.context.getBean(FormattingConversionService.class); FormattingConversionService cs = this.context
.getBean(FormattingConversionService.class);
Date date = new DateTime(1988, 6, 25, 20, 30).toDate(); Date date = new DateTime(1988, 6, 25, 20, 30).toDate();
assertThat(cs.convert(date, String.class), equalTo("25*06*1988")); assertThat(cs.convert(date, String.class), equalTo("25*06*1988"));
} }
...@@ -245,18 +261,21 @@ public class WebMvcAutoConfigurationTests { ...@@ -245,18 +261,21 @@ public class WebMvcAutoConfigurationTests {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected Map<String, List<Resource>> getMappingLocations() protected Map<String, List<Resource>> getMappingLocations()
throws IllegalAccessException { throws IllegalAccessException {
SimpleUrlHandlerMapping mapping = (SimpleUrlHandlerMapping) this.context HandlerMapping mapping = (HandlerMapping) this.context
.getBean("resourceHandlerMapping"); .getBean("resourceHandlerMapping");
Map<String, List<Resource>> mappingLocations = new LinkedHashMap<String, List<Resource>>();
if (mapping instanceof SimpleUrlHandlerMapping) {
Field locationsField = ReflectionUtils.findField( Field locationsField = ReflectionUtils.findField(
ResourceHttpRequestHandler.class, "locations"); ResourceHttpRequestHandler.class, "locations");
locationsField.setAccessible(true); locationsField.setAccessible(true);
Map<String, List<Resource>> mappingLocations = new LinkedHashMap<String, List<Resource>>(); for (Map.Entry<String, Object> entry : ((SimpleUrlHandlerMapping) mapping)
for (Map.Entry<String, Object> entry : mapping.getHandlerMap().entrySet()) { .getHandlerMap().entrySet()) {
ResourceHttpRequestHandler handler = (ResourceHttpRequestHandler) entry ResourceHttpRequestHandler handler = (ResourceHttpRequestHandler) entry
.getValue(); .getValue();
mappingLocations.put(entry.getKey(), mappingLocations.put(entry.getKey(),
(List<Resource>) locationsField.get(handler)); (List<Resource>) locationsField.get(handler));
} }
}
return mappingLocations; return mappingLocations;
} }
......
...@@ -73,6 +73,7 @@ content into your application; rather pick only the properties that you need. ...@@ -73,6 +73,7 @@ content into your application; rather pick only the properties that you need.
spring.view.prefix= # MVC view prefix spring.view.prefix= # MVC view prefix
spring.view.suffix= # ... and suffix spring.view.suffix= # ... and suffix
spring.resources.cache-period= # cache timeouts in headers sent to browser spring.resources.cache-period= # cache timeouts in headers sent to browser
spring.resources.add-mappings=true # if default mappings should be added
# THYMELEAF ({sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[ThymeleafAutoConfiguration]) # THYMELEAF ({sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[ThymeleafAutoConfiguration])
spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.prefix=classpath:/templates/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment