SPR-8698 Support flash attrs and a ModelAndView return value.

Before this change, flash attributes could only be added if via
RedirectAttributes.addFlashAttribute(..) if the method returned
a view name or a View instance. With this change, the above is
supported with a ModelAndView return value as well.
This commit is contained in:
Rossen Stoyanchev
2012-01-09 20:18:44 -05:00
parent fe0ffec8b9
commit 66df039b03
2 changed files with 79 additions and 16 deletions

View File

@@ -21,6 +21,8 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.SmartView;
import org.springframework.web.servlet.View;
/** /**
* Handles return values of type {@link ModelAndView} copying view and model * Handles return values of type {@link ModelAndView} copying view and model
@@ -48,17 +50,29 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
MethodParameter returnType, MethodParameter returnType,
ModelAndViewContainer mavContainer, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception { NativeWebRequest webRequest) throws Exception {
if (returnValue != null) { if (returnValue == null) {
ModelAndView mav = (ModelAndView) returnValue; mavContainer.setRequestHandled(true);
mavContainer.setViewName(mav.getViewName()); return;
if (!mav.isReference()) { }
mavContainer.setView(mav.getView());
ModelAndView mav = (ModelAndView) returnValue;
if (mav.isReference()) {
String viewName = mav.getViewName();
mavContainer.setViewName(viewName);
if (viewName != null && viewName.startsWith("redirect:")) {
mavContainer.setRedirectModelScenario(true);
} }
mavContainer.addAllAttributes(mav.getModel());
} }
else { else {
mavContainer.setRequestHandled(true); View view = mav.getView();
mavContainer.setView(view);
if (view instanceof SmartView) {
if (((SmartView) view).isRedirectView()) {
mavContainer.setRedirectModelScenario(true);
}
}
} }
mavContainer.addAllAttributes(mav.getModel());
} }
} }

View File

@@ -18,6 +18,8 @@ package org.springframework.web.servlet.mvc.method.annotation;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@@ -26,10 +28,11 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler; import org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap;
import org.springframework.web.servlet.view.RedirectView; import org.springframework.web.servlet.view.RedirectView;
/** /**
@@ -45,44 +48,90 @@ public class ModelAndViewMethodReturnValueHandlerTests {
private ServletWebRequest webRequest; private ServletWebRequest webRequest;
private MethodParameter returnParamModelAndView;
@Before @Before
public void setUp() { public void setUp() throws Exception {
this.handler = new ModelAndViewMethodReturnValueHandler(); this.handler = new ModelAndViewMethodReturnValueHandler();
this.mavContainer = new ModelAndViewContainer(); this.mavContainer = new ModelAndViewContainer();
this.webRequest = new ServletWebRequest(new MockHttpServletRequest()); this.webRequest = new ServletWebRequest(new MockHttpServletRequest());
this.returnParamModelAndView = getReturnValueParam("modelAndView");
} }
@Test @Test
public void supportsReturnType() throws Exception { public void supportsReturnType() throws Exception {
assertTrue(handler.supportsReturnType(getReturnValueParam("modelAndView"))); assertTrue(handler.supportsReturnType(returnParamModelAndView));
assertFalse(handler.supportsReturnType(getReturnValueParam("viewName"))); assertFalse(handler.supportsReturnType(getReturnValueParam("viewName")));
} }
@Test @Test
public void handleReturnValueViewName() throws Exception { public void handleViewReference() throws Exception {
ModelAndView mav = new ModelAndView("viewName", "attrName", "attrValue"); ModelAndView mav = new ModelAndView("viewName", "attrName", "attrValue");
handler.handleReturnValue(mav, getReturnValueParam("modelAndView"), mavContainer, webRequest); handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
assertEquals("viewName", mavContainer.getView()); assertEquals("viewName", mavContainer.getView());
assertEquals("attrValue", mavContainer.getModel().get("attrName")); assertEquals("attrValue", mavContainer.getModel().get("attrName"));
} }
@Test @Test
public void handleReturnValueView() throws Exception { public void handleViewInstance() throws Exception {
ModelAndView mav = new ModelAndView(new RedirectView(), "attrName", "attrValue"); ModelAndView mav = new ModelAndView(new RedirectView(), "attrName", "attrValue");
handler.handleReturnValue(mav, getReturnValueParam("modelAndView"), mavContainer, webRequest); handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
assertEquals(RedirectView.class, mavContainer.getView().getClass()); assertEquals(RedirectView.class, mavContainer.getView().getClass());
assertEquals("attrValue", mavContainer.getModel().get("attrName")); assertEquals("attrValue", mavContainer.getModel().get("attrName"));
} }
@Test @Test
public void handleReturnValueNull() throws Exception { public void handleNull() throws Exception {
handler.handleReturnValue(null, getReturnValueParam("modelAndView"), mavContainer, webRequest); handler.handleReturnValue(null, returnParamModelAndView, mavContainer, webRequest);
assertTrue(mavContainer.isRequestHandled()); assertTrue(mavContainer.isRequestHandled());
} }
@Test
public void handleRedirectAttributesWithViewReference() throws Exception {
RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap();
mavContainer.setRedirectModel(redirectAttributes);
ModelAndView mav = new ModelAndView(new RedirectView(), "attrName", "attrValue");
handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
assertEquals(RedirectView.class, mavContainer.getView().getClass());
assertEquals("attrValue", mavContainer.getModel().get("attrName"));
assertSame("RedirectAttributes should be used if controller redirects", redirectAttributes,
mavContainer.getModel());
}
@Test
public void handleRedirectAttributesWithViewInstance() throws Exception {
RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap();
mavContainer.setRedirectModel(redirectAttributes);
ModelAndView mav = new ModelAndView("redirect:viewName", "attrName", "attrValue");
handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
ModelMap model = mavContainer.getModel();
assertEquals("redirect:viewName", mavContainer.getViewName());
assertEquals("attrValue", model.get("attrName"));
assertSame("RedirectAttributes should be used if controller redirects", redirectAttributes, model);
}
@Test
public void handleRedirectAttributesWithoutRedirect() throws Exception {
RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap();
mavContainer.setRedirectModel(redirectAttributes);
ModelAndView mav = new ModelAndView();
handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
ModelMap model = mavContainer.getModel();
assertEquals(null, mavContainer.getView());
assertTrue(mavContainer.getModel().isEmpty());
assertNotSame("RedirectAttributes should not be used if controller doesn't redirect", redirectAttributes, model);
}
private MethodParameter getReturnValueParam(String methodName) throws Exception { private MethodParameter getReturnValueParam(String methodName) throws Exception {
Method method = getClass().getDeclaredMethod(methodName); Method method = getClass().getDeclaredMethod(methodName);
return new MethodParameter(method, -1); return new MethodParameter(method, -1);