Skip to content

Commit

Permalink
Optimize UrlPathHelper configuration for Spring MVC
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bclozel committed May 22, 2020
1 parent 525e03d commit a12a305
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
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}.
Expand Down Expand Up @@ -188,16 +189,20 @@ public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {

private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;

private final ObjectProvider<DispatcherServletPath> dispatcherServletPath;

final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;

public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties,
ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider,
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) {
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
ObjectProvider<DispatcherServletPath> dispatcherServletPath) {
this.resourceProperties = resourceProperties;
this.mvcProperties = mvcProperties;
this.beanFactory = beanFactory;
this.messageConvertersProvider = messageConvertersProvider;
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
this.dispatcherServletPath = dispatcherServletPath;
}

@Override
Expand Down Expand Up @@ -227,6 +232,14 @@ public void configurePathMatch(PathMatchConfigurer configurer) {
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
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;
Expand All @@ -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
Expand Down Expand Up @@ -848,6 +850,22 @@ void customPrinterAndParserShouldBeRegisteredAsConverters() {
});
}

@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<String, Object> handlerMap = getHandlerMap(context.getBean("resourceHandlerMapping", HandlerMapping.class));
assertThat(handlerMap).hasSize(2);
Expand Down

0 comments on commit a12a305

Please sign in to comment.