Skip to content

Commit 15042e2

Browse files
committed
Merge branch '2.4.x'
Closes gh-26623
2 parents c380f06 + 6bf069d commit 15042e2

File tree

2 files changed

+132
-54
lines changed

2 files changed

+132
-54
lines changed

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

+63-53
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
import org.springframework.web.accept.ContentNegotiationManager;
8585
import org.springframework.web.accept.ContentNegotiationStrategy;
8686
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
87+
import org.springframework.web.context.ServletContextAware;
8788
import org.springframework.web.context.request.NativeWebRequest;
8889
import org.springframework.web.context.request.RequestAttributes;
8990
import org.springframework.web.context.request.RequestContextListener;
@@ -182,7 +183,11 @@ public OrderedFormContentFilter formContentFilter() {
182183
@EnableConfigurationProperties({ WebMvcProperties.class,
183184
org.springframework.boot.autoconfigure.web.ResourceProperties.class, WebProperties.class })
184185
@Order(0)
185-
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
186+
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {
187+
188+
private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
189+
190+
private final Resources resourceProperties;
186191

187192
private final WebMvcProperties mvcProperties;
188193

@@ -194,13 +199,19 @@ public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
194199

195200
private final ObjectProvider<ServletRegistrationBean<?>> servletRegistrations;
196201

197-
final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
202+
private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
203+
204+
private ServletContext servletContext;
198205

199-
public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties,
200-
ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider,
206+
public WebMvcAutoConfigurationAdapter(
207+
org.springframework.boot.autoconfigure.web.ResourceProperties resourceProperties,
208+
WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory,
209+
ObjectProvider<HttpMessageConverters> messageConvertersProvider,
201210
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
202211
ObjectProvider<DispatcherServletPath> dispatcherServletPath,
203212
ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
213+
this.resourceProperties = resourceProperties.hasBeenCustomized() ? resourceProperties
214+
: webProperties.getResources();
204215
this.mvcProperties = mvcProperties;
205216
this.beanFactory = beanFactory;
206217
this.messageConvertersProvider = messageConvertersProvider;
@@ -210,6 +221,11 @@ public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcPropert
210221
this.mvcProperties.checkConfiguration();
211222
}
212223

224+
@Override
225+
public void setServletContext(ServletContext servletContext) {
226+
this.servletContext = servletContext;
227+
}
228+
213229
@Override
214230
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
215231
this.messageConvertersProvider
@@ -312,6 +328,49 @@ public void addFormatters(FormatterRegistry registry) {
312328
ApplicationConversionService.addBeans(registry, this.beanFactory);
313329
}
314330

331+
@Override
332+
public void addResourceHandlers(ResourceHandlerRegistry registry) {
333+
if (!this.resourceProperties.isAddMappings()) {
334+
logger.debug("Default resource handling disabled");
335+
return;
336+
}
337+
addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
338+
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
339+
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
340+
if (this.servletContext != null) {
341+
ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION);
342+
registration.addResourceLocations(resource);
343+
}
344+
});
345+
}
346+
347+
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, String... locations) {
348+
addResourceHandler(registry, pattern, (registration) -> registration.addResourceLocations(locations));
349+
}
350+
351+
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern,
352+
Consumer<ResourceHandlerRegistration> customizer) {
353+
if (registry.hasMappingForPattern(pattern)) {
354+
return;
355+
}
356+
ResourceHandlerRegistration registration = registry.addResourceHandler(pattern);
357+
customizer.accept(registration);
358+
registration.setCachePeriod(getSeconds(this.resourceProperties.getCache().getPeriod()));
359+
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
360+
registration.setUseLastModified(this.resourceProperties.getCache().isUseLastModified());
361+
customizeResourceHandlerRegistration(registration);
362+
}
363+
364+
private Integer getSeconds(Duration cachePeriod) {
365+
return (cachePeriod != null) ? (int) cachePeriod.getSeconds() : null;
366+
}
367+
368+
private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) {
369+
if (this.resourceHandlerRegistrationCustomizer != null) {
370+
this.resourceHandlerRegistrationCustomizer.customize(registration);
371+
}
372+
}
373+
315374
@Bean
316375
@ConditionalOnMissingBean({ RequestContextListener.class, RequestContextFilter.class })
317376
@ConditionalOnMissingFilterBean(RequestContextFilter.class)
@@ -328,8 +387,6 @@ public static RequestContextFilter requestContextFilter() {
328387
@EnableConfigurationProperties(WebProperties.class)
329388
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
330389

331-
private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
332-
333390
private final Resources resourceProperties;
334391

335392
private final WebMvcProperties mvcProperties;
@@ -340,8 +397,6 @@ public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfigurat
340397

341398
private final WebMvcRegistrations mvcRegistrations;
342399

343-
private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
344-
345400
private ResourceLoader resourceLoader;
346401

347402
@SuppressWarnings("deprecation")
@@ -356,7 +411,6 @@ public EnableWebMvcConfiguration(
356411
this.mvcProperties = mvcProperties;
357412
this.webProperties = webProperties;
358413
this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
359-
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
360414
this.beanFactory = beanFactory;
361415
}
362416

@@ -396,50 +450,6 @@ public RequestMappingHandlerMapping requestMappingHandlerMapping(
396450
resourceUrlProvider);
397451
}
398452

