diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration.java index 52ef8d65ad..7dff563257 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration.java @@ -62,6 +62,11 @@ public class DispatcherServletAutoConfiguration { */ public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet"; + /* + * The bean name for a ServletRegistrationBean for the DispatcherServlet "/" + */ + public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration"; + @Configuration @Conditional(DefaultDispatcherServletCondition.class) @ConditionalOnClass(ServletRegistration.class) @@ -78,10 +83,11 @@ public class DispatcherServletAutoConfiguration { return new DispatcherServlet(); } - @Bean + @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME) public ServletRegistrationBean dispatcherServletRegistration() { ServletRegistrationBean registration = new ServletRegistrationBean( dispatcherServlet(), this.server.getServletPath()); + registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); if (this.multipartConfig != null) { registration.setMultipartConfig(this.multipartConfig); } @@ -97,6 +103,17 @@ public class DispatcherServletAutoConfiguration { AnnotatedTypeMetadata metadata) { ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); + + ConditionOutcome outcome = checkServlets(beanFactory); + + if (!outcome.isMatch()) { + return outcome; + } + + return checkServletRegistrations(beanFactory); + } + + private ConditionOutcome checkServlets(ConfigurableListableBeanFactory beanFactory) { List servlets = Arrays.asList(beanFactory.getBeanNamesForType( DispatcherServlet.class, false, false)); boolean containsDispatcherBean = beanFactory @@ -117,9 +134,46 @@ public class DispatcherServletAutoConfiguration { return ConditionOutcome.noMatch("found non-DispatcherServlet named " + DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); } + return ConditionOutcome .match("one or more DispatcherServlets found and none is named " + DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); + + } + + /** + */ + protected ConditionOutcome checkServletRegistrations( + ConfigurableListableBeanFactory beanFactory) { + + List registrations = Arrays.asList(beanFactory.getBeanNamesForType( + ServletRegistrationBean.class, false, false)); + boolean containsDispatcherRegistrationBean = beanFactory + .containsBean(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME); + + if (registrations.isEmpty()) { + if (containsDispatcherRegistrationBean) { + return ConditionOutcome + .noMatch("found no ServletRegistrationBean but a non-ServletRegistrationBean named " + + DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME); + } + return ConditionOutcome.match("no ServletRegistrationBean found"); + } + + if (registrations.contains(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)) { + return ConditionOutcome.noMatch("found ServletRegistrationBean named " + + DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME); + } + if (containsDispatcherRegistrationBean) { + return ConditionOutcome + .noMatch("found non-ServletRegistrationBean named " + + DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME); + } + + return ConditionOutcome + .match("one or more ServletRegistrationBeans is found and none is named " + + DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME); + } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java index 6f54501f6e..15c6f20cda 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java @@ -54,6 +54,21 @@ public class DispatcherServletAutoConfigurationTests { assertEquals("[/]", registration.getUrlMappings().toString()); } + @Test + public void registrationOverride() throws Exception { + this.context = new AnnotationConfigWebApplicationContext(); + this.context.register(CustomDispatcherRegistration.class, + ServerPropertiesAutoConfiguration.class, + DispatcherServletAutoConfiguration.class); + this.context.setServletContext(new MockServletContext()); + this.context.refresh(); + ServletRegistrationBean registration = this.context + .getBean(ServletRegistrationBean.class); + assertEquals("[/foo]", registration.getUrlMappings().toString()); + assertEquals("customDispatcher", registration.getServletName()); + assertEquals(0, this.context.getBeanNamesForType(DispatcherServlet.class).length); + } + @Test public void servletPath() throws Exception { this.context = new AnnotationConfigWebApplicationContext(); @@ -95,4 +110,15 @@ public class DispatcherServletAutoConfigurationTests { } + @Configuration + protected static class CustomDispatcherRegistration { + @Bean + public ServletRegistrationBean dispatcherServletRegistration() { + ServletRegistrationBean registration = new ServletRegistrationBean( + new DispatcherServlet(), "/foo"); + registration.setName("customDispatcher"); + return registration; + } + } + }