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 4fde3d2d7c..79ecbb6752 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 @@ -34,6 +34,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.boot.context.embedded.ServletRegistrationBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ConditionContext; @@ -53,6 +54,7 @@ import org.springframework.web.servlet.DispatcherServlet; * * @author Phillip Webb * @author Dave Syer + * @author Stephane Nicoll */ @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration @@ -74,17 +76,24 @@ public class DispatcherServletAutoConfiguration { @Configuration @Conditional(DefaultDispatcherServletCondition.class) @ConditionalOnClass(ServletRegistration.class) + @EnableConfigurationProperties(WebMvcProperties.class) protected static class DispatcherServletConfiguration { @Autowired private ServerProperties server; + @Autowired + private WebMvcProperties webMvcProperties; + @Autowired(required = false) private MultipartConfigElement multipartConfig; @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServlet dispatcherServlet() { - return new DispatcherServlet(); + DispatcherServlet dispatcherServlet = new DispatcherServlet(); + dispatcherServlet.setThrowExceptionIfNoHandlerFound( + this.webMvcProperties.isThrowExceptionIfNoHandlerFound()); + return dispatcherServlet; } @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcProperties.java index 2301c69a45..8a1935031b 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcProperties.java @@ -53,6 +53,12 @@ public class WebMvcProperties { */ private boolean ignoreDefaultModelOnRedirect = true; + /** + * If a "NoHandlerFoundException" should be thrown if no Handler was found to process + * a request. + */ + private boolean throwExceptionIfNoHandlerFound = false; + private final Async async = new Async(); private final View view = new View(); @@ -90,6 +96,14 @@ public class WebMvcProperties { this.ignoreDefaultModelOnRedirect = ignoreDefaultModelOnRedirect; } + public boolean isThrowExceptionIfNoHandlerFound() { + return this.throwExceptionIfNoHandlerFound; + } + + public void setThrowExceptionIfNoHandlerFound(boolean throwExceptionIfNoHandlerFound) { + this.throwExceptionIfNoHandlerFound = throwExceptionIfNoHandlerFound; + } + public Async getAsync() { return this.async; } 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 d673ecfcd8..2777727a63 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 @@ -19,7 +19,9 @@ package org.springframework.boot.autoconfigure.web; import javax.servlet.MultipartConfigElement; import javax.servlet.http.HttpServletRequest; +import org.junit.After; import org.junit.Test; +import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.UnsatisfiedDependencyException; import org.springframework.boot.context.embedded.MultipartConfigFactory; import org.springframework.boot.context.embedded.ServletRegistrationBean; @@ -49,6 +51,13 @@ public class DispatcherServletAutoConfigurationTests { private AnnotationConfigWebApplicationContext context; + @After + public void closeContext() { + if (this.context != null) { + this.context.close(); + } + } + @Test public void registrationProperties() throws Exception { this.context = new AnnotationConfigWebApplicationContext(); @@ -137,6 +146,20 @@ public class DispatcherServletAutoConfigurationTests { instanceOf(MockMultipartResolver.class)); } + @Test + public void dispatcherServletConfig() { + this.context = new AnnotationConfigWebApplicationContext(); + this.context.setServletContext(new MockServletContext()); + this.context.register(ServerPropertiesAutoConfiguration.class, + DispatcherServletAutoConfiguration.class); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.mvc.throw-exception-if-no-handler-found:true"); + this.context.refresh(); + DispatcherServlet bean = this.context.getBean(DispatcherServlet.class); + assertEquals(true, new DirectFieldAccessor(bean). + getPropertyValue("throwExceptionIfNoHandlerFound")); + } + @Configuration protected static class MultipartConfiguration { diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index af3c47902d..fcd6e79f90 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -151,6 +151,7 @@ content into your application; rather pick only the properties that you need. spring.mvc.favicon.enabled=true spring.mvc.message-codes-resolver-format= # PREFIX_ERROR_CODE / POSTFIX_ERROR_CODE spring.mvc.ignore-default-model-on-redirect=true # if the content of the "default" model should be ignored redirects + spring.mvc.throw-exception-if-no-handler-found=false # if a "NoHandlerFoundException" should be thrown if no Handler was found to process a request spring.mvc.async.request-timeout= # async request timeout in milliseconds spring.mvc.view.prefix= # MVC view prefix spring.mvc.view.suffix= # ... and suffix