Skip to content

Commit 5f33643

Browse files
committed
Configure interceptors for WelcomePageHandlerMapping
Fixes gh-16309
1 parent f2fd169 commit 5f33643

File tree

4 files changed

+134
-41
lines changed

4 files changed

+134
-41
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,20 @@ public OrderedFormContentFilter formContentFilter() {
167167
return new OrderedFormContentFilter();
168168
}
169169

170+
static String[] getResourceLocations(String[] staticLocations) {
171+
String[] locations = new String[staticLocations.length + SERVLET_LOCATIONS.length];
172+
System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length);
173+
System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length, SERVLET_LOCATIONS.length);
174+
return locations;
175+
}
176+
170177
// Defined as a nested config to ensure WebMvcConfigurer is not read when not
171178
// on the classpath
172179
@Configuration
173180
@Import(EnableWebMvcConfiguration.class)
174181
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
175182
@Order(0)
176-
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware {
183+
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
177184

178185
private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
179186

@@ -187,8 +194,6 @@ public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer,
187194

188195
final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
189196

190-
private ResourceLoader resourceLoader;
191-
192197
public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties,
193198
ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider,
194199
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) {
@@ -199,11 +204,6 @@ public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, Web
199204
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
200205
}
201206

202-
@Override
203-
public void setResourceLoader(ResourceLoader resourceLoader) {
204-
this.resourceLoader = resourceLoader;
205-
}
206-
207207
@Override
208208
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
209209
this.messageConvertersProvider
@@ -338,37 +338,6 @@ private Integer getSeconds(Duration cachePeriod) {
338338
return (cachePeriod != null) ? (int) cachePeriod.getSeconds() : null;
339339
}
340340

