From 6f150e4f07b6d637fb550f66008a68ea0f824997 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 8 Dec 2011 03:38:50 +0000 Subject: [PATCH] SPR-8898 Allow match by trailing slash in RequestMappingHandlerMapping. --- .../resources/changelog.txt | 1 + .../condition/PatternsRequestCondition.java | 48 +++++++++++-------- .../RequestMappingHandlerMapping.java | 23 +++++++-- .../PatternsRequestConditionTests.java | 12 +++-- ...RequestMappingInfoHandlerMappingTests.java | 2 +- 5 files changed, 59 insertions(+), 27 deletions(-) diff --git a/build-spring-framework/resources/changelog.txt b/build-spring-framework/resources/changelog.txt index 7d4193a2f2c..ce9f13f17f4 100644 --- a/build-spring-framework/resources/changelog.txt +++ b/build-spring-framework/resources/changelog.txt @@ -19,6 +19,7 @@ Changes in version 3.1 GA (2011-12-12) * ResourceHttpRequestHandler and ContentNegotiatingViewResolver use consistent mime type resolution * Portlet MVC annotation mapping allows for distributing action names across controllers * added String constants to MediaType +* add useTrailingSlashMatch property to RequestMappingHandlerMapping Changes in version 3.1 RC2 (2011-11-28) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java index 2e32d1d6e16..9b61fe7c954 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java @@ -50,13 +50,15 @@ public final class PatternsRequestCondition extends AbstractRequestCondition patterns, UrlPathHelper urlPathHelper, PathMatcher pathMatcher, - boolean useSuffixPatternMatch) { + boolean useSuffixPatternMatch, + boolean useTrailingSlashMatch) { this.patterns = Collections.unmodifiableSet(prependLeadingSlash(patterns)); this.urlPathHelper = urlPathHelper != null ? urlPathHelper : new UrlPathHelper(); this.pathMatcher = pathMatcher != null ? pathMatcher : new AntPathMatcher(); this.useSuffixPatternMatch = useSuffixPatternMatch; + this.useTrailingSlashMatch = useTrailingSlashMatch; } private static List asList(String... patterns) { @@ -106,12 +112,12 @@ public final class PatternsRequestCondition extends AbstractRequestCondition getPatterns() { - return patterns; + return this.patterns; } @Override protected Collection getContent() { - return patterns; + return this.patterns; } @Override @@ -134,7 +140,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition matches = new ArrayList(); for (String pattern : patterns) { String match = getMatchingPattern(pattern, lookupPath); @@ -181,27 +188,30 @@ public final class PatternsRequestCondition extends AbstractRequestCondition patternComparator = pathMatcher.getPatternComparator(lookupPath); + String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); + Comparator patternComparator = this.pathMatcher.getPatternComparator(lookupPath); Iterator iterator = patterns.iterator(); Iterator iteratorOther = other.patterns.iterator(); diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java index 95478692581..8301ce7c4df 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java @@ -44,14 +44,25 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi private boolean useSuffixPatternMatch = true; + private boolean useTrailingSlashMatch = true; + /** * 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". + * requests. If enabled a method mapped to "/users" also matches to "/users.*". + *

The default value is {@code true}. */ public void setUseSuffixPatternMatch(boolean useSuffixPatternMatch) { this.useSuffixPatternMatch = useSuffixPatternMatch; } + + /** + * 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 {@code true}. + */ + public void setUseTrailingSlashMatch(boolean useTrailingSlashMatch) { + this.useTrailingSlashMatch = useTrailingSlashMatch; + } /** * Whether to use suffix pattern matching. @@ -59,6 +70,12 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi public boolean useSuffixPatternMatch() { return this.useSuffixPatternMatch; } + /** + * Whether to match to URLs irrespective of the presence of a trailing slash. + */ + public boolean useTrailingSlashMatch() { + return this.useTrailingSlashMatch; + } /** * {@inheritDoc} @@ -125,7 +142,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi private RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, RequestCondition customCondition) { return new RequestMappingInfo( new PatternsRequestCondition(annotation.value(), - getUrlPathHelper(), getPathMatcher(), useSuffixPatternMatch), + getUrlPathHelper(), getPathMatcher(), this.useSuffixPatternMatch, this.useTrailingSlashMatch), new RequestMethodsRequestCondition(annotation.method()), new ParamsRequestCondition(annotation.params()), new HeadersRequestCondition(annotation.headers()), diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java index de54f7260ef..d59dce9f3d3 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java @@ -106,7 +106,7 @@ public class PatternsRequestConditionTests { assertNotNull(match); assertEquals("/{foo}.*", match.getPatterns().iterator().next()); - condition = new PatternsRequestCondition(new String[] {"/{foo}"}, null, null, false); + condition = new PatternsRequestCondition(new String[] {"/{foo}"}, null, null, false, false); match = condition.getMatchingCondition(request); assertNotNull(match); @@ -121,15 +121,19 @@ public class PatternsRequestConditionTests { PatternsRequestCondition match = condition.getMatchingCondition(request); assertNotNull(match); - assertEquals("/foo/", match.getPatterns().iterator().next()); + assertEquals("Should match by default", "/foo/", match.getPatterns().iterator().next()); - boolean useSuffixPatternMatch = false; - condition = new PatternsRequestCondition(new String[] {"/foo"}, null, null, useSuffixPatternMatch); + condition = new PatternsRequestCondition(new String[] {"/foo"}, null, null, false, true); match = condition.getMatchingCondition(request); assertNotNull(match); assertEquals("Trailing slash should be insensitive to useSuffixPatternMatch settings (SPR-6164, SPR-5636)", "/foo/", match.getPatterns().iterator().next()); + + condition = new PatternsRequestCondition(new String[] {"/foo"}, null, null, false, false); + match = condition.getMatchingCondition(request); + + assertNull(match); } @Test diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java index e38c87ac465..d6562766e76 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java @@ -317,7 +317,7 @@ public class RequestMappingInfoHandlerMappingTests { RequestMapping annotation = AnnotationUtils.findAnnotation(method, RequestMapping.class); if (annotation != null) { return new RequestMappingInfo( - new PatternsRequestCondition(annotation.value(), getUrlPathHelper(), getPathMatcher(), true), + new PatternsRequestCondition(annotation.value(), getUrlPathHelper(), getPathMatcher(), true, true), new RequestMethodsRequestCondition(annotation.method()), new ParamsRequestCondition(annotation.params()), new HeadersRequestCondition(annotation.headers()),