Add trailing slash support to AbstractUrlHandlerMapping
Issue: SPR-12818
This commit is contained in:
parent
b18053f93a
commit
c172d9d745
|
@ -54,6 +54,8 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||||
|
|
||||||
private Object rootHandler;
|
private Object rootHandler;
|
||||||
|
|
||||||
|
private boolean useTrailingSlashMatch = false;
|
||||||
|
|
||||||
private boolean lazyInitHandlers = false;
|
private boolean lazyInitHandlers = false;
|
||||||
|
|
||||||
private final Map<String, Object> handlerMap = new LinkedHashMap<String, Object>();
|
private final Map<String, Object> handlerMap = new LinkedHashMap<String, Object>();
|
||||||
|
@ -76,6 +78,22 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||||
return this.rootHandler;
|
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/".
|
||||||
|
* <p>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
|
* Set whether to lazily initialize handlers. Only applicable to
|
||||||
* singleton handlers, as prototypes are always lazily initialized.
|
* singleton handlers, as prototypes are always lazily initialized.
|
||||||
|
@ -159,6 +177,11 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||||
if (getPathMatcher().match(registeredPattern, urlPath)) {
|
if (getPathMatcher().match(registeredPattern, urlPath)) {
|
||||||
matchingPatterns.add(registeredPattern);
|
matchingPatterns.add(registeredPattern);
|
||||||
}
|
}
|
||||||
|
else if (useTrailingSlashMatch()) {
|
||||||
|
if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {
|
||||||
|
matchingPatterns.add(registeredPattern +"/");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
String bestPatternMatch = null;
|
String bestPatternMatch = null;
|
||||||
Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
|
Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
|
||||||
|
@ -171,6 +194,10 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||||
}
|
}
|
||||||
if (bestPatternMatch != null) {
|
if (bestPatternMatch != null) {
|
||||||
handler = this.handlerMap.get(bestPatternMatch);
|
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?
|
// Bean name or resolved handler?
|
||||||
if (handler instanceof String) {
|
if (handler instanceof String) {
|
||||||
String handlerName = (String) handler;
|
String handlerName = (String) handler;
|
||||||
|
|
|
@ -110,6 +110,11 @@ public class SimpleUrlHandlerMappingTests {
|
||||||
assertTrue("Handler is correct bean", hec != null && hec.getHandler() == otherBean);
|
assertTrue("Handler is correct bean", hec != null && hec.getHandler() == otherBean);
|
||||||
assertEquals("welcome.x", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
|
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 = new MockHttpServletRequest("GET", "/");
|
||||||
req.setServletPath("/welcome.html");
|
req.setServletPath("/welcome.html");
|
||||||
hec = getHandler(hm, req);
|
hec = getHandler(hm, req);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
|
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
|
||||||
<property name="defaultHandler"><ref local="starController"/></property>
|
<property name="defaultHandler"><ref local="starController"/></property>
|
||||||
<property name="rootHandler"><ref local="mainController"/></property>
|
<property name="rootHandler"><ref local="mainController"/></property>
|
||||||
|
<property name="useTrailingSlashMatch" value="true"/>
|
||||||
<property name="urlMap">
|
<property name="urlMap">
|
||||||
<map>
|
<map>
|
||||||
<entry key="/welcome*"><ref local="otherController"/></entry>
|
<entry key="/welcome*"><ref local="otherController"/></entry>
|
||||||
|
@ -22,6 +23,7 @@
|
||||||
<bean id="urlMappingWithProps" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
|
<bean id="urlMappingWithProps" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
|
||||||
<property name="defaultHandler"><ref local="starController"/></property>
|
<property name="defaultHandler"><ref local="starController"/></property>
|
||||||
<property name="rootHandler"><ref local="mainController"/></property>
|
<property name="rootHandler"><ref local="mainController"/></property>
|
||||||
|
<property name="useTrailingSlashMatch" value="true"/>
|
||||||
<property name="mappings"><ref local="propsForUrlMapping2"/></property>
|
<property name="mappings"><ref local="propsForUrlMapping2"/></property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue