SPR-5251: URI Templates support relative @RequestMappings (on class level, with more specific mapping on method level)

This commit is contained in:
Arjen Poutsma 2008-11-19 17:08:34 +00:00
parent 2b2805058b
commit 27ed13f44d
2 changed files with 73 additions and 4 deletions

View File

@ -51,6 +51,7 @@ import org.springframework.ui.Model;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.validation.support.BindingAwareModelMap;
@ -503,6 +504,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
}
if (targetHandlerMethods.size() == 1) {
extractHandlerMethodUriTemplates(targetPathMatches.values().iterator().next(), lookupPath, request);
return targetHandlerMethods.values().iterator().next();
}
else if (!targetHandlerMethods.isEmpty()) {
@ -525,6 +527,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
}
}
extractHandlerMethodUriTemplates(bestPathMatch, lookupPath, request);
return targetHandlerMethods.get(bestMappingMatch);
}
else {
@ -570,6 +573,37 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
private boolean isBetterParamMatch(RequestMappingInfo mapping, RequestMappingInfo mappingToCompare) {
return (mappingToCompare.params.length < mapping.params.length);
}
@SuppressWarnings("unchecked")
private void extractHandlerMethodUriTemplates(String mappedPath, String lookupPath, HttpServletRequest request) {
Map<String, String> variables = null;
boolean hasSuffix = (mappedPath.indexOf('.') != -1);
if (!hasSuffix && pathMatcher.match(mappedPath + ".*", lookupPath)) {
String realPath = mappedPath + ".*";
if (pathMatcher.match(realPath, lookupPath)) {
variables = pathMatcher.extractUriTemplateVariables(realPath, lookupPath);
}
}
if (variables == null && !mappedPath.startsWith("/")) {
String realPath = "/**/" + mappedPath;
if (pathMatcher.match(realPath, lookupPath)) {
variables = pathMatcher.extractUriTemplateVariables(realPath, lookupPath);
} else {
realPath = realPath + ".*";
if (pathMatcher.match(realPath, lookupPath)) {
variables = pathMatcher.extractUriTemplateVariables(realPath, lookupPath);
}
}
}
if (!CollectionUtils.isEmpty(variables)) {
Map<String, String> typeVariables =
(Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
if (typeVariables != null) {
variables.putAll(typeVariables);
}
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, variables);
}
}
}

View File

@ -5,7 +5,6 @@ import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
@ -50,6 +49,26 @@ public class UriTemplateServletAnnotationControllerTests {
assertEquals("test-42", response.getContentAsString());
}
@Test
public void ambiguous() throws Exception {
initServlet(AmbiguousUriTemplateController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/12345");
MockHttpServletResponse response = new MockHttpServletResponse();
servlet.service(request, response);
assertEquals("specific", response.getContentAsString());
}
@Test
public void relative() throws Exception {
initServlet(RelativePathUriTemplateController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21");
MockHttpServletResponse response = new MockHttpServletResponse();
servlet.service(request, response);
assertEquals("test-42-21", response.getContentAsString());
}
private void initServlet(final Class<?> controllerclass) throws ServletException {
servlet = new DispatcherServlet() {
@Override
@ -101,10 +120,26 @@ public class UriTemplateServletAnnotationControllerTests {
@RequestMapping("/hotels/{hotel}/**")
public static class RelativePathUriTemplateController {
@RequestMapping("/bookings/{booking}")
public void handle(@PathVariable("hotel") int hotel, @PathVariable int booking, HttpServletResponse response)
@RequestMapping("bookings/{booking}")
public void handle(@PathVariable("hotel") String hotel, @PathVariable int booking, Writer writer)
throws IOException {
response.getWriter().write("test-" + hotel + "-" + booking);
assertEquals("Invalid path variable value", "42", hotel);
assertEquals("Invalid path variable value", 21, booking);
writer.write("test-" + hotel + "-" + booking);
}
}
@Controller
public static class AmbiguousUriTemplateController {
@RequestMapping("/hotels/{hotel}")
public void handleVars(Writer writer) throws IOException {
writer.write("variables");
}
@RequestMapping("/hotels/12345")
public void handleSpecific(Writer writer) throws IOException {
writer.write("specific");
}
}