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
This commit is contained in:
Brian Clozel
2014-01-20 20:44:55 +01:00
parent 8edb7a18cc
commit eac4881809
4 changed files with 140 additions and 5 deletions

View File

@@ -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) {

View File

@@ -24,6 +24,63 @@
</xsd:annotation>
<xsd:complexType>
<xsd:all minOccurs="0">
<xsd:element name="path-matching" minOccurs="0">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures the path matching part of the Spring MVC Controller programming model.
Like annotation-driven, code-based alternatives are also documented in EnableWebMvc Javadoc.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="suffix-pattern" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether to use suffix pattern match (".*") when matching patterns to requests. If enabled
a method mapped to "/users" also matches to "/users.*".
The default value is true.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="trailing-slash" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether to match to URLs irrespective of the presence of a trailing slash.
If enabled a method mapped to "/users" also matches to "/users/".
The default value is true.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="registered-suffixes-only" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether to use suffix pattern match for registered file extensions only when matching patterns to requests.
If enabled, a controller method mapped to "/users" also matches to "/users.json" assuming ".json" is a file extension registered with
the provided ContentNegotiationManager. This can be useful for allowing only specific URL extensions to be used as well as in cases
where a "." in the URL path can lead to ambiguous interpretation of path variable content, (e.g. given "/users/{user}" and incoming
URLs such as "/users/john.j.joe" and "/users/john.j.joe.json").
If enabled, this attribute also enables suffix-pattern. The default value is false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="path-helper" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The bean name of the UrlPathHelper to use for resolution of lookup paths.
Use this to override the default UrlPathHelper with a custom subclass, or to share common UrlPathHelper settings across
multiple HandlerMappings and MethodNameResolvers.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="path-matcher" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The bean name of the PathMatcher implementation to use for matching URL paths against registered URL patterns.
Default is AntPathMatcher.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="message-converters" minOccurs="0">
<xsd:annotation>
<xsd:documentation><![CDATA[