From 5f3364326b503ad1f4d784813df0a04c4b7d4dba Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Thu, 1 Aug 2019 09:14:10 -0700 Subject: [PATCH] Configure interceptors for WelcomePageHandlerMapping Fixes gh-16309 --- .../web/servlet/WebMvcAutoConfiguration.java | 89 ++++++++++--------- .../servlet/WelcomePageIntegrationTests.java | 76 ++++++++++++++++ .../src/test/resources/public/custom.css | 0 .../resources/templates/thymeleaf/index.html | 10 +++ 4 files changed, 134 insertions(+), 41 deletions(-) create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WelcomePageIntegrationTests.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/resources/public/custom.css create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/resources/templates/thymeleaf/index.html diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java index c48be3feb1..592168862e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java @@ -167,13 +167,20 @@ public class WebMvcAutoConfiguration { return new OrderedFormContentFilter(); } + static String[] getResourceLocations(String[] staticLocations) { + String[] locations = new String[staticLocations.length + SERVLET_LOCATIONS.length]; + System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length); + System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length, SERVLET_LOCATIONS.length); + return locations; + } + // Defined as a nested config to ensure WebMvcConfigurer is not read when not // on the classpath @Configuration @Import(EnableWebMvcConfiguration.class) @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class }) @Order(0) - public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware { + public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer { private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class); @@ -187,8 +194,6 @@ public class WebMvcAutoConfiguration { final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer; - private ResourceLoader resourceLoader; - public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider messageConvertersProvider, ObjectProvider resourceHandlerRegistrationCustomizerProvider) { @@ -199,11 +204,6 @@ public class WebMvcAutoConfiguration { this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable(); } - @Override - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; - } - @Override public void configureMessageConverters(List> converters) { this.messageConvertersProvider @@ -338,37 +338,6 @@ public class WebMvcAutoConfiguration { return (cachePeriod != null) ? (int) cachePeriod.getSeconds() : null; } - @Bean - public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext) { - return new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), - applicationContext, getWelcomePage(), this.mvcProperties.getStaticPathPattern()); - } - - static String[] getResourceLocations(String[] staticLocations) { - String[] locations = new String[staticLocations.length + SERVLET_LOCATIONS.length]; - System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length); - System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length, SERVLET_LOCATIONS.length); - return locations; - } - - private Optional getWelcomePage() { - String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations()); - return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst(); - } - - private Resource getIndexHtml(String location) { - return this.resourceLoader.getResource(location + "index.html"); - } - - private boolean isReadable(Resource resource) { - try { - return resource.exists() && (resource.getURL() != null); - } - catch (Exception ex) { - return false; - } - } - private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) { if (this.resourceHandlerRegistrationCustomizer != null) { this.resourceHandlerRegistrationCustomizer.customize(registration); @@ -430,7 +399,9 @@ public class WebMvcAutoConfiguration { * Configuration equivalent to {@code @EnableWebMvc}. */ @Configuration - public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration { + public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware { + + private final ResourceProperties resourceProperties; private final WebMvcProperties mvcProperties; @@ -438,8 +409,12 @@ public class WebMvcAutoConfiguration { private final WebMvcRegistrations mvcRegistrations; - public EnableWebMvcConfiguration(ObjectProvider mvcPropertiesProvider, + private ResourceLoader resourceLoader; + + public EnableWebMvcConfiguration(ResourceProperties resourceProperties, + ObjectProvider mvcPropertiesProvider, ObjectProvider mvcRegistrationsProvider, ListableBeanFactory beanFactory) { + this.resourceProperties = resourceProperties; this.mvcProperties = mvcPropertiesProvider.getIfAvailable(); this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique(); this.beanFactory = beanFactory; @@ -470,6 +445,33 @@ public class WebMvcAutoConfiguration { return super.requestMappingHandlerMapping(); } + @Bean + public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext) { + WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping( + new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(), + this.mvcProperties.getStaticPathPattern()); + welcomePageHandlerMapping.setInterceptors(getInterceptors()); + return welcomePageHandlerMapping; + } + + private Optional getWelcomePage() { + String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations()); + return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst(); + } + + private Resource getIndexHtml(String location) { + return this.resourceLoader.getResource(location + "index.html"); + } + + private boolean isReadable(Resource resource) { + try { + return resource.exists() && (resource.getURL() != null); + } + catch (Exception ex) { + return false; + } + } + @Bean @Override public FormattingConversionService mvcConversionService() { @@ -543,6 +545,11 @@ public class WebMvcAutoConfiguration { return manager; } + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + } @Configuration diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WelcomePageIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WelcomePageIntegrationTests.java new file mode 100644 index 0000000000..ea7eb22ed4 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WelcomePageIntegrationTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2012-2019 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 + * + * https://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.servlet; + +import java.net.URI; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; +import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for the welcome page. + * + * @author Madhura Bhave + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = { "spring.resources.chain.strategy.content.enabled=true", + "spring.thymeleaf.prefix=classpath:/templates/thymeleaf/" }) +public class WelcomePageIntegrationTests { + + @LocalServerPort + private int port; + + private TestRestTemplate template = new TestRestTemplate(); + + @Test + public void contentStrategyWithWelcomePage() throws Exception { + RequestEntity entity = RequestEntity.get(new URI("http://localhost:" + this.port + "/")) + .header("Accept", MediaType.ALL.toString()).build(); + ResponseEntity content = this.template.exchange(entity, String.class); + assertThat(content.getBody()).contains("/custom-"); + } + + @Configuration + @Import({ PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, + DispatcherServletAutoConfiguration.class, ThymeleafAutoConfiguration.class }) + public static class TestConfiguration { + + public static void main(String[] args) { + new SpringApplicationBuilder(TestConfiguration.class).run(args); + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/public/custom.css b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/public/custom.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/templates/thymeleaf/index.html b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/templates/thymeleaf/index.html new file mode 100644 index 0000000000..13a28612ca --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/templates/thymeleaf/index.html @@ -0,0 +1,10 @@ + + + + Test Thymeleaf + + + + + +