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 new file mode 100644 index 0000000000..235da4acf0 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java @@ -0,0 +1,50 @@ +/* + * 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; + } + +} 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 4ddf6b5a2b..f4fd6db2b9 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 @@ -38,6 +38,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 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.Configuration; import org.springframework.core.Ordered; @@ -114,6 +115,7 @@ public class WebMvcAutoConfiguration { } public static String DEFAULT_PREFIX = ""; + public static String DEFAULT_SUFFIX = ""; @Bean @@ -126,6 +128,7 @@ public class WebMvcAutoConfiguration { // on the classpath @Configuration @EnableWebMvc + @EnableConfigurationProperties(ResourceProperties.class) public static class WebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter { private static Log logger = LogFactory.getLog(WebMvcConfigurerAdapter.class); @@ -136,8 +139,8 @@ public class WebMvcAutoConfiguration { @Value("${spring.view.suffix:}") private String suffix = ""; - @Value("${spring.resources.cachePeriod:}") - private Integer cachePeriod; + @Autowired + private ResourceProperties resourceProperties = new ResourceProperties(); @Value("${spring.mvc.message-codes-resolver.format:}") private DefaultMessageCodesResolver.Format messageCodesResolverFormat = null; @@ -242,15 +245,21 @@ public class WebMvcAutoConfiguration { @Override 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/**")) { registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/") - .setCachePeriod(this.cachePeriod); + .setCachePeriod(cachePeriod); } if (!registry.hasMappingForPattern("/**")) { registry.addResourceHandler("/**") .addResourceLocations(RESOURCE_LOCATIONS) - .setCachePeriod(this.cachePeriod); + .setCachePeriod(cachePeriod); } } 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 56d848ef53..d55c705cb0 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 @@ -155,6 +155,19 @@ public class WebMvcAutoConfigurationTests { 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> mappingLocations = getMappingLocations(); + assertThat(mappingLocations.size(), equalTo(0)); + } + @Test public void noLocaleResolver() throws Exception { this.context = new AnnotationConfigEmbeddedWebApplicationContext(); @@ -195,7 +208,8 @@ public class WebMvcAutoConfigurationTests { HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); 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(); // formatting cs should use simple toString() assertThat(cs.convert(date, String.class), equalTo(date.toString())); @@ -205,13 +219,15 @@ public class WebMvcAutoConfigurationTests { public void overrideDateFormat() throws Exception { this.context = new AnnotationConfigEmbeddedWebApplicationContext(); // 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, WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); 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(); assertThat(cs.convert(date, String.class), equalTo("25*06*1988")); } @@ -245,17 +261,20 @@ public class WebMvcAutoConfigurationTests { @SuppressWarnings("unchecked") protected Map> getMappingLocations() throws IllegalAccessException { - SimpleUrlHandlerMapping mapping = (SimpleUrlHandlerMapping) this.context + HandlerMapping mapping = (HandlerMapping) this.context .getBean("resourceHandlerMapping"); - Field locationsField = ReflectionUtils.findField( - ResourceHttpRequestHandler.class, "locations"); - locationsField.setAccessible(true); Map> mappingLocations = new LinkedHashMap>(); - for (Map.Entry entry : mapping.getHandlerMap().entrySet()) { - ResourceHttpRequestHandler handler = (ResourceHttpRequestHandler) entry - .getValue(); - mappingLocations.put(entry.getKey(), - (List) locationsField.get(handler)); + if (mapping instanceof SimpleUrlHandlerMapping) { + Field locationsField = ReflectionUtils.findField( + ResourceHttpRequestHandler.class, "locations"); + locationsField.setAccessible(true); + for (Map.Entry entry : ((SimpleUrlHandlerMapping) mapping) + .getHandlerMap().entrySet()) { + ResourceHttpRequestHandler handler = (ResourceHttpRequestHandler) entry + .getValue(); + mappingLocations.put(entry.getKey(), + (List) locationsField.get(handler)); + } } return mappingLocations; } 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 85c2751fe4..c21d81c987 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -73,6 +73,7 @@ content into your application; rather pick only the properties that you need. spring.view.prefix= # MVC view prefix spring.view.suffix= # ... and suffix 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]) spring.thymeleaf.prefix=classpath:/templates/