mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-20 20:59:07 +00:00
SPR-6464 Add 'setAlwaysUseRedirectAttributes' flag.
When set to 'true' the flag makes RedirectAttributes the only way to add attributes for a redirect thus ignoring the content of the default model even if RedirectAttributes is not in the list of controller method args.
This commit is contained in:
+40
-14
@@ -40,6 +40,7 @@ import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.ReflectionUtils.MethodFilter;
|
||||
import org.springframework.validation.DataBinder;
|
||||
@@ -92,6 +93,7 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletRequ
|
||||
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.RedirectAttributes;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap;
|
||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
@@ -145,6 +147,8 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
||||
|
||||
private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
|
||||
|
||||
private boolean alwaysUseRedirectAttributes;
|
||||
|
||||
private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache =
|
||||
new ConcurrentHashMap<Class<?>, SessionAttributesHandler>();
|
||||
|
||||
@@ -329,6 +333,22 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
||||
this.parameterNameDiscoverer = parameterNameDiscoverer;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default a controller uses {@link Model} to select attributes for
|
||||
* rendering and for redirecting. However, a controller can also use
|
||||
* {@link RedirectAttributes} to select attributes before a redirect.
|
||||
* <p>When this flag is set to {@code true}, {@link RedirectAttributes}
|
||||
* becomes the only way to select attributes for a redirect.
|
||||
* In other words, for a redirect a controller must use
|
||||
* {@link RedirectAttributes} or no attributes will be used.
|
||||
* <p>The default value is {@code false}, meaning the {@link Model} is
|
||||
* used unless {@link RedirectAttributes} is used.
|
||||
* @see RedirectAttributes
|
||||
*/
|
||||
public void setAlwaysUseRedirectAttributes(boolean alwaysUseRedirectAttributes) {
|
||||
this.alwaysUseRedirectAttributes = alwaysUseRedirectAttributes;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (beanFactory instanceof ConfigurableBeanFactory) {
|
||||
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
|
||||
@@ -510,13 +530,19 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
||||
HandlerMethod handlerMethod) throws Exception {
|
||||
|
||||
ServletWebRequest webRequest = new ServletWebRequest(request, response);
|
||||
|
||||
ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod);
|
||||
ModelFactory modelFactory = getModelFactory(handlerMethod);
|
||||
|
||||
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
|
||||
ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);
|
||||
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
|
||||
|
||||
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
|
||||
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
|
||||
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
|
||||
|
||||
if (this.alwaysUseRedirectAttributes) {
|
||||
DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null);
|
||||
mavContainer.setRedirectModel(new RedirectAttributesModelMap(dataBinder));
|
||||
}
|
||||
|
||||
SessionStatus sessionStatus = new SimpleSessionStatus();
|
||||
|
||||
@@ -536,23 +562,23 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
||||
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
|
||||
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
|
||||
}
|
||||
return mav;
|
||||
return mav;
|
||||
}
|
||||
}
|
||||
|
||||
private ServletInvocableHandlerMethod createRequestMappingMethod(HandlerMethod handlerMethod) {
|
||||
ServletInvocableHandlerMethod requestMappingMethod =
|
||||
new ServletInvocableHandlerMethod(handlerMethod.getBean(), handlerMethod.getMethod());
|
||||
requestMappingMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
|
||||
requestMappingMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
|
||||
requestMappingMethod.setDataBinderFactory(getDataBinderFactory(handlerMethod));
|
||||
requestMappingMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
|
||||
return requestMappingMethod;
|
||||
private ServletInvocableHandlerMethod createRequestMappingMethod(HandlerMethod handlerMethod,
|
||||
WebDataBinderFactory binderFactory) {
|
||||
ServletInvocableHandlerMethod requestMethod;
|
||||
requestMethod = new ServletInvocableHandlerMethod(handlerMethod.getBean(), handlerMethod.getMethod());
|
||||
requestMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
|
||||
requestMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
|
||||
requestMethod.setDataBinderFactory(binderFactory);
|
||||
requestMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
|
||||
return requestMethod;
|
||||
}
|
||||
|
||||
private ModelFactory getModelFactory(HandlerMethod handlerMethod) {
|
||||
private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
|
||||
SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
|
||||
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
|
||||
Class<?> handlerType = handlerMethod.getBeanType();
|
||||
ModelFactory modelFactory = this.modelFactoryCache.get(handlerType);
|
||||
if (modelFactory == null) {
|
||||
|
||||
+10
-4
@@ -49,10 +49,16 @@ public class RedirectAttributesMethodArgumentResolver implements HandlerMethodAr
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest,
|
||||
WebDataBinderFactory binderFactory) throws Exception {
|
||||
DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null);
|
||||
ModelMap attributes = new RedirectAttributesModelMap(dataBinder);
|
||||
mavContainer.setRedirectModel(attributes);
|
||||
return attributes;
|
||||
|
||||
if (mavContainer.getRedirectModel() != null) {
|
||||
return mavContainer.getRedirectModel();
|
||||
}
|
||||
else {
|
||||
DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null);
|
||||
ModelMap redirectAttributes = new RedirectAttributesModelMap(dataBinder);
|
||||
mavContainer.setRedirectModel(redirectAttributes);
|
||||
return redirectAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -61,14 +61,14 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan
|
||||
String viewName = (String) returnValue;
|
||||
mavContainer.setViewName(viewName);
|
||||
if (isRedirectViewName(viewName)) {
|
||||
mavContainer.setRedirectModelEnabled();
|
||||
mavContainer.setUseRedirectModel();
|
||||
}
|
||||
}
|
||||
else if (returnValue instanceof View){
|
||||
View view = (View) returnValue;
|
||||
mavContainer.setView(view);
|
||||
if (isRedirectView(view)) {
|
||||
mavContainer.setRedirectModelEnabled();
|
||||
mavContainer.setUseRedirectModel();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
+26
-3
@@ -66,13 +66,14 @@ public class RedirectAttributesModelMap extends ModelMap implements RedirectAttr
|
||||
* <p>Formats the attribute value as a String before adding it.
|
||||
*/
|
||||
public RedirectAttributesModelMap addAttribute(String attributeName, Object attributeValue) {
|
||||
if (attributeValue != null) {
|
||||
super.addAttribute(attributeName, formatValue(attributeValue));
|
||||
}
|
||||
super.addAttribute(attributeName, formatValue(attributeValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
private String formatValue(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return (dataBinder != null) ? dataBinder.convertIfNecessary(value, String.class) : value.toString();
|
||||
}
|
||||
|
||||
@@ -126,6 +127,28 @@ public class RedirectAttributesModelMap extends ModelMap implements RedirectAttr
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>The value is formatted as a String before being added.
|
||||
*/
|
||||
@Override
|
||||
public Object put(String key, Object value) {
|
||||
return super.put(key, formatValue(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>Each value is formatted as a String before being added.
|
||||
*/
|
||||
@Override
|
||||
public void putAll(Map<? extends String, ? extends Object> map) {
|
||||
if (map != null) {
|
||||
for (String key : map.keySet()) {
|
||||
put(key, formatValue(map.get(key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RedirectAttributes addFlashAttribute(String attributeName, Object attributeValue) {
|
||||
this.flashAttributes.addAttribute(attributeName, attributeValue);
|
||||
return this;
|
||||
|
||||
Reference in New Issue
Block a user