From 5b1165b1029263ff0020562da95bd30380f303e4 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 15 Feb 2013 11:31:32 -0500 Subject: [PATCH] Ignore path parameters in request mappings Before this change the presence of path params (e.g. "/foo;q=1/bar") expected the request mapping to contain a URI variable in the place of semicolon content (e.g. either "/{foo}/bar" or "/{foo};{fooParams}"). The change ensures path params are ignored in @RequestMapping patterns so that "/foo/bar" matches to "/foo;q=1/bar" as well as "/foo;q=1;p=2/bar". Along with this change, the RequestMappingHandlerMapping no longer defaults to having semicolon content removed from the URL, which means @MatrixVariable is supported by default without the need for any further configuration. Issue: SPR-10234 --- .../web/util/UrlPathHelper.java | 6 ++-- .../AnnotationDrivenBeanDefinitionParser.java | 1 - .../WebMvcConfigurationSupport.java | 1 - .../handler/AbstractHandlerMapping.java | 1 + .../handler/AbstractHandlerMethodMapping.java | 7 ++++ .../condition/PatternsRequestCondition.java | 36 +++++++++++-------- .../PatternsRequestConditionTests.java | 11 ++++++ ...RequestMappingInfoHandlerMappingTests.java | 1 - 8 files changed, 42 insertions(+), 22 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java b/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java index 7f98ee2369..362b933658 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java +++ b/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java @@ -441,10 +441,8 @@ public class UrlPathHelper { * @return the updated URI string */ public String removeSemicolonContent(String requestUri) { - if (this.removeSemicolonContent) { - return removeSemicolonContentInternal(requestUri); - } - return removeJsessionid(requestUri); + return this.removeSemicolonContent ? + removeSemicolonContentInternal(requestUri) : removeJsessionid(requestUri); } private String removeSemicolonContentInternal(String requestUri) { 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 9d409a3fec..7fef39364c 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 @@ -154,7 +154,6 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { handlerMappingDef.setSource(source); handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); handlerMappingDef.getPropertyValues().add("order", 0); - handlerMappingDef.getPropertyValues().add("removeSemicolonContent", false); handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager); String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java index e85f189126..c3d1fc0883 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java @@ -192,7 +192,6 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv public RequestMappingHandlerMapping requestMappingHandlerMapping() { RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping(); handlerMapping.setOrder(0); - handlerMapping.setRemoveSemicolonContent(false); handlerMapping.setInterceptors(getInterceptors()); handlerMapping.setContentNegotiationManager(mvcContentNegotiationManager()); return handlerMapping; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java index ea079c4938..b790a1e62b 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java @@ -127,6 +127,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport /** * Set if ";" (semicolon) content should be stripped from the request URI. + *

The default value is {@code false}. * @see org.springframework.web.util.UrlPathHelper#setRemoveSemicolonContent(boolean) */ public void setRemoveSemicolonContent(boolean removeSemicolonContent) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java index c8f11c8175..ccdec77d51 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java @@ -37,6 +37,7 @@ import org.springframework.util.ReflectionUtils.MethodFilter; import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.HandlerMethodSelector; import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.util.UrlPathHelper; /** * Abstract base class for {@link HandlerMapping} implementations that define a @@ -61,6 +62,12 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap private final MultiValueMap urlMap = new LinkedMultiValueMap(); + public AbstractHandlerMethodMapping() { + UrlPathHelper pathHelper = new UrlPathHelper(); + pathHelper.setRemoveSemicolonContent(false); + setUrlPathHelper(pathHelper); + } + /** * Whether to detect handler methods in beans in ancestor ApplicationContexts. *

Default is "false": Only beans in the current ApplicationContext are diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java index 357e31fe36..53642385ca 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java @@ -42,9 +42,16 @@ import org.springframework.web.util.UrlPathHelper; */ public final class PatternsRequestCondition extends AbstractRequestCondition { + private static UrlPathHelper pathHelperNoSemicolonContent; + + static { + pathHelperNoSemicolonContent = new UrlPathHelper(); + pathHelperNoSemicolonContent.setRemoveSemicolonContent(true); + } + private final Set patterns; - private final UrlPathHelper urlPathHelper; + private final UrlPathHelper pathHelper; private final PathMatcher pathMatcher; @@ -105,7 +112,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition fileExtensions) { this.patterns = Collections.unmodifiableSet(prependLeadingSlash(patterns)); - this.urlPathHelper = urlPathHelper != null ? urlPathHelper : new UrlPathHelper(); + this.pathHelper = urlPathHelper != null ? urlPathHelper : new UrlPathHelper(); this.pathMatcher = pathMatcher != null ? pathMatcher : new AntPathMatcher(); this.useSuffixPatternMatch = useSuffixPatternMatch; this.useTrailingSlashMatch = useTrailingSlashMatch; @@ -179,7 +186,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition matches = new ArrayList(); for (String pattern : patterns) { String match = getMatchingPattern(pattern, lookupPath); + if (match == null && lookupPathNoSemicolonContent != null) { + match = getMatchingPattern(pattern, lookupPathNoSemicolonContent); + } if (match != null) { matches.add(match); } } Collections.sort(matches, this.pathMatcher.getPatternComparator(lookupPath)); return matches.isEmpty() ? null : - new PatternsRequestCondition(matches, this.urlPathHelper, this.pathMatcher, this.useSuffixPatternMatch, + new PatternsRequestCondition(matches, this.pathHelper, this.pathMatcher, this.useSuffixPatternMatch, this.useTrailingSlashMatch, this.fileExtensions); } @@ -225,7 +239,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition patternComparator = this.pathMatcher.getPatternComparator(lookupPath); Iterator iterator = patterns.iterator(); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java index 9c38b7c39c..72f6639713 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java @@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest; import org.junit.Test; import org.springframework.mock.web.test.MockHttpServletRequest; +import org.springframework.web.util.UrlPathHelper; /** * @author Rossen Stoyanchev @@ -185,6 +186,16 @@ public class PatternsRequestConditionTests { assertNull(match); } + @Test + public void matchIgnorePathParams() { + UrlPathHelper pathHelper = new UrlPathHelper(); + pathHelper.setRemoveSemicolonContent(false); + PatternsRequestCondition condition = new PatternsRequestCondition(new String[] {"/foo/bar"}, pathHelper, null, true, true); + PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo;q=1/bar;s=1")); + + assertNotNull(match); + } + @Test public void compareEqualPatterns() { PatternsRequestCondition c1 = new PatternsRequestCondition("/foo*"); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java index 2db8412a82..0998bf59f0 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java @@ -90,7 +90,6 @@ public class RequestMappingInfoHandlerMappingTests { this.handlerMapping = new TestRequestMappingInfoHandlerMapping(); this.handlerMapping.registerHandler(testController); - this.handlerMapping.setRemoveSemicolonContent(false); } @Test