From 3fb753bc0c1477d828ba58963d1e4caf8a7d5265 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 2 Aug 2011 08:27:26 +0000 Subject: [PATCH] SPR-8448 Use URI template vars rather than path vars in RedirectView --- .../web/servlet/view/RedirectView.java | 46 +++++++++++-------- .../view/RedirectViewUriTemplateTests.java | 24 +++++----- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java index 0a3f5893eff..4c7777c5b1a 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java @@ -22,7 +22,6 @@ import java.lang.reflect.Array; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -38,6 +37,8 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.beans.BeanUtils; import org.springframework.http.HttpStatus; import org.springframework.util.ObjectUtils; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.View; import org.springframework.web.util.UriTemplate; import org.springframework.web.util.UriUtils; @@ -47,8 +48,8 @@ import org.springframework.web.util.WebUtils; *

View that redirects to an absolute, context relative, or current request * relative URL. The URL may be a URI template in which case the URI template * variables will be replaced with values available in the model. By default - * all primitive model attributes (or collections thereof), not used to fill - * in URI tempate variables, are exposed as HTTP query parameters, but this + * all primitive model attributes (or collections thereof), not used as URI + * template variables, are exposed as HTTP query parameters, but this * behavior can be changed by overriding the * {@link #isEligibleProperty(String, Object)} method. * @@ -99,6 +100,7 @@ public class RedirectView extends AbstractUrlBasedView { * Constructor for use as a bean. */ public RedirectView() { + setExposePathVariables(false); } /** @@ -110,6 +112,7 @@ public class RedirectView extends AbstractUrlBasedView { */ public RedirectView(String url) { super(url); + setExposePathVariables(false); } /** @@ -121,6 +124,7 @@ public class RedirectView extends AbstractUrlBasedView { public RedirectView(String url, boolean contextRelative) { super(url); this.contextRelative = contextRelative; + setExposePathVariables(false); } /** @@ -134,6 +138,7 @@ public class RedirectView extends AbstractUrlBasedView { super(url); this.contextRelative = contextRelative; this.http10Compatible = http10Compatible; + setExposePathVariables(false); } /** @@ -150,6 +155,7 @@ public class RedirectView extends AbstractUrlBasedView { this.contextRelative = contextRelative; this.http10Compatible = http10Compatible; this.exposeModelAttributes = exposeModelAttributes; + setExposePathVariables(false); } @@ -245,23 +251,32 @@ public class RedirectView extends AbstractUrlBasedView { enc = WebUtils.DEFAULT_CHARACTER_ENCODING; } - UriTemplate redirectUri = createUriTemplate(targetUrl, enc); - if (redirectUri.getVariableNames().size() > 0) { - targetUrl = new StringBuilder(redirectUri.expand(model).toString()); - model = removeKeys(model, redirectUri.getVariableNames()); + UriTemplate uriTemplate = createUriTemplate(targetUrl, enc); + if (uriTemplate.getVariableNames().size() > 0) { + Map vars = new HashMap(); + vars.putAll(getCurrentUriVars(request)); + vars.putAll(model); + targetUrl = new StringBuilder(uriTemplate.expand(vars).toString()); + model = removeKeys(model, uriTemplate.getVariableNames()); } if (this.exposeModelAttributes) { - List pathVarNames = getPathVarNames(request); - if (!pathVarNames.isEmpty()) { - model = removeKeys(model, pathVarNames); - } appendQueryProperties(targetUrl, model, enc); } return targetUrl.toString(); } + /** + * Returns the URI template variables extracted from the current request. + */ + @SuppressWarnings("unchecked") + private Map getCurrentUriVars(HttpServletRequest request) { + String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; + Map map = (Map) request.getAttribute(name); + return (map != null) ? map : new HashMap(); + } + @SuppressWarnings("serial") private UriTemplate createUriTemplate(StringBuilder targetUrl, final String encoding) { return new UriTemplate(targetUrl.toString()) { @@ -287,15 +302,6 @@ public class RedirectView extends AbstractUrlBasedView { return result; } - /** - * Returns the names of PathVariable for the current request; or an empty list. - */ - @SuppressWarnings("unchecked") - private List getPathVarNames(HttpServletRequest request) { - Map map = (Map) request.getAttribute(View.PATH_VARIABLES); - return (map != null) ? new ArrayList(map.keySet()) : Collections.emptyList(); - } - /** * Append query properties to the redirect URL. * Stringifies, URL-encodes and formats model attributes as query properties. diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java index e6b1f962e90..c573a50e996 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java @@ -25,7 +25,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.web.servlet.View; +import org.springframework.web.servlet.HandlerMapping; public class RedirectViewUriTemplateTests { @@ -75,21 +75,23 @@ public class RedirectViewUriTemplateTests { } @Test - public void doNotAppendUriTemplateVarFromCurrentRequest() throws Exception { + public void currentRequestUriTemplateVars() throws Exception { Map model = new HashMap(); - model.put("name1", "value1"); - model.put("name2", "value2"); - model.put("name3", "value3"); + model.put("key1", "value1"); + model.put("name", "value2"); + model.put("key3", "value3"); - Map uriTemplatVars = new HashMap(); - uriTemplatVars.put("name1", "value1"); - uriTemplatVars.put("name2", "value2"); - request.setAttribute(View.PATH_VARIABLES, uriTemplatVars); + Map vars = new HashMap(); + vars.put("var1", "v1"); + vars.put("name", "v2"); + vars.put("var3", "v3"); + request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, vars); String url = "http://url.somewhere.com"; - RedirectView redirectView = new RedirectView(url + "/{name2}"); + RedirectView redirectView = new RedirectView(url + "/{key1}/{var1}/{name}"); redirectView.renderMergedOutputModel(model, request, response); - assertEquals(url + "/value2?name3=value3", response.getRedirectedUrl()); + assertEquals(url + "/value1/v1/value2?key3=value3", response.getRedirectedUrl()); } + }