399-
@Override
400-
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
401-
super.addResourceHandlers(registry);
402-
if (!this.resourceProperties.isAddMappings()) {
403-
logger.debug("Default resource handling disabled");
404-
return;
405-
}
406-
ServletContext servletContext = getServletContext();
407-
addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
408-
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
409-
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
410-
if (servletContext != null) {
411-
registration.addResourceLocations(new ServletContextResource(servletContext, SERVLET_LOCATION));
412-
}
413-
});
414-
}
415-
416-
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, String... locations) {
417-
addResourceHandler(registry, pattern, (registration) -> registration.addResourceLocations(locations));
418-
}
419-
420-
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern,
421-
Consumer<ResourceHandlerRegistration> customizer) {
422-
if (registry.hasMappingForPattern(pattern)) {
423-
return;
424-
}
425-
ResourceHandlerRegistration registration = registry.addResourceHandler(pattern);
426-
customizer.accept(registration);
427-
registration.setCachePeriod(getSeconds(this.resourceProperties.getCache().getPeriod()));
428-
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
429-
registration.setUseLastModified(this.resourceProperties.getCache().isUseLastModified());
430-
customizeResourceHandlerRegistration(registration);
431-
}
432-
433-
private Integer getSeconds(Duration cachePeriod) {
434-
return (cachePeriod != null) ? (int) cachePeriod.getSeconds() : null;
435-
}
436-
437-
private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) {
438-
if (this.resourceHandlerRegistrationCustomizer != null) {
439-
this.resourceHandlerRegistrationCustomizer.customize(registration);
440-
}
441-
}
442-
443453
@Bean
444454
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
445455
FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java

+69-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.concurrent.TimeUnit;
3333
import java.util.function.Consumer;
3434

35+
import javax.servlet.ServletException;
3536
import javax.servlet.http.HttpServletRequest;
3637
import javax.servlet.http.HttpServletResponse;
3738
import javax.validation.ValidatorFactory;
@@ -52,9 +53,11 @@
5253
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
5354
import org.springframework.boot.test.context.runner.ContextConsumer;
5455
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
56+
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
5557
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
5658
import org.springframework.boot.web.servlet.FilterRegistrationBean;
5759
import org.springframework.boot.web.servlet.ServletRegistrationBean;
60+
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
5861
import org.springframework.boot.web.servlet.filter.OrderedFormContentFilter;
5962
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
6063
import org.springframework.context.ApplicationContext;
@@ -82,6 +85,7 @@
8285
import org.springframework.web.accept.ParameterContentNegotiationStrategy;
8386
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
8487
import org.springframework.web.context.request.ServletWebRequest;
88+
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
8589
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
8690
import org.springframework.web.filter.FormContentFilter;
8791
import org.springframework.web.filter.HiddenHttpMethodFilter;
@@ -99,6 +103,7 @@
99103
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
100104
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
101105
import org.springframework.web.servlet.config.annotation.CorsRegistry;
106+
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
102107
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
103108
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
104109
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
@@ -1004,6 +1009,25 @@ void lastModifiedNotUsedIfDisabled() {
10041009
(handler) -> assertThat(handler.isUseLastModified()).isFalse()));
10051010
}
10061011

