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:
@@ -21,6 +21,8 @@ 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.ModelAndView;
|
||||
import org.springframework.web.servlet.SmartView;
|
||||
import org.springframework.web.servlet.View;
|
||||
|
||||
/**
|
||||
* Handles return values of type {@link ModelAndView} copying view and model
|
||||
@@ -48,17 +50,29 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
|
||||
MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest) throws Exception {
|
||||
if (returnValue != null) {
|
||||
ModelAndView mav = (ModelAndView) returnValue;
|
||||
mavContainer.setViewName(mav.getViewName());
|
||||
if (!mav.isReference()) {
|
||||
mavContainer.setView(mav.getView());
|
||||
if (returnValue == null) {
|
||||
mavContainer.setRequestHandled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
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 {
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,8 @@ package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
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 java.lang.reflect.Method;
|
||||
@@ -26,10 +28,11 @@ 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.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;
|
||||
|
||||
/**
|
||||
@@ -45,44 +48,90 @@ public class ModelAndViewMethodReturnValueHandlerTests {
|
||||
|
||||
private ServletWebRequest webRequest;
|
||||
|
||||
private MethodParameter returnParamModelAndView;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
public void setUp() throws Exception {
|
||||
this.handler = new ModelAndViewMethodReturnValueHandler();
|
||||
this.mavContainer = new ModelAndViewContainer();
|
||||
this.webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||
this.returnParamModelAndView = getReturnValueParam("modelAndView");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsReturnType() throws Exception {
|
||||
assertTrue(handler.supportsReturnType(getReturnValueParam("modelAndView")));
|
||||
assertTrue(handler.supportsReturnType(returnParamModelAndView));
|
||||
assertFalse(handler.supportsReturnType(getReturnValueParam("viewName")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleReturnValueViewName() throws Exception {
|
||||
public void handleViewReference() throws Exception {
|
||||
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("attrValue", mavContainer.getModel().get("attrName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleReturnValueView() throws Exception {
|
||||
public void handleViewInstance() throws Exception {
|
||||
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("attrValue", mavContainer.getModel().get("attrName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleReturnValueNull() throws Exception {
|
||||
handler.handleReturnValue(null, getReturnValueParam("modelAndView"), mavContainer, webRequest);
|
||||
public void handleNull() throws Exception {
|
||||
handler.handleReturnValue(null, returnParamModelAndView, mavContainer, webRequest);
|
||||
|
||||
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 {
|
||||
Method method = getClass().getDeclaredMethod(methodName);
|
||||
return new MethodParameter(method, -1);
|
||||
|
||||
Reference in New Issue
Block a user