diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/SmartView.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/SmartView.java new file mode 100644 index 00000000000..55dcdb21d81 --- /dev/null +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/SmartView.java @@ -0,0 +1,32 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.servlet; + +/** + * Interface to be implemented by Views that perform a redirect. + * + * @author Rossen Stoyanchev + * @since 3.1 + */ +public interface SmartView extends View { + + /** + * Whether the view performs a redirect. + */ + boolean isRedirectView(); + +} diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java index 8fc09573f49..2cf5406c34d 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java @@ -74,8 +74,6 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite; import org.springframework.web.method.support.InvocableHandlerMethod; import org.springframework.web.method.support.ModelAndViewContainer; -import org.springframework.web.servlet.FlashMap; -import org.springframework.web.servlet.FlashMapManager; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.mvc.LastModified; @@ -85,7 +83,7 @@ import org.springframework.web.servlet.mvc.method.annotation.support.DefaultMeth import org.springframework.web.servlet.mvc.method.annotation.support.HttpEntityMethodProcessor; import org.springframework.web.servlet.mvc.method.annotation.support.ModelAndViewMethodReturnValueHandler; import org.springframework.web.servlet.mvc.method.annotation.support.PathVariableMethodArgumentResolver; -import org.springframework.web.servlet.mvc.method.annotation.support.RedirectModelMethodArgumentResolver; +import org.springframework.web.servlet.mvc.method.annotation.support.RedirectAttributesMethodArgumentResolver; import org.springframework.web.servlet.mvc.method.annotation.support.RequestPartMethodArgumentResolver; import org.springframework.web.servlet.mvc.method.annotation.support.RequestResponseBodyMethodProcessor; import org.springframework.web.servlet.mvc.method.annotation.support.ServletCookieValueMethodArgumentResolver; @@ -93,7 +91,7 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletMode import org.springframework.web.servlet.mvc.method.annotation.support.ServletRequestMethodArgumentResolver; import org.springframework.web.servlet.mvc.method.annotation.support.ServletResponseMethodArgumentResolver; import org.springframework.web.servlet.mvc.method.annotation.support.ViewMethodReturnValueHandler; -import org.springframework.web.servlet.mvc.support.RedirectModel; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.support.RequestContextUtils; import org.springframework.web.util.WebUtils; @@ -369,7 +367,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i argumentResolvers.addResolver(new ServletRequestMethodArgumentResolver()); argumentResolvers.addResolver(new ServletResponseMethodArgumentResolver()); argumentResolvers.addResolver(new HttpEntityMethodProcessor(messageConverters)); - argumentResolvers.addResolver(new RedirectModelMethodArgumentResolver()); + argumentResolvers.addResolver(new RedirectAttributesMethodArgumentResolver()); argumentResolvers.addResolver(new ModelMethodProcessor()); argumentResolvers.addResolver(new ErrorsMethodArgumentResolver()); @@ -530,15 +528,13 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i } else { ModelMap model = mavContainer.getModel(); - ModelAndView mav = new ModelAndView().addAllObjects(model); - mav.setViewName(mavContainer.getViewName()); + ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model); if (!mavContainer.isViewReference()) { mav.setView((View) mavContainer.getView()); } - if (model instanceof RedirectModel) { - RedirectModel redirectModel = (RedirectModel) model; - FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request); - flashMap.putAll(redirectModel.getFlashAttributes()); + if (model instanceof RedirectAttributes) { + Map flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); + RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } return mav; } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectModelMethodArgumentResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectAttributesMethodArgumentResolver.java similarity index 73% rename from org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectModelMethodArgumentResolver.java rename to org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectAttributesMethodArgumentResolver.java index 5c353b794f7..caf8749e610 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectModelMethodArgumentResolver.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectAttributesMethodArgumentResolver.java @@ -16,6 +16,8 @@ package org.springframework.web.servlet.mvc.method.annotation.support; +import java.util.Map; + import org.springframework.core.MethodParameter; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; @@ -25,21 +27,22 @@ import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.annotation.support.ModelMethodProcessor; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; -import org.springframework.web.servlet.mvc.support.RedirectModel; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap; /** - * Resolves {@link RedirectModel} method arguments. + * Resolves {@link RedirectAttributesModelMap} method arguments. * *

This resolver must be listed ahead of the {@link ModelMethodProcessor}, - * which also resolves arguments of type {@link Model}. + * which also resolves arguments of type {@link Map} and {@link Model}. * * @author Rossen Stoyanchev * @since 3.1 */ -public class RedirectModelMethodArgumentResolver implements HandlerMethodArgumentResolver { +public class RedirectAttributesMethodArgumentResolver implements HandlerMethodArgumentResolver { public boolean supportsParameter(MethodParameter parameter) { - return RedirectModel.class.equals(parameter.getParameterType()); + return RedirectAttributes.class.isAssignableFrom(parameter.getParameterType()); } public Object resolveArgument(MethodParameter parameter, @@ -47,10 +50,9 @@ public class RedirectModelMethodArgumentResolver implements HandlerMethodArgumen NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null); - ModelMap implicitModel = mavContainer.getModel(); - RedirectModel redirectModel = new RedirectModel(dataBinder, implicitModel); - mavContainer.setRedirectModel(redirectModel); - return redirectModel; + ModelMap attributes = new RedirectAttributesModelMap(dataBinder); + mavContainer.setRedirectModel(attributes); + return attributes; } } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java index bd90fe91a9e..280c9608b4f 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java @@ -23,6 +23,7 @@ import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.RequestToViewNameTranslator; +import org.springframework.web.servlet.SmartView; import org.springframework.web.servlet.View; /** @@ -60,14 +61,14 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan String viewName = (String) returnValue; mavContainer.setViewName(viewName); if (isRedirectViewName(viewName)) { - mavContainer.useRedirectModel(); + mavContainer.setRedirectModelEnabled(); } } else if (returnValue instanceof View){ View view = (View) returnValue; mavContainer.setView(view); if (isRedirectView(view)) { - mavContainer.useRedirectModel(); + mavContainer.setRedirectModelEnabled(); } } else { @@ -94,7 +95,12 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan * "false" otherwise. */ protected boolean isRedirectView(View view) { - return "RedirectView".equals(view.getClass().getSimpleName()); + if (SmartView.class.isAssignableFrom(view.getClass())) { + return ((SmartView) view).isRedirectView(); + } + else { + return false; + } } } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectAttributes.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectAttributes.java new file mode 100644 index 00000000000..11e6f077428 --- /dev/null +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectAttributes.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.servlet.mvc.support; + +import java.util.Collection; +import java.util.Map; + +import org.springframework.ui.Model; + +/** + * A {@link Model} that can also store attributes candidate for flash storage. + * + * @author Rossen Stoyanchev + * @since 3.1 + */ +public interface RedirectAttributes extends Model { + + /** + * Add the supplied attribute under the supplied name. + * @param attributeName the name of the model attribute (never null) + * @param attributeValue the model attribute value (can be null) + */ + RedirectAttributes addAttribute(String attributeName, Object attributeValue); + + /** + * Add the supplied attribute to this Map using a + * {@link org.springframework.core.Conventions#getVariableName generated name}. + *

Note: Empty {@link java.util.Collection Collections} are not added to + * the model when using this method because we cannot correctly determine + * the true convention name. View code should check for null rather + * than for empty collections as is already done by JSTL tags. + * @param attributeValue the model attribute value (never null) + */ + RedirectAttributes addAttribute(Object attributeValue); + + /** + * Copy all attributes in the supplied Collection into this + * Map, using attribute name generation for each element. + * @see #addAttribute(Object) + */ + RedirectAttributes addAllAttributes(Collection attributeValues); + + /** + * Copy all attributes in the supplied Map into this Map. + * @see #addAttribute(String, Object) + */ + Model addAllAttributes(Map attributes); + + /** + * Copy all attributes in the supplied Map into this Map, + * with existing objects of the same name taking precedence (i.e. not getting + * replaced). + */ + RedirectAttributes mergeAttributes(Map attributes); + + /** + * Add the given attribute as a candidate for flash storage. + * @param attributeName the flash attribute name; never null + * @param attributeValue the flash attribute value; may be null + */ + RedirectAttributes addFlashAttribute(String attributeName, Object attributeValue); + + /** + * Add the given attribute value as a candidate for flash storage using a + * {@link org.springframework.core.Conventions#getVariableName generated name}. + * @param attributeValue the flash attribute value; never null + */ + RedirectAttributes addFlashAttribute(Object attributeValue); + + /** + * Return the attributes candidate for flash storage. + */ + Map getFlashAttributes(); + +} \ No newline at end of file diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectAttributesModelMap.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectAttributesModelMap.java new file mode 100644 index 00000000000..0dc565e0077 --- /dev/null +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectAttributesModelMap.java @@ -0,0 +1,157 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.servlet.mvc.support; + +import java.util.Collection; +import java.util.Map; + +import org.springframework.ui.ModelMap; +import org.springframework.validation.DataBinder; + +/** + * A {@link ModelMap} that implements the {@link RedirectAttributes} interface. + * + *

Attributes are formatted and stored as Strings so they can be used as URI + * variables or as query parameters in the redirect URL. Alternatively, + * attributes may also be added as flash attributes in order to request storing + * them until the next request without affecting the redirect URL. + * + * @author Rossen Stoyanchev + * @since 3.1 + */ +@SuppressWarnings("serial") +public class RedirectAttributesModelMap extends ModelMap implements RedirectAttributes { + + private final DataBinder dataBinder; + + private final ModelMap flashAttributes = new ModelMap(); + + /** + * Default constructor without a DataBinder. + * Redirect attribute values will be formatted via {@link #toString()}. + */ + public RedirectAttributesModelMap() { + this(null); + } + + /** + * Constructor with a DataBinder to use to format redirect attribute values. + * @param dataBinder a DataBinder for converting attribute values to String. + */ + public RedirectAttributesModelMap(DataBinder dataBinder) { + this.dataBinder = dataBinder; + } + + /** + * Return the attributes candidate for flash storage. + */ + public Map getFlashAttributes() { + return flashAttributes; + } + + /** + * Format the attribute value as a String and add it. If the value is + * {@code null} it is not be added. + * @param attributeName the attribute name; never null + * @param attributeValue the attribute value; skipped if null + */ + public RedirectAttributesModelMap addAttribute(String attributeName, Object attributeValue) { + if (attributeValue != null) { + super.addAttribute(attributeName, formatValue(attributeValue)); + } + return this; + } + + private String formatValue(Object value) { + return (dataBinder != null) ? dataBinder.convertIfNecessary(value, String.class) : value.toString(); + } + + /** + * Add an attribute using a + * {@link org.springframework.core.Conventions#getVariableName generated name}. + * Before being added the attribute value is formatted as a String. + * @param attributeValue the attribute value; never null + */ + public RedirectAttributesModelMap addAttribute(Object attributeValue) { + super.addAttribute(attributeValue); + return this; + } + + /** + * Copy all attributes in the supplied Collection into this + * Model using attribute name generation for each element. + * @see #addAttribute(Object) + */ + public RedirectAttributesModelMap addAllAttributes(Collection attributeValues) { + super.addAllAttributes(attributeValues); + return this; + } + + /** + * Copy all supplied attributes into this model. + * @see #addAttribute(String, Object) + */ + public RedirectAttributesModelMap addAllAttributes(Map attributes) { + if (attributes != null) { + for (String key : attributes.keySet()) { + addAttribute(key, attributes.get(key)); + } + } + return this; + } + + /** + * Copy all supplied attributes into this model with with existing + * attributes of the same name taking precedence (i.e. not getting replaced). + * @see #addAttribute(String, Object) + */ + public RedirectAttributesModelMap mergeAttributes(Map attributes) { + if (attributes != null) { + for (String key : attributes.keySet()) { + if (!containsKey(key)) { + addAttribute(key, attributes.get(key)); + } + } + } + return this; + } + + public Map asMap() { + return this; + } + + /** + * Add the given attribute as a candidate for flash storage. + * @param attributeName the flash attribute name; never null + * @param attributeValue the flash attribute value; may be null + */ + public RedirectAttributes addFlashAttribute(String attributeName, Object attributeValue) { + this.flashAttributes.addAttribute(attributeName, attributeValue); + return this; + } + + /** + * Add the given attribute value as a candidate for flash storage using a + * {@link org.springframework.core.Conventions#getVariableName generated name}. + * @param attributeValue the flash attribute value; never null + */ + public RedirectAttributes addFlashAttribute(Object attributeValue) { + this.flashAttributes.addAttribute(attributeValue); + return this; + } + +} diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectModel.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectModel.java deleted file mode 100644 index 209e9591914..00000000000 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectModel.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.web.servlet.mvc.support; - -import java.beans.PropertyEditor; -import java.util.Collection; -import java.util.Map; - -import org.springframework.core.convert.converter.Converter; -import org.springframework.format.Formatter; -import org.springframework.ui.ExtendedModelMap; -import org.springframework.ui.Model; -import org.springframework.ui.ModelMap; -import org.springframework.util.Assert; -import org.springframework.validation.DataBinder; - -/** - * A {@link Model} implementation that controllers can use when they wish to - * redirect. For a redirect a controller needs to use an empty model and - * only add those attributes that will be used in the redirect URL -- - * either embedded as URI template variables or appended as query parameters. - * To be used in the URL such attributes need to be formatted as String - * values. Alternatively a controller may choose to keep attributes in - * flash storage instead for the duration of the redirect. - * - *

A RedirectModel serves the above needs as follows: - *

- * - *

Note that a RedirectModel will not be used unless the controller decides - * to redirect. - * - * @author Rossen Stoyanchev - * @since 3.1 - */ -@SuppressWarnings("serial") -public class RedirectModel extends ExtendedModelMap { - - private final DataBinder dataBinder; - - private final ModelMap flashAttributes = new ModelMap(); - - private final ModelMap implicitModel; - - /** - * Create a new instance without a DataBinder. Attribute values will be - * formatted via {@link #toString()}. - */ - public RedirectModel() { - this(null, null); - } - - /** - * Create a new instance providing a DataBinder to use for formatting - * attribute values. - * @param dataBinder a DataBinder for converting attribute values to String. - * @param implicitModel the implicit model for the current request; - * used in conjunction with {@link #addModelAttributes(String...)} - * to copy attributes from the implicit model to the redirect model. - */ - public RedirectModel(DataBinder dataBinder, ModelMap implicitModel) { - this.dataBinder = dataBinder; - this.implicitModel = implicitModel; - } - - /** - * Return the attributes candidate for flash storage. - */ - public Map getFlashAttributes() { - return flashAttributes; - } - - /** - * Add an attribute. Before being added the attribute value is formatted as - * a String in preparation for use in the redirect URL. If the attribute - * value is null it is not be added to the model. - * @param attributeName the attribute name; never null - * @param attributeValue the attribute value; skipped if null - */ - public RedirectModel addAttribute(String attributeName, Object attributeValue) { - if (attributeValue != null) { - super.addAttribute(attributeName, formatValue(attributeValue)); - } - return this; - } - - private String formatValue(Object value) { - return (dataBinder != null) ? dataBinder.convertIfNecessary(value, String.class) : value.toString(); - } - - /** - * Add an attribute using a - * {@link org.springframework.core.Conventions#getVariableName generated name}. - * Before being added the attribute value is formatted as a String. - * @param attributeValue the attribute value; never null - */ - public RedirectModel addAttribute(Object attributeValue) { - super.addAttribute(attributeValue); - return this; - } - - /** - * Copy all attributes in the supplied Collection into this - * Model using attribute name generation for each element. - * @see #addAttribute(Object) - */ - public RedirectModel addAllAttributes(Collection attributeValues) { - super.addAllAttributes(attributeValues); - return this; - } - - /** - * Copy all supplied attributes into this redirect model. - * @see #addAttribute(String, Object) - */ - public RedirectModel addAllAttributes(Map attributes) { - if (attributes != null) { - for (String key : attributes.keySet()) { - addAttribute(key, attributes.get(key)); - } - } - return this; - } - - /** - * Copy all supplied attributes into this redirect model with with existing - * attributes of the same name taking precedence (i.e. not getting replaced). - * @see #addAttribute(String, Object) - */ - public RedirectModel mergeAttributes(Map attributes) { - if (attributes != null) { - for (String key : attributes.keySet()) { - if (!containsKey(key)) { - addAttribute(key, attributes.get(key)); - } - } - } - return this; - } - - /** - * Copy the attributes specified by name from the "implicit" model of the - * current request to this redirect model instance. - * @param attributeNames the names of attributes present in the implicit model. - * attribute names are required to be present; if an attribute is present - * but is null, it is skipped - * @see #addAttribute(String, Object) - */ - public RedirectModel addModelAttributes(String... attributeNames) { - Assert.notNull(this.implicitModel, "The implicit model has not been set."); - for (String name : attributeNames) { - Assert.isTrue(this.implicitModel.containsAttribute(name), name + " not found in implicit model"); - Object value = this.implicitModel.get(name); - addAttribute(name, value); - } - return this; - } - - /** - * Add the given attribute as a candidate for flash storage. - * @param attributeName the flash attribute name; never null - * @param attributeValue the flash attribute value; may be null - */ - public RedirectModel addFlashAttribute(String attributeName, Object attributeValue) { - this.flashAttributes.addAttribute(attributeName, attributeValue); - return this; - } - - /** - * Add the given attribute value as a candidate for flash storage using a - * {@link org.springframework.core.Conventions#getVariableName generated name}. - * @param attributeValue the flash attribute value; never null - */ - public RedirectModel addFlashAttribute(Object attributeValue) { - this.flashAttributes.addAttribute(attributeValue); - return this; - } - -} 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 d5e8cd8826f..2948f42ae31 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 @@ -40,6 +40,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.web.servlet.FlashMap; import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.SmartView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.support.RequestContextUtils; import org.springframework.web.util.UriTemplate; @@ -85,7 +86,7 @@ import org.springframework.web.util.WebUtils; * @see #setExposeModelAttributes * @see javax.servlet.http.HttpServletResponse#sendRedirect */ -public class RedirectView extends AbstractUrlBasedView { +public class RedirectView extends AbstractUrlBasedView implements SmartView { private boolean contextRelative = false; @@ -216,6 +217,13 @@ public class RedirectView extends AbstractUrlBasedView { this.statusCode = statusCode; } + /** + * Returns "true" indicating this view performs a redirect. + */ + public boolean isRedirectView() { + return true; + } + /** * Convert model to request parameters and redirect to the given URL. * @see #appendQueryProperties diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java index 293d4cc6201..75ce089bc4e 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java @@ -138,7 +138,7 @@ import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver; import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebArgumentResolverAdapter; -import org.springframework.web.servlet.mvc.support.RedirectModel; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.support.RequestContextUtils; import org.springframework.web.servlet.view.InternalResourceViewResolver; @@ -2816,13 +2816,13 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl } @RequestMapping(value = "/messages", method = RequestMethod.POST) - public String sendMessage(TestBean testBean, BindingResult result, RedirectModel redirectModel) { + public String sendMessage(TestBean testBean, BindingResult result, RedirectAttributes redirectAttrs) { if (result.hasErrors()) { return "messages/new"; } else { - redirectModel.addAttribute("id", "1").addAttribute("name", "value"); - redirectModel.addFlashAttribute("successMessage", "yay!"); + redirectAttrs.addAttribute("id", "1").addAttribute("name", "value") + .addFlashAttribute("successMessage", "yay!"); return "redirect:/messages/{id}"; } } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandlerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandlerTests.java index e6e77e808bf..9e5c1e0f333 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandlerTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandlerTests.java @@ -26,10 +26,12 @@ import org.junit.Before; import org.junit.Test; import org.springframework.core.MethodParameter; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.ui.ModelMap; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.View; -import org.springframework.web.servlet.mvc.support.RedirectModel; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap; import org.springframework.web.servlet.view.InternalResourceView; import org.springframework.web.servlet.view.RedirectView; @@ -70,7 +72,7 @@ public class ViewMethodReturnValueHandlerTests { @Test public void returnViewRedirect() throws Exception { RedirectView redirectView = new RedirectView("testView"); - RedirectModel redirectModel = new RedirectModel(); + ModelMap redirectModel = new RedirectAttributesModelMap(); mavContainer.setRedirectModel(redirectModel); handler.handleReturnValue(redirectView, createMethodParam("view"), mavContainer, webRequest); @@ -87,7 +89,7 @@ public class ViewMethodReturnValueHandlerTests { @Test public void returnViewNameRedirect() throws Exception { - RedirectModel redirectModel = new RedirectModel(); + ModelMap redirectModel = new RedirectAttributesModelMap(); mavContainer.setRedirectModel(redirectModel); handler.handleReturnValue("redirect:testView", createMethodParam("viewName"), mavContainer, webRequest); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/support/RedirectModelTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/support/RedirectAttributesModelMapTests.java similarity index 58% rename from org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/support/RedirectModelTests.java rename to org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/support/RedirectAttributesModelMapTests.java index 06b8e363ad8..e67da0b9ab2 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/support/RedirectModelTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/support/RedirectAttributesModelMapTests.java @@ -28,57 +28,53 @@ import org.springframework.beans.TestBean; import org.springframework.core.convert.converter.Converter; import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.format.support.FormattingConversionService; -import org.springframework.ui.ModelMap; import org.springframework.validation.DataBinder; /** * - * Test fixture for RedirectModel tests. + * Test fixture for {@link RedirectAttributesModelMap} tests. * * @author Rossen Stoyanchev * @since 3.1 */ -public class RedirectModelTests { +public class RedirectAttributesModelMapTests { - private RedirectModel redirectModel; + private RedirectAttributesModelMap redirectAttributes; private FormattingConversionService conversionService; - private ModelMap implicitModel; - @Before public void setup() { this.conversionService = new DefaultFormattingConversionService(); DataBinder dataBinder = new DataBinder(null); dataBinder.setConversionService(conversionService); - this.implicitModel = new ModelMap(); - this.redirectModel = new RedirectModel(dataBinder, implicitModel); + this.redirectAttributes = new RedirectAttributesModelMap(dataBinder); } @Test public void addAttributePrimitiveType() { - this.redirectModel.addAttribute("speed", 65); - assertEquals("65", this.redirectModel.get("speed")); + this.redirectAttributes.addAttribute("speed", 65); + assertEquals("65", this.redirectAttributes.get("speed")); } @Test public void addAttributeCustomType() { String attrName = "person"; - this.redirectModel.addAttribute(attrName, new TestBean("Fred")); + this.redirectAttributes.addAttribute(attrName, new TestBean("Fred")); - assertEquals("ConversionService should have invoked toString()", "Fred", this.redirectModel.get(attrName)); + assertEquals("ConversionService should have invoked toString()", "Fred", this.redirectAttributes.get(attrName)); this.conversionService.addConverter(new TestBeanConverter()); - this.redirectModel.addAttribute(attrName, new TestBean("Fred")); + this.redirectAttributes.addAttribute(attrName, new TestBean("Fred")); - assertEquals("Type converter should have been used", "[Fred]", this.redirectModel.get(attrName)); + assertEquals("Type converter should have been used", "[Fred]", this.redirectAttributes.get(attrName)); } @Test public void addAttributeToString() { String attrName = "person"; - RedirectModel model = new RedirectModel(); + RedirectAttributesModelMap model = new RedirectAttributesModelMap(); model.addAttribute(attrName, new TestBean("Fred")); assertEquals("toString() should have been used", "Fred", model.get(attrName)); @@ -86,17 +82,17 @@ public class RedirectModelTests { @Test public void addAttributeValue() { - this.redirectModel.addAttribute(new TestBean("Fred")); + this.redirectAttributes.addAttribute(new TestBean("Fred")); - assertEquals("Fred", this.redirectModel.get("testBean")); + assertEquals("Fred", this.redirectAttributes.get("testBean")); } @Test public void addAllAttributesList() { - this.redirectModel.addAllAttributes(Arrays.asList(new TestBean("Fred"), new Integer(5))); + this.redirectAttributes.addAllAttributes(Arrays.asList(new TestBean("Fred"), new Integer(5))); - assertEquals("Fred", this.redirectModel.get("testBean")); - assertEquals("5", this.redirectModel.get("integer")); + assertEquals("Fred", this.redirectAttributes.get("testBean")); + assertEquals("5", this.redirectAttributes.get("integer")); } @Test @@ -104,10 +100,10 @@ public class RedirectModelTests { Map map = new HashMap(); map.put("person", new TestBean("Fred")); map.put("age", 33); - this.redirectModel.addAllAttributes(map); + this.redirectAttributes.addAllAttributes(map); - assertEquals("Fred", this.redirectModel.get("person")); - assertEquals("33", this.redirectModel.get("age")); + assertEquals("Fred", this.redirectAttributes.get("person")); + assertEquals("33", this.redirectAttributes.get("age")); } @Test @@ -116,27 +112,11 @@ public class RedirectModelTests { map.put("person", new TestBean("Fred")); map.put("age", 33); - this.redirectModel.addAttribute("person", new TestBean("Ralph")); - this.redirectModel.mergeAttributes(map); + this.redirectAttributes.addAttribute("person", new TestBean("Ralph")); + this.redirectAttributes.mergeAttributes(map); - assertEquals("Ralph", this.redirectModel.get("person")); - assertEquals("33", this.redirectModel.get("age")); - } - - @Test - public void addModelAttributes() { - this.implicitModel.addAttribute("person", new TestBean("Ralph")); - this.implicitModel.addAttribute("age", 33); - - this.redirectModel.addModelAttributes("person", "age"); - - assertEquals("Ralph", this.redirectModel.get("person")); - assertEquals("33", this.redirectModel.get("age")); - } - - @Test(expected=IllegalArgumentException.class) - public void addModelAttributesInvalidName() { - this.redirectModel.addModelAttributes("person"); + assertEquals("Ralph", this.redirectAttributes.get("person")); + assertEquals("33", this.redirectAttributes.get("age")); } public static class TestBeanConverter implements Converter {