Commit 004363ce authored by Phillip Webb's avatar Phillip Webb

Use WebMvcConfigurer to add resource handlers

Move resource handler auto-configuration logic back to the
`WebMvcConfigurer` so that they also get applied to child contexts.

Closes gh-25743
parent ee76d603
...@@ -33,6 +33,7 @@ import java.util.concurrent.Executor; ...@@ -33,6 +33,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.ValidatorFactory; import javax.validation.ValidatorFactory;
...@@ -50,9 +51,11 @@ import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguratio ...@@ -50,9 +51,11 @@ import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguratio
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor; import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.filter.OrderedFormContentFilter; import org.springframework.boot.web.servlet.filter.OrderedFormContentFilter;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
...@@ -81,6 +84,7 @@ import org.springframework.web.accept.ParameterContentNegotiationStrategy; ...@@ -81,6 +84,7 @@ import org.springframework.web.accept.ParameterContentNegotiationStrategy;
import org.springframework.web.accept.PathExtensionContentNegotiationStrategy; import org.springframework.web.accept.PathExtensionContentNegotiationStrategy;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.FormContentFilter; import org.springframework.web.filter.FormContentFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter; import org.springframework.web.filter.HiddenHttpMethodFilter;
...@@ -95,6 +99,7 @@ import org.springframework.web.servlet.ViewResolver; ...@@ -95,6 +99,7 @@ import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer; import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver; import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
...@@ -898,6 +903,25 @@ class WebMvcAutoConfigurationTests { ...@@ -898,6 +903,25 @@ class WebMvcAutoConfigurationTests {
}); });
} }
@Test // gh-25743
void addResourceHandlersAppliesToChildAndParentContext() {
try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext()) {
context.register(WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
ResourceHandlersWithChildAndParentContextConfiguration.class);
context.refresh();
SimpleUrlHandlerMapping resourceHandlerMapping = context.getBean("resourceHandlerMapping",
SimpleUrlHandlerMapping.class);
DispatcherServlet extraDispatcherServlet = context.getBean("extraDispatcherServlet",
DispatcherServlet.class);
SimpleUrlHandlerMapping extraResourceHandlerMapping = extraDispatcherServlet.getWebApplicationContext()
.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class);
assertThat(resourceHandlerMapping).isNotSameAs(extraResourceHandlerMapping);
assertThat(resourceHandlerMapping.getUrlMap()).containsKey("/**");
assertThat(extraResourceHandlerMapping.getUrlMap()).containsKey("/**");
}
}
private void assertCacheControl(AssertableWebApplicationContext context) { private void assertCacheControl(AssertableWebApplicationContext context) {
Map<String, Object> handlerMap = getHandlerMap(context.getBean("resourceHandlerMapping", HandlerMapping.class)); Map<String, Object> handlerMap = getHandlerMap(context.getBean("resourceHandlerMapping", HandlerMapping.class));
assertThat(handlerMap).hasSize(2); assertThat(handlerMap).hasSize(2);
...@@ -1330,4 +1354,49 @@ class WebMvcAutoConfigurationTests { ...@@ -1330,4 +1354,49 @@ class WebMvcAutoConfigurationTests {
} }
@Configuration(proxyBeanMethods = false)
static class ResourceHandlersWithChildAndParentContextConfiguration {
@Bean
TomcatServletWebServerFactory webServerFactory() {
return new TomcatServletWebServerFactory(0);
}
@Bean
ServletRegistrationBean<?> additionalDispatcherServlet(DispatcherServlet extraDispatcherServlet) {
ServletRegistrationBean<?> registration = new ServletRegistrationBean<>(extraDispatcherServlet, "/extra/*");
registration.setName("additionalDispatcherServlet");
registration.setLoadOnStartup(1);
return registration;
}
@Bean
private DispatcherServlet extraDispatcherServlet() throws ServletException {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(ResourceHandlersWithChildAndParentContextChildConfiguration.class);
dispatcherServlet.setApplicationContext(applicationContext);
return dispatcherServlet;
}
}
@Configuration(proxyBeanMethods = false)
@EnableWebMvc
static class ResourceHandlersWithChildAndParentContextChildConfiguration {
@Bean
WebMvcConfigurer myConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/testtesttest");
}
};
}
}
} }
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