From c172d9d745c30c90dbba416cb15b38b7e9b54fb3 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 13 Apr 2015 15:33:25 -0400 Subject: [PATCH] Add trailing slash support to AbstractUrlHandlerMapping Issue: SPR-12818 --- .../handler/AbstractUrlHandlerMapping.java | 27 +++++++++++++++++++ .../handler/SimpleUrlHandlerMappingTests.java | 5 ++++ .../web/servlet/handler/map2.xml | 2 ++ 3 files changed, 34 insertions(+) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java index 1817dae326..5d6406e5d9 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java @@ -54,6 +54,8 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping { private Object rootHandler; + private boolean useTrailingSlashMatch = false; + private boolean lazyInitHandlers = false; private final Map handlerMap = new LinkedHashMap(); @@ -76,6 +78,22 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping { return this.rootHandler; } + /** + * Whether to match to URLs irrespective of the presence of a trailing slash. + * If enabled a URL pattern such as "/users" also matches to "/users/". + *

The default value is {@code false}. + */ + public void setUseTrailingSlashMatch(boolean useTrailingSlashMatch) { + this.useTrailingSlashMatch = useTrailingSlashMatch; + } + + /** + * Whether to match to URLs irrespective of the presence of a trailing slash. + */ + public boolean useTrailingSlashMatch() { + return this.useTrailingSlashMatch; + } + /** * Set whether to lazily initialize handlers. Only applicable to * singleton handlers, as prototypes are always lazily initialized. @@ -159,6 +177,11 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping { if (getPathMatcher().match(registeredPattern, urlPath)) { matchingPatterns.add(registeredPattern); } + else if (useTrailingSlashMatch()) { + if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) { + matchingPatterns.add(registeredPattern +"/"); + } + } } String bestPatternMatch = null; Comparator patternComparator = getPathMatcher().getPatternComparator(urlPath); @@ -171,6 +194,10 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping { } if (bestPatternMatch != null) { handler = this.handlerMap.get(bestPatternMatch); + if (handler == null) { + Assert.isTrue(bestPatternMatch.endsWith("/")); + handler = this.handlerMap.get(bestPatternMatch.substring(0, bestPatternMatch.length() - 1)); + } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java index 27a782788b..dd6b09bd2c 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java @@ -110,6 +110,11 @@ public class SimpleUrlHandlerMappingTests { assertTrue("Handler is correct bean", hec != null && hec.getHandler() == otherBean); assertEquals("welcome.x", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)); + req = new MockHttpServletRequest("GET", "/welcome/"); + hec = getHandler(hm, req); + assertTrue("Handler is correct bean", hec != null && hec.getHandler() == otherBean); + assertEquals("welcome", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)); + req = new MockHttpServletRequest("GET", "/"); req.setServletPath("/welcome.html"); hec = getHandler(hm, req); diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/handler/map2.xml b/spring-webmvc/src/test/resources/org/springframework/web/servlet/handler/map2.xml index 9e89531838..92adae2d15 100644 --- a/spring-webmvc/src/test/resources/org/springframework/web/servlet/handler/map2.xml +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/handler/map2.xml @@ -6,6 +6,7 @@ + @@ -22,6 +23,7 @@ +