1012+
@Test // gh-25743
1013+
void addResourceHandlersAppliesToChildAndParentContext() {
1014+
try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext()) {
1015+
context.register(WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
1016+
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
1017+
ResourceHandlersWithChildAndParentContextConfiguration.class);
1018+
context.refresh();
1019+
SimpleUrlHandlerMapping resourceHandlerMapping = context.getBean("resourceHandlerMapping",
1020+
SimpleUrlHandlerMapping.class);
1021+
DispatcherServlet extraDispatcherServlet = context.getBean("extraDispatcherServlet",
1022+
DispatcherServlet.class);
1023+
SimpleUrlHandlerMapping extraResourceHandlerMapping = extraDispatcherServlet.getWebApplicationContext()
1024+
.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class);
1025+
assertThat(resourceHandlerMapping).isNotSameAs(extraResourceHandlerMapping);
1026+
assertThat(resourceHandlerMapping.getUrlMap()).containsKey("/**");
1027+
assertThat(extraResourceHandlerMapping.getUrlMap()).containsKey("/**");
1028+
}
1029+
}
1030+
10071031
private void assertResourceHttpRequestHandler(AssertableWebApplicationContext context,
10081032
Consumer<ResourceHttpRequestHandler> handlerConsumer) {
10091033
Map<String, Object> handlerMap = getHandlerMap(context.getBean("resourceHandlerMapping", HandlerMapping.class));
@@ -1458,7 +1482,6 @@ public String resolveThemeName(HttpServletRequest request) {
14581482

14591483
@Override
14601484
public void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName) {
1461-
14621485
}
14631486

14641487
}
@@ -1478,4 +1501,49 @@ protected void updateFlashMaps(List<FlashMap> flashMaps, HttpServletRequest requ
14781501

14791502
}
14801503

1504+
@Configuration(proxyBeanMethods = false)
1505+
static class ResourceHandlersWithChildAndParentContextConfiguration {
1506+
1507+
@Bean
1508+
TomcatServletWebServerFactory webServerFactory() {
1509+
return new TomcatServletWebServerFactory(0);
1510+
}
1511+
1512+
@Bean
1513+
ServletRegistrationBean<?> additionalDispatcherServlet(DispatcherServlet extraDispatcherServlet) {
1514+
ServletRegistrationBean<?> registration = new ServletRegistrationBean<>(extraDispatcherServlet, "/extra/*");
1515+
registration.setName("additionalDispatcherServlet");
1516+
registration.setLoadOnStartup(1);
1517+
return registration;
1518+
}
1519+
1520+
@Bean
1521+
private DispatcherServlet extraDispatcherServlet() throws ServletException {
1522+
DispatcherServlet dispatcherServlet = new DispatcherServlet();
1523+
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
1524+
applicationContext.register(ResourceHandlersWithChildAndParentContextChildConfiguration.class);
1525+
dispatcherServlet.setApplicationContext(applicationContext);
1526+
return dispatcherServlet;
1527+
}
1528+
1529+
}
1530+
1531+
@Configuration(proxyBeanMethods = false)
1532+
@EnableWebMvc
1533+
static class ResourceHandlersWithChildAndParentContextChildConfiguration {
1534+
1535+
@Bean
1536+
WebMvcConfigurer myConfigurer() {
1537+
return new WebMvcConfigurer() {
1538+
1539+
@Override
1540+
public void addResourceHandlers(ResourceHandlerRegistry registry) {
1541+
registry.addResourceHandler("/testtesttest");
1542+
}
1543+
1544+
};
1545+
}
1546+
1547+
}
1548+
14811549
}

0 commit comments

Comments
 (0)