341-
@Bean
342-
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext) {
343-
return new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext),
344-
applicationContext, getWelcomePage(), this.mvcProperties.getStaticPathPattern());
345-
}
346-
347-
static String[] getResourceLocations(String[] staticLocations) {
348-
String[] locations = new String[staticLocations.length + SERVLET_LOCATIONS.length];
349-
System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length);
350-
System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length, SERVLET_LOCATIONS.length);
351-
return locations;
352-
}
353-
354-
private Optional<Resource> getWelcomePage() {
355-
String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
356-
return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
357-
}
358-
359-
private Resource getIndexHtml(String location) {
360-
return this.resourceLoader.getResource(location + "index.html");
361-
}
362-
363-
private boolean isReadable(Resource resource) {
364-
try {
365-
return resource.exists() && (resource.getURL() != null);
366-
}
367-
catch (Exception ex) {
368-
return false;
369-
}
370-
}
371-
372341
private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) {
373342
if (this.resourceHandlerRegistrationCustomizer != null) {
374343
this.resourceHandlerRegistrationCustomizer.customize(registration);
@@ -430,16 +399,22 @@ private List<Resource> resolveFaviconLocations() {
430399
* Configuration equivalent to {@code @EnableWebMvc}.
431400
*/
432401
@Configuration
433-
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
402+
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
403+
404+
private final ResourceProperties resourceProperties;
434405

435406
private final WebMvcProperties mvcProperties;
436407

437408
private final ListableBeanFactory beanFactory;
438409

439410
private final WebMvcRegistrations mvcRegistrations;
440411

441-
public EnableWebMvcConfiguration(ObjectProvider<WebMvcProperties> mvcPropertiesProvider,
412+
private ResourceLoader resourceLoader;
413+
414+
public EnableWebMvcConfiguration(ResourceProperties resourceProperties,
415+
ObjectProvider<WebMvcProperties> mvcPropertiesProvider,
442416
ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider, ListableBeanFactory beanFactory) {
417+
this.resourceProperties = resourceProperties;
443418
this.mvcProperties = mvcPropertiesProvider.getIfAvailable();
444419
this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
445420
this.beanFactory = beanFactory;
@@ -470,6 +445,33 @@ public RequestMappingHandlerMapping requestMappingHandlerMapping() {
470445
return super.requestMappingHandlerMapping();
471446
}
472447

448+
@Bean
449+
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext) {
450+
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
451+
new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
452+
this.mvcProperties.getStaticPathPattern());
453+
welcomePageHandlerMapping.setInterceptors(getInterceptors());
454+
return welcomePageHandlerMapping;
455+
}
456+
457+
private Optional<Resource> getWelcomePage() {
458+
String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
459+
return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
460+
}
461+
462+
private Resource getIndexHtml(String location) {
463+
return this.resourceLoader.getResource(location + "index.html");
464+
}
465+
466+
private boolean isReadable(Resource resource) {
467+
try {
468+
return resource.exists() && (resource.getURL() != null);
469+
}
470+
catch (Exception ex) {
471+
return false;
472+
}
473+
}
474+
473475
@Bean
474476
@Override
475477
public FormattingConversionService mvcConversionService() {
@@ -543,6 +545,11 @@ public ContentNegotiationManager mvcContentNegotiationManager() {
543545
return manager;
544546
}
545547

548+
@Override
549+
public void setResourceLoader(ResourceLoader resourceLoader) {
550+
this.resourceLoader = resourceLoader;
551+
}
552+
546553
}
547554

548555
@Configuration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.web.servlet;
18+
19+
import java.net.URI;
20+
21+
import org.junit.Test;
22+
import org.junit.runner.RunWith;
23+
24+
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
25+
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
26+
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
27+
import org.springframework.boot.builder.SpringApplicationBuilder;
28+
import org.springframework.boot.test.context.SpringBootTest;
29+
import org.springframework.boot.test.web.client.TestRestTemplate;
30+
import org.springframework.boot.web.server.LocalServerPort;
31+
import org.springframework.context.annotation.Configuration;
32+
import org.springframework.context.annotation.Import;
33+
import org.springframework.http.MediaType;
34+
import org.springframework.http.RequestEntity;
35+
import org.springframework.http.ResponseEntity;
36+
import org.springframework.test.context.junit4.SpringRunner;
37+
38+
import static org.assertj.core.api.Assertions.assertThat;
39+
40+
/**
41+
* Integration tests for the welcome page.
42+
*
43+
* @author Madhura Bhave
44+
*/
45+
@RunWith(SpringRunner.class)
46+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
47+
properties = { "spring.resources.chain.strategy.content.enabled=true",
48+
"spring.thymeleaf.prefix=classpath:/templates/thymeleaf/" })
49+
public class WelcomePageIntegrationTests {
50+
51+
@LocalServerPort
52+
private int port;
53+
54+
private TestRestTemplate template = new TestRestTemplate();
55+
56+
@Test
57+
public void contentStrategyWithWelcomePage() throws Exception {
58+
RequestEntity<?> entity = RequestEntity.get(new URI("http://localhost:" + this.port + "/"))
59+
.header("Accept", MediaType.ALL.toString()).build();
60+
ResponseEntity<String> content = this.template.exchange(entity, String.class);
61+
assertThat(content.getBody()).contains("/custom-");
62+
}
63+
64+
@Configuration
65+
@Import({ PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class,
66+
HttpMessageConvertersAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class,
67+
DispatcherServletAutoConfiguration.class, ThymeleafAutoConfiguration.class })
68+
public static class TestConfiguration {
69+
70+
public static void main(String[] args) {
71+
new SpringApplicationBuilder(TestConfiguration.class).run(args);
72+
}
73+
74+
}
75+
76+
}

spring-boot-project/spring-boot-autoconfigure/src/test/resources/public/custom.css

Whitespace-only changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!doctype html>
2+
<html xmlns:th="https://www.thymeleaf.org">
3+
<head>
4+
<title>Test Thymeleaf</title>
5+
<link th:href="@{/custom.css}" rel="stylesheet" />
6+
</head>
7+
<body>
8+
9+
</body>
10+
</html>

0 commit comments

Comments
 (0)