diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java index 5ba30a4d49e281489ae48752617723e08bdd931f..2b936b5de37836c964d9251aca2e3c0ff71853fe 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java @@ -503,7 +503,15 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen if (pattern.equals(lookupPath) || pathMatcher.match(pattern, lookupPath)) { return true; } - return !(pattern.indexOf('.') != -1) && pathMatcher.match(pattern + ".*", lookupPath); + boolean hasSuffix = pattern.indexOf('.') != -1; + if (!hasSuffix && pathMatcher.match(pattern + ".*", lookupPath)) { + return true; + } + boolean endsWithSlash = pattern.endsWith("/"); + if (!endsWithSlash && pathMatcher.match(pattern + "/", lookupPath)) { + return true; + } + return false; } private boolean checkParameters(RequestMappingInfo mapping, HttpServletRequest request) { diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.java index 07c136ffb688abcf7bbcd5e6eb52a1f5ea9dc7d1..f2087c192a0f78e37674521a72f897ee8595d58f 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.java @@ -86,10 +86,10 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler /** * Set whether to register paths using the default suffix pattern as well: - * i.e. whether "/users" should be registered as "/users.*" too. + * i.e. whether "/users" should be registered as "/users.*" and "/users/" too. *

Default is "true". Turn this convention off if you intend to interpret * your @RequestMapping paths strictly. - *

Note that paths which include a ".xxx" suffix already will not be + *

Note that paths which include a ".xxx" suffix or end with "/" already will not be * transformed using the default suffix pattern in any case. */ public void setUseDefaultSuffixPattern(boolean useDefaultSuffixPattern) { @@ -168,8 +168,9 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler */ protected void addUrlsForPath(Set urls, String path) { urls.add(path); - if (this.useDefaultSuffixPattern && path.indexOf('.') == -1) { + if (this.useDefaultSuffixPattern && path.indexOf('.') == -1 && !path.endsWith("/")) { urls.add(path + ".*"); + urls.add(path + "/"); } } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/UriTemplateServletAnnotationControllerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/UriTemplateServletAnnotationControllerTests.java index fd87705ddf32d7e15ad1c2829b6f14145acda154..587f70a9bf9eedb0e5e8deefade3465ab05b2922 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/UriTemplateServletAnnotationControllerTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/UriTemplateServletAnnotationControllerTests.java @@ -152,6 +152,11 @@ public class UriTemplateServletAnnotationControllerTests { servlet.service(request, response); assertEquals("list", response.getContentAsString()); + request = new MockHttpServletRequest("GET", "/hotels/"); + response = new MockHttpServletResponse(); + servlet.service(request, response); + assertEquals("list", response.getContentAsString()); + request = new MockHttpServletRequest("POST", "/hotels"); response = new MockHttpServletResponse(); servlet.service(request, response); @@ -162,6 +167,11 @@ public class UriTemplateServletAnnotationControllerTests { servlet.service(request, response); assertEquals("show-42", response.getContentAsString()); + request = new MockHttpServletRequest("GET", "/hotels/42/"); + response = new MockHttpServletResponse(); + servlet.service(request, response); + assertEquals("show-42", response.getContentAsString()); + request = new MockHttpServletRequest("PUT", "/hotels/42"); response = new MockHttpServletResponse(); servlet.service(request, response);