SPR-6280 - PathVariable resolution does not work properly
This commit is contained in:
@@ -19,6 +19,8 @@ package org.springframework.web.servlet.handler;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -214,13 +216,20 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||
return buildPathExposingHandler(handler, urlPath, null);
|
||||
}
|
||||
// Pattern match?
|
||||
String bestPathMatch = null;
|
||||
List<String> matchingPaths = new ArrayList<String>();
|
||||
for (String registeredPath : this.handlerMap.keySet()) {
|
||||
if (getPathMatcher().match(registeredPath, urlPath) &&
|
||||
(bestPathMatch == null || bestPathMatch.length() < registeredPath.length())) {
|
||||
bestPathMatch = registeredPath;
|
||||
if (getPathMatcher().match(registeredPath, urlPath)) {
|
||||
matchingPaths.add(registeredPath);
|
||||
}
|
||||
}
|
||||
String bestPathMatch = null;
|
||||
if (!matchingPaths.isEmpty()) {
|
||||
Collections.sort(matchingPaths, getPathMatcher().getPatternComparator(urlPath));
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Matching path for request [" + urlPath + "] are " + matchingPaths);
|
||||
}
|
||||
bestPathMatch = matchingPaths.get(0);
|
||||
}
|
||||
if (bestPathMatch != null) {
|
||||
handler = this.handlerMap.get(bestPathMatch);
|
||||
// Bean name or resolved handler?
|
||||
|
||||
@@ -221,6 +221,22 @@ public class UriTemplateServletAnnotationControllerTests {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiPaths() throws Exception {
|
||||
initServlet(MultiPathController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/category/page/5");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("handle4-page-5", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/category/page/5.html");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("handle4-page-5", response.getContentAsString());
|
||||
}
|
||||
|
||||
|
||||
private void initServlet(final Class<?> controllerclass) throws ServletException {
|
||||
servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
@@ -258,6 +274,17 @@ public class UriTemplateServletAnnotationControllerTests {
|
||||
assertEquals("test-hotel.with.dot", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customRegex() throws Exception {
|
||||
initServlet(CustomRegexController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Controllers
|
||||
*/
|
||||
@@ -371,12 +398,24 @@ public class UriTemplateServletAnnotationControllerTests {
|
||||
@RequestMapping("hotels")
|
||||
public static class ImplicitSubPathController {
|
||||
|
||||
@RequestMapping("{hotel}")
|
||||
@RequestMapping("{hotel:.*}")
|
||||
public void handleHotel(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("test-" + hotel);
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class CustomRegexController {
|
||||
|
||||
@RequestMapping("/{root:\\d+}")
|
||||
public void handle(@PathVariable("root") int root, Writer writer) throws IOException {
|
||||
assertEquals("Invalid path variable value", 42, root);
|
||||
writer.write("test-" + root);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
@RequestMapping("hotels")
|
||||
public static class CrudController {
|
||||
@@ -429,4 +468,34 @@ public class UriTemplateServletAnnotationControllerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/category")
|
||||
public static class MultiPathController {
|
||||
|
||||
@RequestMapping(value = {"/{category}/page/{page}", "/**/{category}/page/{page}"})
|
||||
public void category(@PathVariable String category, @PathVariable int page, Writer writer) throws IOException {
|
||||
writer.write("handle1-");
|
||||
writer.write("category-" + category);
|
||||
writer.write("page-" + page);
|
||||
}
|
||||
|
||||
@RequestMapping(value = {"/{category}", "/**/{category}"})
|
||||
public void category(@PathVariable String category, Writer writer) throws IOException {
|
||||
writer.write("handle2-");
|
||||
writer.write("category-" + category);
|
||||
}
|
||||
|
||||
@RequestMapping(value = {""})
|
||||
public void category(Writer writer) throws IOException {
|
||||
writer.write("handle3");
|
||||
}
|
||||
|
||||
@RequestMapping(value = {"/page/{page}"})
|
||||
public void category(@PathVariable int page, Writer writer) throws IOException {
|
||||
writer.write("handle4-");
|
||||
writer.write("page-" + page);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user