From a12a3054c9c5dded034ee72faac20e578b5503af Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Fri, 22 May 2020 18:35:08 +0200 Subject: [PATCH] Optimize UrlPathHelper configuration for Spring MVC Prior to this commit, Spring Boot would auto-configure Spring MVC and would keep the default `UrlPathHelper` configuration. Since Spring Boot is in charge of configuring the `DispatcherServlet` and its mapping, it is in a position to optimally configure the `UrlPathHelper` depending on the chosen mapping. This commit sets the `alwaysUseFullPath` property of `UrlPathHelper` if the Servlet mapping is `"/"`. This is more efficient since this configuration requires less processing of the request path. Closes gh-21499 --- .../web/servlet/WebMvcAutoConfiguration.java | 15 ++++++++++++- .../servlet/WebMvcAutoConfigurationTests.java | 22 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java index 062484c1fd..2167937eee 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java @@ -119,6 +119,7 @@ import org.springframework.web.servlet.resource.VersionResourceResolver; import org.springframework.web.servlet.view.BeanNameViewResolver; import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.util.UrlPathHelper; /** * {@link EnableAutoConfiguration Auto-configuration} for {@link EnableWebMvc Web MVC}. @@ -188,16 +189,20 @@ public class WebMvcAutoConfiguration { private final ObjectProvider messageConvertersProvider; + private final ObjectProvider dispatcherServletPath; + final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer; public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider messageConvertersProvider, - ObjectProvider resourceHandlerRegistrationCustomizerProvider) { + ObjectProvider resourceHandlerRegistrationCustomizerProvider, + ObjectProvider dispatcherServletPath) { this.resourceProperties = resourceProperties; this.mvcProperties = mvcProperties; this.beanFactory = beanFactory; this.messageConvertersProvider = messageConvertersProvider; this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable(); + this.dispatcherServletPath = dispatcherServletPath; } @Override @@ -227,6 +232,14 @@ public class WebMvcAutoConfiguration { configurer.setUseSuffixPatternMatch(this.mvcProperties.getPathmatch().isUseSuffixPattern()); configurer.setUseRegisteredSuffixPatternMatch( this.mvcProperties.getPathmatch().isUseRegisteredSuffixPattern()); + this.dispatcherServletPath.ifAvailable((dispatcherPath) -> { + String servletUrlMapping = dispatcherPath.getServletUrlMapping(); + if (servletUrlMapping.equals("/")) { + UrlPathHelper urlPathHelper = new UrlPathHelper(); + urlPathHelper.setAlwaysUseFullPath(true); + configurer.setUrlPathHelper(urlPathHelper); + } + }); } @Override diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java index 2877ae0251..b53f94b6fb 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java @@ -118,6 +118,7 @@ import org.springframework.web.servlet.resource.VersionResourceResolver; import org.springframework.web.servlet.resource.VersionStrategy; import org.springframework.web.servlet.view.AbstractView; import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; +import org.springframework.web.util.UrlPathHelper; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -139,8 +140,9 @@ class WebMvcAutoConfigurationTests { private static final MockServletWebServerFactory webServerFactory = new MockServletWebServerFactory(); private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(WebMvcAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class)) + .withConfiguration( + AutoConfigurations.of(WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test @@ -848,6 +850,22 @@ class WebMvcAutoConfigurationTests { }); } + @Test + void urlPathHelperUsesFullPathByDefault() { + this.contextRunner.run((context) -> { + UrlPathHelper urlPathHelper = context.getBean(UrlPathHelper.class); + assertThat(urlPathHelper).extracting("alwaysUseFullPath").isEqualTo(true); + }); + } + + @Test + void urlPathHelperDoesNotUseFullPathWithServletMapping() { + this.contextRunner.withPropertyValues("spring.mvc.servlet.path=/test/").run((context) -> { + UrlPathHelper urlPathHelper = context.getBean(UrlPathHelper.class); + assertThat(urlPathHelper).extracting("alwaysUseFullPath").isEqualTo(false); + }); + } + private void assertCacheControl(AssertableWebApplicationContext context) { Map handlerMap = getHandlerMap(context.getBean("resourceHandlerMapping", HandlerMapping.class)); assertThat(handlerMap).hasSize(2);