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.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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user