mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Improve PathMatcher/PatternParser XML configuration
Prior to this commit, the MVC namespace for the XML Spring configuration model would use the `PathMatcher` bean instance when provided like this: ``` <bean id="pathMatcher" class="org.springframework.util.AntPathMatcher"/> <mvc:annotation-driven> <mvc:path-matching path-matcher="pathMatcher"/> </mvc:annotation-driven> <mvc:resources mapping="/resources/**" location="classpath:/static/"/> ``` With this configuration, the handler mapping for annotated controller would use the given `AntPathMatcher` instance but the handler mapping for resources would still use the default, which is `PathPatternParser` since 6.0. This commit ensures that when a custom `path-matcher` is defined, it's consistently used for all MVC handler mappings as an alias to the well-known bean name. This allows to use `AntPathMatcher` consistently while working on a migration path to `PathPatternParser` This commit also adds a new XML attribute to the path matching configuration that makes it possible to use a custom `PathPatternParser` instance: ``` <bean id="patternParser" class="org.springframework.web.util.pattern.PathPatternParser"/> <mvc:annotation-driven> <mvc:path-matching pattern-parser="patternParser"/> </mvc:annotation-driven> ``` Closes gh-34064
This commit is contained in:
+1
@@ -89,6 +89,7 @@ class AnnotationDrivenBeanDefinitionParserTests {
|
||||
assertThat(hm.useRegisteredSuffixPatternMatch()).isTrue();
|
||||
assertThat(hm.getUrlPathHelper()).isInstanceOf(TestPathHelper.class);
|
||||
assertThat(hm.getPathMatcher()).isInstanceOf(TestPathMatcher.class);
|
||||
assertThat(hm.getPatternParser()).isNull();
|
||||
List<String> fileExtensions = hm.getContentNegotiationManager().getAllFileExtensions();
|
||||
assertThat(fileExtensions).containsExactly("xml");
|
||||
}
|
||||
|
||||
+40
-6
@@ -64,6 +64,7 @@ import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConve
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
@@ -145,6 +146,7 @@ import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
import org.springframework.web.testfixture.servlet.MockRequestDispatcher;
|
||||
import org.springframework.web.testfixture.servlet.MockServletContext;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
@@ -202,6 +204,8 @@ public class MvcNamespaceTests {
|
||||
assertThat(mapping).isNotNull();
|
||||
assertThat(mapping.getOrder()).isEqualTo(0);
|
||||
assertThat(mapping.getUrlPathHelper().shouldRemoveSemicolonContent()).isTrue();
|
||||
assertThat(mapping.getPathMatcher()).isEqualTo(appContext.getBean("mvcPathMatcher"));
|
||||
assertThat(mapping.getPatternParser()).isNotNull();
|
||||
mapping.setDefaultHandler(handlerMethod);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.json");
|
||||
@@ -392,6 +396,8 @@ public class MvcNamespaceTests {
|
||||
SimpleUrlHandlerMapping resourceMapping = appContext.getBean(SimpleUrlHandlerMapping.class);
|
||||
assertThat(resourceMapping).isNotNull();
|
||||
assertThat(resourceMapping.getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE - 1);
|
||||
assertThat(resourceMapping.getPathMatcher()).isNotNull();
|
||||
assertThat(resourceMapping.getPatternParser()).isNotNull();
|
||||
|
||||
BeanNameUrlHandlerMapping beanNameMapping = appContext.getBean(BeanNameUrlHandlerMapping.class);
|
||||
assertThat(beanNameMapping).isNotNull();
|
||||
@@ -423,6 +429,31 @@ public class MvcNamespaceTests {
|
||||
.isInstanceOf(NoResourceFoundException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUseDeprecatedPathMatcher() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-deprecated-path-matcher.xml");
|
||||
Map<String, AbstractHandlerMapping> handlerMappings = appContext.getBeansOfType(AbstractHandlerMapping.class);
|
||||
AntPathMatcher mvcPathMatcher = appContext.getBean("pathMatcher", AntPathMatcher.class);
|
||||
assertThat(handlerMappings).hasSize(4);
|
||||
handlerMappings.forEach((name, hm) -> {
|
||||
assertThat(hm.getPathMatcher()).as("path matcher for %s", name).isEqualTo(mvcPathMatcher);
|
||||
assertThat(hm.getPatternParser()).as("pattern parser for %s", name).isNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUsePathPatternParser() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-custom-pattern-parser.xml");
|
||||
|
||||
PathPatternParser patternParser = appContext.getBean("patternParser", PathPatternParser.class);
|
||||
Map<String, AbstractHandlerMapping> handlerMappings = appContext.getBeansOfType(AbstractHandlerMapping.class);
|
||||
assertThat(handlerMappings).hasSize(4);
|
||||
handlerMappings.forEach((name, hm) -> {
|
||||
assertThat(hm.getPathMatcher()).as("path matcher for %s", name).isNotNull();
|
||||
assertThat(hm.getPatternParser()).as("pattern parser for %s", name).isEqualTo(patternParser);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testResourcesWithOptionalAttributes() {
|
||||
loadBeanDefinitions("mvc-config-resources-optional-attrs.xml");
|
||||
@@ -601,6 +632,9 @@ public class MvcNamespaceTests {
|
||||
assertThat(beanNameMapping).isNotNull();
|
||||
assertThat(beanNameMapping.getOrder()).isEqualTo(2);
|
||||
|
||||
assertThat(beanNameMapping.getPathMatcher()).isNotNull();
|
||||
assertThat(beanNameMapping.getPatternParser()).isNotNull();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
|
||||
@@ -896,11 +930,11 @@ public class MvcNamespaceTests {
|
||||
assertThat(viewController.getUrlPathHelper().getClass()).isEqualTo(TestPathHelper.class);
|
||||
assertThat(viewController.getPathMatcher().getClass()).isEqualTo(TestPathMatcher.class);
|
||||
|
||||
for (SimpleUrlHandlerMapping handlerMapping : appContext.getBeansOfType(SimpleUrlHandlerMapping.class).values()) {
|
||||
appContext.getBeansOfType(SimpleUrlHandlerMapping.class).forEach((name, handlerMapping) -> {
|
||||
assertThat(handlerMapping).isNotNull();
|
||||
assertThat(handlerMapping.getUrlPathHelper().getClass()).isEqualTo(TestPathHelper.class);
|
||||
assertThat(handlerMapping.getPathMatcher().getClass()).isEqualTo(TestPathMatcher.class);
|
||||
}
|
||||
assertThat(handlerMapping.getUrlPathHelper().getClass()).as("path helper for %s", name).isEqualTo(TestPathHelper.class);
|
||||
assertThat(handlerMapping.getPathMatcher().getClass()).as("path matcher for %s", name).isEqualTo(TestPathMatcher.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -910,7 +944,7 @@ public class MvcNamespaceTests {
|
||||
String[] beanNames = appContext.getBeanNamesForType(AbstractHandlerMapping.class);
|
||||
assertThat(beanNames).hasSize(2);
|
||||
for (String beanName : beanNames) {
|
||||
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping)appContext.getBean(beanName);
|
||||
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) appContext.getBean(beanName);
|
||||
assertThat(handlerMapping).isNotNull();
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(handlerMapping);
|
||||
Map<String, CorsConfiguration> configs = ((UrlBasedCorsConfigurationSource) accessor
|
||||
@@ -935,7 +969,7 @@ public class MvcNamespaceTests {
|
||||
String[] beanNames = appContext.getBeanNamesForType(AbstractHandlerMapping.class);
|
||||
assertThat(beanNames).hasSize(2);
|
||||
for (String beanName : beanNames) {
|
||||
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping)appContext.getBean(beanName);
|
||||
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) appContext.getBean(beanName);
|
||||
assertThat(handlerMapping).isNotNull();
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(handlerMapping);
|
||||
Map<String, CorsConfiguration> configs = ((UrlBasedCorsConfigurationSource) accessor
|
||||
|
||||
Reference in New Issue
Block a user