From eac48818098a9ee4ab20f0b37a1e79518c30308a Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Mon, 20 Jan 2014 20:44:55 +0100 Subject: [PATCH] Make RequestMappingHandlerMapping xml config easier Prior to this commit, it was necessary to override the HandlerMapping definition to change properties like useSuffixPatternMatch, useSuffixPatternMatch... Also, one couldn't set custom pathmatcher/pathhelper on RequestMappingHandlerMapping via XML configuration. This commits adds a new "mvc:annotation-driven" subelement called "mvc:path-matching" for the tag that allows to configure such properties: * suffix-pattern * trailing-slash * registered-suffixes-only * path-matcher * path-helper Note: this is a new take on this issue, since 96b418cc has been reverted by e2b99c3. Issue: SPR-10163 --- .../AnnotationDrivenBeanDefinitionParser.java | 30 ++++++++++ .../web/servlet/config/spring-mvc-4.0.xsd | 57 +++++++++++++++++++ ...tationDrivenBeanDefinitionParserTests.java | 32 +++++++++-- .../config/mvc-config-path-matching.xml | 26 +++++++++ 4 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-path-matching.xml diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java index 7b4ceef94f0..ebab71b9238 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java @@ -125,6 +125,7 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv * @author Juergen Hoeller * @author Arjen Poutsma * @author Rossen Stoyanchev + * @author Brian Clozel * @since 3.0 */ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { @@ -172,6 +173,8 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables); } + configurePathMatchingProperties(handlerMappingDef, element); + RuntimeBeanReference conversionService = getConversionService(element, source, parserContext); RuntimeBeanReference validator = getValidator(element, source, parserContext); RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element); @@ -334,6 +337,33 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { return contentNegotiationManagerRef; } + private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef, Element element) { + + Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching"); + if(pathMatchingElement != null) { + if (pathMatchingElement.hasAttribute("suffix-pattern")) { + Boolean useSuffixPatternMatch = Boolean.valueOf(pathMatchingElement.getAttribute("suffix-pattern")); + handlerMappingDef.getPropertyValues().add("useSuffixPatternMatch", useSuffixPatternMatch); + } + if (pathMatchingElement.hasAttribute("trailing-slash")) { + Boolean useTrailingSlashMatch = Boolean.valueOf(pathMatchingElement.getAttribute("trailing-slash")); + handlerMappingDef.getPropertyValues().add("useTrailingSlashMatch", useTrailingSlashMatch); + } + if (pathMatchingElement.hasAttribute("registered-suffixes-only")) { + Boolean useRegisteredSuffixPatternMatch = Boolean.valueOf(pathMatchingElement.getAttribute("registered-suffixes-only")); + handlerMappingDef.getPropertyValues().add("useRegisteredSuffixPatternMatch", useRegisteredSuffixPatternMatch); + } + if (pathMatchingElement.hasAttribute("path-helper")) { + RuntimeBeanReference pathHelperRef = new RuntimeBeanReference(pathMatchingElement.getAttribute("path-helper")); + handlerMappingDef.getPropertyValues().add("urlPathHelper", pathHelperRef); + } + if (pathMatchingElement.hasAttribute("path-matcher")) { + RuntimeBeanReference pathMatcherRef = new RuntimeBeanReference(pathMatchingElement.getAttribute("path-matcher")); + handlerMappingDef.getPropertyValues().add("pathMatcher", pathMatcherRef); + } + } + } + private Properties getDefaultMediaTypes() { Properties props = new Properties(); if (romePresent) { diff --git a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.0.xsd b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.0.xsd index 985d54a5846..92053fa4546 100644 --- a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.0.xsd +++ b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.0.xsd @@ -24,6 +24,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fileExtensions = hm.getContentNegotiationManager().getAllFileExtensions(); + assertThat(fileExtensions, Matchers.contains("xml")); + assertThat(fileExtensions, Matchers.hasSize(1)); + } + @Test public void testMessageConverters() { loadBeanDefinitions("mvc-config-message-converters.xml"); @@ -198,3 +216,7 @@ class TestMessageCodesResolver implements MessageCodesResolver { } } + +class TestPathMatcher extends AntPathMatcher { } + +class TestPathHelper extends UrlPathHelper { } \ No newline at end of file diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-path-matching.xml b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-path-matching.xml new file mode 100644 index 00000000000..8b27fa26f57 --- /dev/null +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-path-matching.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + xml=application/rss+xml + + + + \ No newline at end of file