SPR-7543 Add @PathVariables to the model

master
Rossen Stoyanchev 14 years ago
parent a4716c2a94
commit ed9d9a402b
  1. 12
      org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolver.java
  2. 2
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapterIntegrationTests.java
  3. 13
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolverTests.java
  4. 30
      org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractNamedValueMethodArgumentResolver.java

@ -27,6 +27,7 @@ import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.annotation.support.AbstractNamedValueMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerMapping;
/**
@ -73,6 +74,17 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
throw new IllegalStateException("Could not find the URL template variable [" + name + "]");
}
@Override
protected void handleResolvedValue(Object arg,
String name,
MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) {
if (mavContainer != null) {
mavContainer.addAttribute(name, arg);
}
}
private static class PathVariableNamedValueInfo extends NamedValueInfo {
private PathVariableNamedValueInfo(PathVariable annotation) {

@ -293,7 +293,7 @@ public class RequestMappingHandlerMethodAdapterIntegrationTests {
@ModelAttribute OtherUser otherUser,
Model model) throws Exception {
model.addAttribute("cookie", cookie).addAttribute("pathvar", pathvar).addAttribute("header", header)
model.addAttribute("cookie", cookie).addAttribute("header", header)
.addAttribute("systemHeader", systemHeader).addAttribute("headerMap", headerMap)
.addAttribute("dateParam", dateParam).addAttribute("paramMap", paramMap)
.addAttribute("paramByConvention", paramByConvention).addAttribute("value", value)

@ -32,6 +32,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.support.PathVariableMethodArgumentResolver;
@ -48,6 +49,8 @@ public class PathVariableMethodArgumentResolverTests {
private MethodParameter paramString;
private ModelAndViewContainer mavContainer;
private ServletWebRequest webRequest;
private MockHttpServletRequest request;
@ -60,6 +63,7 @@ public class PathVariableMethodArgumentResolverTests {
paramNamedString = new MethodParameter(method, 0);
paramString = new MethodParameter(method, 1);
mavContainer = new ModelAndViewContainer();
request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
}
@ -76,13 +80,14 @@ public class PathVariableMethodArgumentResolverTests {
uriTemplateVars.put("name", "value");
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars);
String result = (String) resolver.resolveArgument(paramNamedString, null, webRequest, null);
assertEquals("value", result);
String result = (String) resolver.resolveArgument(paramNamedString, mavContainer, webRequest, null);
assertEquals("PathVariable not resolved correctly", "value", result);
assertEquals("PathVariable not added to the model", "value", mavContainer.getAttribute("name"));
}
@Test(expected = IllegalStateException.class)
public void handleMissingValue() throws Exception {
resolver.resolveArgument(paramNamedString, null, webRequest, null);
resolver.resolveArgument(paramNamedString, mavContainer, webRequest, null);
fail("Unresolved path variable should lead to exception.");
}

@ -42,6 +42,7 @@ import org.springframework.web.method.support.ModelAndViewContainer;
* <li>Obtain named value information for a method parameter
* <li>Resolve names into argument values
* <li>Handle missing argument values when argument values are required
* <li>Optionally handle a resolved value
* </ul>
* <p>A default value string can contain ${...} placeholders and Spring Expression Language #{...} expressions.
* For this to work a {@link ConfigurableBeanFactory} must be supplied to the class constructor.
@ -87,16 +88,17 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
else if (namedValueInfo.required) {
handleMissingValue(namedValueInfo.name, parameter);
}
arg = checkForNull(namedValueInfo.name, arg, paramType);
arg = handleNullValue(namedValueInfo.name, arg, paramType);
}
if (binderFactory != null) {
WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
return binder.convertIfNecessary(arg, paramType, parameter);
}
else {
return arg;
arg = binder.convertIfNecessary(arg, paramType, parameter);
}
handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
return arg;
}
/**
@ -170,7 +172,10 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
*/
protected abstract void handleMissingValue(String name, MethodParameter parameter) throws ServletException;
private Object checkForNull(String name, Object value, Class<?> paramType) {
/**
* A {@code null} results in a {@code false} value for {@code boolean}s or an exception for other primitives.
*/
private Object handleNullValue(String name, Object value, Class<?> paramType) {
if (value == null) {
if (Boolean.TYPE.equals(paramType)) {
return Boolean.FALSE;
@ -184,6 +189,19 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
return value;
}
/**
* Invoked after a value is resolved.
* @param arg the resolved argument value
* @param name the argument name
* @param parameter the argument parameter type
* @param mavContainer the {@link ModelAndViewContainer}, which may be {@code null}
* @param webRequest the current request
*/
protected void handleResolvedValue(Object arg, String name, MethodParameter parameter,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) {
}
/**
* Represents the information about a named value, including name, whether it's required and a default value.
*/

Loading…
Cancel
Save