diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMap.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMap.java
index 72f2155b116..0b7bc82ad03 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMap.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/FlashMap.java
@@ -17,10 +17,10 @@
package org.springframework.web.servlet;
import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.springframework.beans.BeanUtils;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StringUtils;
/**
* A FlashMap provides a way for one request to store attributes intended for
@@ -35,7 +35,7 @@ import org.springframework.beans.BeanUtils;
* recipient. On a redirect, the target URL is known and for example
* {@code org.springframework.web.servlet.view.RedirectView} has the
* opportunity to automatically update the current FlashMap with target
- * URL information .
+ * URL information.
*
*
Annotated controllers will usually not use this type directly.
* See {@code org.springframework.web.servlet.mvc.support.RedirectAttributes}
@@ -46,13 +46,13 @@ import org.springframework.beans.BeanUtils;
*
* @see FlashMapManager
*/
-public class FlashMap extends HashMap implements Comparable {
+public final class FlashMap extends HashMap implements Comparable {
private static final long serialVersionUID = 1L;
private String targetRequestPath;
- private final Map targetRequestParams = new LinkedHashMap();
+ private final MultiValueMap targetRequestParams = new LinkedMultiValueMap();
private long expirationStartTime;
@@ -93,17 +93,15 @@ public class FlashMap extends HashMap implements Comparable params) {
+ public FlashMap addTargetRequestParams(MultiValueMap params) {
if (params != null) {
- for (String name : params.keySet()) {
- Object value = params.get(name);
- if ((value != null) && BeanUtils.isSimpleValueType(value.getClass())) {
- this.targetRequestParams.put(name, value.toString());
+ for (String key : params.keySet()) {
+ for (String value : params.get(key)) {
+ addTargetRequestParam(key, value);
}
}
}
@@ -111,19 +109,21 @@ public class FlashMap extends HashMap implements Comparable getTargetRequestParams() {
+ public MultiValueMap getTargetRequestParams() {
return targetRequestParams;
}
@@ -174,11 +174,11 @@ public class FlashMap extends HashMap implements ComparableAnnotated controllers are most likely to store and access flash attributes
- * through their model.
+ * Annotated controllers will usually not use this FlashMap directly.
* See {@code org.springframework.web.servlet.mvc.support.RedirectAttributes}.
*
* @author Rossen Stoyanchev
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java
index 959fcf8291f..99fc6a40165 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java
@@ -130,6 +130,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
methodAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
methodAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
methodAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
+ methodAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", true);
if (argumentResolvers != null) {
methodAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
}
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
index 8da51d8aeb6..322f5f6c032 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
@@ -73,42 +73,59 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
/**
- * A base class that provides default configuration for Spring MVC applications by registering Spring MVC
- * infrastructure components to be detected by the {@link DispatcherServlet}. Typically applications should not
- * have to extend this class. A more likely place to start is to annotate an @{@link Configuration}
- * class with @{@link EnableWebMvc} (see @{@link EnableWebMvc} and {@link WebMvcConfigurer} for details).
+ * A base class that provides default configuration for Spring MVC applications
+ * by registering Spring MVC infrastructure components to be detected by the
+ * {@link DispatcherServlet}. An application configuration class is not required
+ * to extend this class. A more likely place to start is to annotate
+ * an @{@link Configuration} class with @{@link EnableWebMvc}
+ * (see @{@link EnableWebMvc} and {@link WebMvcConfigurer} for details).
*
- *
If using @{@link EnableWebMvc} does not give you all you need, consider extending directly from this
- * class. Remember to add @{@link Configuration} to your subclass and @{@link Bean} to any superclass
- * @{@link Bean} methods you choose to override.
+ *
If the customization options available with use of @{@link EnableWebMvc}
+ * are not enough, consider extending directly from this class and override the
+ * appropriate methods. Remember to add @{@link Configuration} to your subclass
+ * and @{@link Bean} to any superclass @{@link Bean} methods you override.
*
*
This class registers the following {@link HandlerMapping}s:
*
- * - {@link RequestMappingHandlerMapping} ordered at 0 for mapping requests to annotated controller methods.
- *
- {@link HandlerMapping} ordered at 1 to map URL paths directly to view names.
- *
- {@link BeanNameUrlHandlerMapping} ordered at 2 to map URL paths to controller bean names.
- *
- {@link HandlerMapping} ordered at {@code Integer.MAX_VALUE-1} to serve static resource requests.
- *
- {@link HandlerMapping} ordered at {@code Integer.MAX_VALUE} to forward requests to the default servlet.
+ *
- {@link RequestMappingHandlerMapping}
+ * ordered at 0 for mapping requests to annotated controller methods.
+ *
- {@link HandlerMapping}
+ * ordered at 1 to map URL paths directly to view names.
+ *
- {@link BeanNameUrlHandlerMapping}
+ * ordered at 2 to map URL paths to controller bean names.
+ *
- {@link HandlerMapping}
+ * ordered at {@code Integer.MAX_VALUE-1} to serve static resource requests.
+ *
- {@link HandlerMapping}
+ * ordered at {@code Integer.MAX_VALUE} to forward requests to the default servlet.
*
*
* Registers these {@link HandlerAdapter}s:
*
- * - {@link RequestMappingHandlerAdapter} for processing requests with annotated controller methods.
- *
- {@link HttpRequestHandlerAdapter} for processing requests with {@link HttpRequestHandler}s.
- *
- {@link SimpleControllerHandlerAdapter} for processing requests with interface-based {@link Controller}s.
+ *
- {@link RequestMappingHandlerAdapter}
+ * for processing requests with annotated controller methods.
+ *
- {@link HttpRequestHandlerAdapter}
+ * for processing requests with {@link HttpRequestHandler}s.
+ *
- {@link SimpleControllerHandlerAdapter}
+ * for processing requests with interface-based {@link Controller}s.
*
*
- * Registers a {@link HandlerExceptionResolverComposite} with this chain of exception resolvers:
+ *
Registers a {@link HandlerExceptionResolverComposite} with this chain of
+ * exception resolvers:
*
- * - {@link ExceptionHandlerExceptionResolver} for handling exceptions through @{@link ExceptionHandler} methods.
- *
- {@link ResponseStatusExceptionResolver} for exceptions annotated with @{@link ResponseStatus}.
- *
- {@link DefaultHandlerExceptionResolver} for resolving known Spring exception types
+ *
- {@link ExceptionHandlerExceptionResolver} for handling exceptions
+ * through @{@link ExceptionHandler} methods.
+ *
- {@link ResponseStatusExceptionResolver} for exceptions annotated
+ * with @{@link ResponseStatus}.
+ *
- {@link DefaultHandlerExceptionResolver} for resolving known Spring
+ * exception types
*
*
* Registers these other instances:
*
- * - {@link FormattingConversionService} for use with annotated controller methods and the spring:eval JSP tag.
- *
- {@link Validator} for validating model attributes on annotated controller methods.
+ *
- {@link FormattingConversionService}
+ * for use with annotated controller methods and the spring:eval JSP tag.
+ *
- {@link Validator}
+ * for validating model attributes on annotated controller methods.
*
*
* @see EnableWebMvc
@@ -137,7 +154,8 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Returns a {@link RequestMappingHandlerMapping} ordered at 0 for mapping requests to annotated controllers.
+ * Return a {@link RequestMappingHandlerMapping} ordered at 0 for mapping
+ * requests to annotated controllers.
*/
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
@@ -148,8 +166,9 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Provides access to the shared handler interceptors used to configure {@link HandlerMapping} instances with.
- * This method cannot be overridden, use {@link #addInterceptors(InterceptorRegistry)} instead.
+ * Provide access to the shared handler interceptors used to configure
+ * {@link HandlerMapping} instances with. This method cannot be overridden,
+ * use {@link #addInterceptors(InterceptorRegistry)} instead.
*/
protected final Object[] getInterceptors() {
if (interceptors == null) {
@@ -162,15 +181,17 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Override this method to add Spring MVC interceptors for pre/post-processing of controller invocation.
+ * Override this method to add Spring MVC interceptors for
+ * pre- and post-processing of controller invocation.
* @see InterceptorRegistry
*/
protected void addInterceptors(InterceptorRegistry registry) {
}
/**
- * Returns a handler mapping ordered at 1 to map URL paths directly to view names.
- * To configure view controllers, override {@link #addViewControllers(ViewControllerRegistry)}.
+ * Return a handler mapping ordered at 1 to map URL paths directly to
+ * view names. To configure view controllers, override
+ * {@link #addViewControllers}.
*/
@Bean
public HandlerMapping viewControllerHandlerMapping() {
@@ -191,7 +212,8 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Returns a {@link BeanNameUrlHandlerMapping} ordered at 2 to map URL paths to controller bean names.
+ * Return a {@link BeanNameUrlHandlerMapping} ordered at 2 to map URL
+ * paths to controller bean names.
*/
@Bean
public BeanNameUrlHandlerMapping beanNameHandlerMapping() {
@@ -202,8 +224,9 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Returns a handler mapping ordered at Integer.MAX_VALUE-1 with mapped resource handlers.
- * To configure resource handling, override {@link #addResourceHandlers(ResourceHandlerRegistry)}.
+ * Return a handler mapping ordered at Integer.MAX_VALUE-1 with mapped
+ * resource handlers. To configure resource handling, override
+ * {@link #addResourceHandlers}.
*/
@Bean
public HandlerMapping resourceHandlerMapping() {
@@ -222,9 +245,9 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Returns a handler mapping ordered at Integer.MAX_VALUE with a mapped default servlet handler.
- * To configure "default" Servlet handling, override
- * {@link #configureDefaultServletHandling(DefaultServletHandlerConfigurer)}.
+ * Return a handler mapping ordered at Integer.MAX_VALUE with a mapped
+ * default servlet handler. To configure "default" Servlet handling,
+ * override {@link #configureDefaultServletHandling}.
*/
@Bean
public HandlerMapping defaultServletHandlerMapping() {
@@ -243,12 +266,13 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Returns a {@link RequestMappingHandlerAdapter} for processing requests through annotated controller methods.
- * Consider overriding one of these other more fine-grained methods:
+ * Returns a {@link RequestMappingHandlerAdapter} for processing requests
+ * through annotated controller methods. Consider overriding one of these
+ * other more fine-grained methods:
*
- * - {@link #addArgumentResolvers(List)} for adding custom argument resolvers.
- *
- {@link #addReturnValueHandlers(List)} for adding custom return value handlers.
- *
- {@link #configureMessageConverters(List)} for adding custom message converters.
+ *
- {@link #addArgumentResolvers} for adding custom argument resolvers.
+ *
- {@link #addReturnValueHandlers} for adding custom return value handlers.
+ *
- {@link #configureMessageConverters} for adding custom message converters.
*
*/
@Bean
@@ -268,34 +292,46 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
adapter.setWebBindingInitializer(webBindingInitializer);
adapter.setCustomArgumentResolvers(argumentResolvers);
adapter.setCustomReturnValueHandlers(returnValueHandlers);
+ adapter.setIgnoreDefaultModelOnRedirect(true);
return adapter;
}
/**
- * Add custom {@link HandlerMethodArgumentResolver}s to use in addition to the ones registered by default.
- * Custom argument resolvers are invoked before built-in resolvers except for those that rely on the presence
- * of annotations (e.g. {@code @RequestParameter}, {@code @PathVariable}, etc.). The latter can be customized
- * by configuring the {@link RequestMappingHandlerAdapter} directly.
- * @param argumentResolvers the list of custom converters; initially an empty list.
+ * Add custom {@link HandlerMethodArgumentResolver}s to use in addition to
+ * the ones registered by default.
+ *
Custom argument resolvers are invoked before built-in resolvers
+ * except for those that rely on the presence of annotations (e.g.
+ * {@code @RequestParameter}, {@code @PathVariable}, etc.).
+ * The latter can be customized by configuring the
+ * {@link RequestMappingHandlerAdapter} directly.
+ * @param argumentResolvers the list of custom converters;
+ * initially an empty list.
*/
protected void addArgumentResolvers(List argumentResolvers) {
}
/**
- * Add custom {@link HandlerMethodReturnValueHandler}s in addition to the ones registered by default.
- * Custom return value handlers are invoked before built-in ones except for those that rely on the presence
- * of annotations (e.g. {@code @ResponseBody}, {@code @ModelAttribute}, etc.). The latter can be customized
- * by configuring the {@link RequestMappingHandlerAdapter} directly.
- * @param returnValueHandlers the list of custom handlers; initially an empty list.
+ * Add custom {@link HandlerMethodReturnValueHandler}s in addition to the
+ * ones registered by default.
+ *
Custom return value handlers are invoked before built-in ones except
+ * for those that rely on the presence of annotations (e.g.
+ * {@code @ResponseBody}, {@code @ModelAttribute}, etc.).
+ * The latter can be customized by configuring the
+ * {@link RequestMappingHandlerAdapter} directly.
+ * @param returnValueHandlers the list of custom handlers;
+ * initially an empty list.
*/
protected void addReturnValueHandlers(List returnValueHandlers) {
}
/**
* Provides access to the shared {@link HttpMessageConverter}s used by the
- * {@link RequestMappingHandlerAdapter} and the {@link ExceptionHandlerExceptionResolver}.
- * This method cannot be overridden. Use {@link #configureMessageConverters(List)} instead.
- * Also see {@link #addDefaultHttpMessageConverters(List)} that can be used to add default message converters.
+ * {@link RequestMappingHandlerAdapter} and the
+ * {@link ExceptionHandlerExceptionResolver}.
+ * This method cannot be overridden.
+ * Use {@link #configureMessageConverters(List)} instead.
+ * Also see {@link #addDefaultHttpMessageConverters(List)} that can be
+ * used to add default message converters.
*/
protected final List> getMessageConverters() {
if (messageConverters == null) {
@@ -309,17 +345,20 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Override this method to add custom {@link HttpMessageConverter}s to use with
- * the {@link RequestMappingHandlerAdapter} and the {@link ExceptionHandlerExceptionResolver}.
- * Adding converters to the list turns off the default converters that would otherwise be registered by default.
- * Also see {@link #addDefaultHttpMessageConverters(List)} that can be used to add default message converters.
- * @param converters a list to add message converters to; initially an empty list.
+ * Override this method to add custom {@link HttpMessageConverter}s to use
+ * with the {@link RequestMappingHandlerAdapter} and the
+ * {@link ExceptionHandlerExceptionResolver}. Adding converters to the
+ * list turns off the default converters that would otherwise be registered
+ * by default. Also see {@link #addDefaultHttpMessageConverters(List)} that
+ * can be used to add default message converters.
+ * @param converters a list to add message converters to;
+ * initially an empty list.
*/
protected void configureMessageConverters(List> converters) {
}
/**
- * A method available to subclasses to add default {@link HttpMessageConverter}s.
+ * Override this method to add default {@link HttpMessageConverter}s.
* @param messageConverters the list to add the default message converters to
*/
protected final void addDefaultHttpMessageConverters(List> messageConverters) {
@@ -346,9 +385,9 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Returns a {@link FormattingConversionService} for use with annotated controller methods and the
- * {@code spring:eval} JSP tag. Also see {@link #addFormatters(FormatterRegistry)} as an alternative
- * to overriding this method.
+ * Returns a {@link FormattingConversionService} for use with annotated
+ * controller methods and the {@code spring:eval} JSP tag.
+ * Also see {@link #addFormatters} as an alternative to overriding this method.
*/
@Bean
public FormattingConversionService mvcConversionService() {
@@ -364,8 +403,9 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Returns {@link Validator} for validating {@code @ModelAttribute} and {@code @RequestBody} arguments of
- * annotated controller methods. To configure a custom validation, override {@link #getValidator()}.
+ * Returns {@link Validator} for validating {@code @ModelAttribute}
+ * and {@code @RequestBody} arguments of annotated controller methods.
+ * To configure a custom validation, override {@link #getValidator()}.
*/
@Bean
Validator mvcValidator() {
@@ -404,7 +444,8 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Returns a {@link HttpRequestHandlerAdapter} for processing requests with {@link HttpRequestHandler}s.
+ * Returns a {@link HttpRequestHandlerAdapter} for processing requests
+ * with {@link HttpRequestHandler}s.
*/
@Bean
public HttpRequestHandlerAdapter httpRequestHandlerAdapter() {
@@ -412,7 +453,8 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Returns a {@link SimpleControllerHandlerAdapter} for processing requests with interface-based controllers.
+ * Returns a {@link SimpleControllerHandlerAdapter} for processing requests
+ * with interface-based controllers.
*/
@Bean
public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() {
@@ -420,8 +462,9 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Returns a {@link HandlerExceptionResolverComposite} that contains a list of exception resolvers.
- * To customize the list of exception resolvers, override {@link #configureHandlerExceptionResolvers(List)}.
+ * Returns a {@link HandlerExceptionResolverComposite} that contains a list
+ * of exception resolvers. To customize the list of exception resolvers,
+ * override {@link #configureHandlerExceptionResolvers(List)}.
*/
@Bean
HandlerExceptionResolver handlerExceptionResolver() throws Exception {
@@ -439,21 +482,28 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw
}
/**
- * Override this method to configure the list of {@link HandlerExceptionResolver}s to use.
- * Adding resolvers to the list turns off the default resolvers that would otherwise be registered by default.
- * Also see {@link #addDefaultHandlerExceptionResolvers(List)} that can be used to add the default exception resolvers.
- * @param exceptionResolvers a list to add exception resolvers to; initially an empty list.
+ * Override this method to configure the list of
+ * {@link HandlerExceptionResolver}s to use. Adding resolvers to the list
+ * turns off the default resolvers that would otherwise be registered by
+ * default. Also see {@link #addDefaultHandlerExceptionResolvers(List)}
+ * that can be used to add the default exception resolvers.
+ * @param exceptionResolvers a list to add exception resolvers to;
+ * initially an empty list.
*/
protected void configureHandlerExceptionResolvers(List exceptionResolvers) {
}
/**
- * A method available to subclasses for adding default {@link HandlerExceptionResolver}s.
+ * A method available to subclasses for adding default
+ * {@link HandlerExceptionResolver}s.
* Adds the following exception resolvers:
*
- * - {@link ExceptionHandlerExceptionResolver} for handling exceptions through @{@link ExceptionHandler} methods.
- *
- {@link ResponseStatusExceptionResolver} for exceptions annotated with @{@link ResponseStatus}.
- *
- {@link DefaultHandlerExceptionResolver} for resolving known Spring exception types
+ *
- {@link ExceptionHandlerExceptionResolver}
+ * for handling exceptions through @{@link ExceptionHandler} methods.
+ *
- {@link ResponseStatusExceptionResolver}
+ * for exceptions annotated with @{@link ResponseStatus}.
+ *
- {@link DefaultHandlerExceptionResolver}
+ * for resolving known Spring exception types
*
*/
protected final void addDefaultHandlerExceptionResolvers(List exceptionResolvers) {
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java
index ea3fbd0d847..fff6b623587 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java
@@ -235,7 +235,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
return null;
}
- if (!mavContainer.isResolveView()) {
+ if (mavContainer.isRequestHandled()) {
return new ModelAndView();
}
else {
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 1db4cd6672b..4ce707ea9e8 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
@@ -93,7 +93,6 @@ 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;
@@ -147,7 +146,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
- private boolean alwaysUseRedirectAttributes;
+ private boolean ignoreDefaultModelOnRedirect = false;
private final Map, SessionAttributesHandler> sessionAttributesHandlerCache =
new ConcurrentHashMap, SessionAttributesHandler>();
@@ -334,19 +333,20 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
}
/**
- * 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.
- * 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.
- *
The default value is {@code false}, meaning the {@link Model} is
- * used unless {@link RedirectAttributes} is used.
+ * A controller can use the "default" {@link Model} in rendering and
+ * redirect scenarios. Alternatively, it can use {@link RedirectAttributes}
+ * to provide attributes for a redirect scenario.
+ *
When this flag is set to {@code true}, the "default" model is never
+ * used in a redirect even if the controller method doesn't explicitly
+ * declare a RedirectAttributes argument.
+ *
When set to {@code false}, the "default" model may be used in a
+ * redirect if the controller method doesn't explicitly declare a
+ * RedirectAttributes argument.
+ *
The default setting is {@code false}.
* @see RedirectAttributes
*/
- public void setAlwaysUseRedirectAttributes(boolean alwaysUseRedirectAttributes) {
- this.alwaysUseRedirectAttributes = alwaysUseRedirectAttributes;
+ public void setIgnoreDefaultModelOnRedirect(boolean ignoreDefaultModelOnRedirect) {
+ this.ignoreDefaultModelOnRedirect = ignoreDefaultModelOnRedirect;
}
public void setBeanFactory(BeanFactory beanFactory) {
@@ -538,18 +538,14 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
+ mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
- if (this.alwaysUseRedirectAttributes) {
- DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null);
- mavContainer.setRedirectModel(new RedirectAttributesModelMap(dataBinder));
- }
-
SessionStatus sessionStatus = new SimpleSessionStatus();
requestMappingMethod.invokeAndHandle(webRequest, mavContainer, sessionStatus);
modelFactory.updateModel(webRequest, mavContainer, sessionStatus);
- if (!mavContainer.isResolveView()) {
+ if (mavContainer.isRequestHandled()) {
return null;
}
else {
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
index 60d42f6d367..348be0654ac 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
@@ -75,7 +75,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
*
Return value handling may be skipped entirely when the method returns {@code null} (also possibly due
* to a {@code void} return type) and one of the following additional conditions is true:
*
- * - A {@link HandlerMethodArgumentResolver} has set the {@link ModelAndViewContainer#setResolveView(boolean)}
+ *
- A {@link HandlerMethodArgumentResolver} has set the {@link ModelAndViewContainer#setRequestHandled(boolean)}
* flag to {@code false} -- e.g. method arguments providing access to the response.
*
- The request qualifies as "not modified" as defined in {@link ServletWebRequest#checkNotModified(long)}
* and {@link ServletWebRequest#checkNotModified(String)}. In this case a response with "not modified" response
@@ -98,13 +98,13 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
setResponseStatus((ServletWebRequest) request);
if (returnValue == null) {
- if (isRequestNotModified(request) || hasResponseStatus() || !mavContainer.isResolveView()) {
- mavContainer.setResolveView(false);
+ if (isRequestNotModified(request) || hasResponseStatus() || mavContainer.isRequestHandled()) {
+ mavContainer.setRequestHandled(true);
return;
}
}
- mavContainer.setResolveView(true);
+ mavContainer.setRequestHandled(false);
try {
returnValueHandlers.handleReturnValue(returnValue, getReturnType(), mavContainer, request);
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessor.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessor.java
index 9e51874ca09..fb8a9d7e6f0 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessor.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessor.java
@@ -101,7 +101,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
- mavContainer.setResolveView(false);
+ mavContainer.setRequestHandled(true);
if (returnValue == null) {
return;
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java
index 84f94f9dd68..f4ff0727e0b 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java
@@ -24,7 +24,7 @@ import org.springframework.web.servlet.ModelAndView;
/**
* Handles return values of type {@link ModelAndView} transferring their content to the {@link ModelAndViewContainer}.
- * If the return value is {@code null}, the {@link ModelAndViewContainer#setResolveView(boolean)} flag is set to
+ * If the return value is {@code null}, the {@link ModelAndViewContainer#setRequestHandled(boolean)} flag is set to
* {@code false} to indicate view resolution is not needed.
*
* @author Rossen Stoyanchev
@@ -49,7 +49,7 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
mavContainer.addAllAttributes(mav.getModel());
}
else {
- mavContainer.setResolveView(false);
+ mavContainer.setRequestHandled(true);
}
}
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectAttributesMethodArgumentResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectAttributesMethodArgumentResolver.java
index 16c70320bed..d8c950e482b 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectAttributesMethodArgumentResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectAttributesMethodArgumentResolver.java
@@ -49,16 +49,10 @@ public class RedirectAttributesMethodArgumentResolver implements HandlerMethodAr
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
-
- 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;
- }
+ DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null);
+ ModelMap redirectAttributes = new RedirectAttributesModelMap(dataBinder);
+ mavContainer.setRedirectModel(redirectAttributes);
+ return redirectAttributes;
}
}
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessor.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessor.java
index 2ef1020f67e..0dd3f2e0bd7 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessor.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessor.java
@@ -98,7 +98,7 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
MethodParameter returnType,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException {
- mavContainer.setResolveView(false);
+ mavContainer.setRequestHandled(true);
if (returnValue != null) {
writeWithMessageConverters(returnValue, returnType, webRequest);
}
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolver.java
index 2f4ce254023..23042cb3b61 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolver.java
@@ -54,7 +54,7 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
/**
* {@inheritDoc}
- *
Sets the {@link ModelAndViewContainer#setResolveView(boolean)} flag to {@code false} to indicate
+ *
Sets the {@link ModelAndViewContainer#setRequestHandled(boolean)} flag to {@code false} to indicate
* that the method signature provides access to the response. If subsequently the underlying method
* returns {@code null}, view resolution will be bypassed.
* @see ServletInvocableHandlerMethod#invokeAndHandle(NativeWebRequest, ModelAndViewContainer, Object...)
@@ -64,7 +64,7 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws IOException {
- mavContainer.setResolveView(false);
+ mavContainer.setRequestHandled(true);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
Class> paramType = parameter.getParameterType();
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 52604afad9f..4052952e6db 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
@@ -61,14 +61,14 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan
String viewName = (String) returnValue;
mavContainer.setViewName(viewName);
if (isRedirectViewName(viewName)) {
- mavContainer.setUseRedirectModel();
+ mavContainer.setUseRedirectModel(true);
}
}
else if (returnValue instanceof View){
View view = (View) returnValue;
mavContainer.setView(view);
if (isRedirectView(view)) {
- mavContainer.setUseRedirectModel();
+ mavContainer.setUseRedirectModel(true);
}
}
else {
@@ -95,7 +95,7 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan
* "false" otherwise.
*/
protected boolean isRedirectView(View view) {
- if (SmartView.class.isAssignableFrom(view.getClass())) {
+ if (view instanceof SmartView) {
return ((SmartView) view).isRedirectView();
}
else {
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/DefaultFlashMapManager.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/DefaultFlashMapManager.java
index c8b9f57b533..6b100f939cc 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/DefaultFlashMapManager.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/DefaultFlashMapManager.java
@@ -27,13 +27,14 @@ import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.CollectionUtils;
+import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.FlashMapManager;
import org.springframework.web.util.UrlPathHelper;
/**
- * A default {@link FlashMapManager} implementation keeps {@link FlashMap}
+ * A default {@link FlashMapManager} implementation that stores {@link FlashMap}
* instances in the HTTP session.
*
* @author Rossen Stoyanchev
@@ -122,9 +123,10 @@ public class DefaultFlashMapManager implements FlashMapManager {
return false;
}
}
- if (flashMap.getTargetRequestParams() != null) {
- for (String paramName : flashMap.getTargetRequestParams().keySet()) {
- if (!flashMap.getTargetRequestParams().get(paramName).equals(request.getParameter(paramName))) {
+ MultiValueMap params = flashMap.getTargetRequestParams();
+ for (String key : params.keySet()) {
+ for (String value : params.get(key)) {
+ if (!value.equals(request.getParameter(key))) {
return false;
}
}
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 0cbe8a8540e..dffa139b668 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
@@ -43,6 +43,8 @@ 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.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;
@@ -240,11 +242,9 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
if (!CollectionUtils.isEmpty(flashMap)) {
- String targetPath = WebUtils.extractUrlPath(targetUrl.toString());
- flashMap.setTargetRequestPath(targetPath);
- if (this.exposeModelAttributes) {
- flashMap.addTargetRequestParams(model);
- }
+ UriComponents uriComponents = UriComponentsBuilder.fromUriString(targetUrl).build();
+ flashMap.setTargetRequestPath(uriComponents.getPath());
+ flashMap.addTargetRequestParams(uriComponents.getQueryParams());
}
sendRedirect(request, response, targetUrl.toString(), this.http10Compatible);
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/FlashMapTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/FlashMapTests.java
index 01d0a97a0de..6583b5d5c07 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/FlashMapTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/FlashMapTests.java
@@ -21,6 +21,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
/**
* Test fixture for {@link FlashMap} tests.
@@ -31,18 +33,17 @@ public class FlashMapTests {
@Test
public void isExpired() throws InterruptedException {
+ assertFalse(new FlashMap().isExpired());
+
FlashMap flashMap = new FlashMap();
flashMap.startExpirationPeriod(0);
-
- Thread.sleep(1);
+ Thread.sleep(100);
assertTrue(flashMap.isExpired());
}
@Test
public void notExpired() throws InterruptedException {
- assertFalse(new FlashMap().isExpired());
-
FlashMap flashMap = new FlashMap();
flashMap.startExpirationPeriod(10);
Thread.sleep(100);
@@ -71,4 +72,51 @@ public class FlashMapTests {
assertEquals(0, flashMap1.compareTo(flashMap2));
}
+ @Test
+ public void addTargetRequestParamNullValue() {
+ FlashMap flashMap = new FlashMap();
+ flashMap.addTargetRequestParam("text", "abc");
+ flashMap.addTargetRequestParam("empty", " ");
+ flashMap.addTargetRequestParam("null", null);
+
+ assertEquals(1, flashMap.getTargetRequestParams().size());
+ assertEquals("abc", flashMap.getTargetRequestParams().getFirst("text"));
+ }
+
+ @Test
+ public void addTargetRequestParamsNullValue() {
+ MultiValueMap params = new LinkedMultiValueMap();
+ params.add("key", "abc");
+ params.add("key", " ");
+ params.add("key", null);
+
+ FlashMap flashMap = new FlashMap();
+ flashMap.addTargetRequestParams(params);
+
+ assertEquals(1, flashMap.getTargetRequestParams().size());
+ assertEquals(1, flashMap.getTargetRequestParams().get("key").size());
+ assertEquals("abc", flashMap.getTargetRequestParams().getFirst("key"));
+ }
+
+ @Test
+ public void addTargetRequestParamNullKey() {
+ FlashMap flashMap = new FlashMap();
+ flashMap.addTargetRequestParam(" ", "abc");
+ flashMap.addTargetRequestParam(null, "abc");
+
+ assertTrue(flashMap.getTargetRequestParams().isEmpty());
+ }
+
+ @Test
+ public void addTargetRequestParamsNullKey() {
+ MultiValueMap params = new LinkedMultiValueMap();
+ params.add(" ", "abc");
+ params.add(null, " ");
+
+ FlashMap flashMap = new FlashMap();
+ flashMap.addTargetRequestParams(params);
+
+ assertTrue(flashMap.getTargetRequestParams().isEmpty());
+ }
+
}
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java
index c9c586240f7..b79e36adfa2 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java
@@ -67,6 +67,7 @@ public class AnnotationDrivenBeanDefinitionParserTests {
MessageCodesResolver resolver = ((ConfigurableWebBindingInitializer) initializer).getMessageCodesResolver();
assertNotNull(resolver);
assertEquals(TestMessageCodesResolver.class, resolver.getClass());
+ assertEquals(true, new DirectFieldAccessor(adapter).getPropertyValue("ignoreDefaultModelOnRedirect"));
}
@Test
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
index 08ae16db95d..c8977750b01 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
@@ -150,6 +150,8 @@ public class WebMvcConfigurationSupportTests {
Validator validator = initializer.getValidator();
assertNotNull(validator);
assertTrue(validator instanceof LocalValidatorFactoryBean);
+
+ assertEquals(true, new DirectFieldAccessor(adapter).getPropertyValue("ignoreDefaultModelOnRedirect"));
}
@Test
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java
index b3462ffd309..616e6de1b5e 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java
@@ -103,7 +103,7 @@ public class RequestMappingHandlerAdapterTests {
handlerAdapter.setArgumentResolvers(Arrays.asList(redirectAttributesResolver, modelResolver));
handlerAdapter.setReturnValueHandlers(Arrays.asList(viewHandler));
- handlerAdapter.setAlwaysUseRedirectAttributes(true);
+ handlerAdapter.setIgnoreDefaultModelOnRedirect(true);
handlerAdapter.afterPropertiesSet();
request.setAttribute(FlashMapManager.OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
@@ -111,7 +111,7 @@ public class RequestMappingHandlerAdapterTests {
HandlerMethod handlerMethod = handlerMethod(new RedirectAttributeHandler(), "handle", Model.class);
ModelAndView mav = handlerAdapter.handle(request, response, handlerMethod);
- assertTrue("No redirect attributes added, model should be empty", mav.getModel().isEmpty());
+ assertTrue("Without RedirectAttributes arg, model should be empty", mav.getModel().isEmpty());
}
@Test
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethodTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethodTests.java
index dcd901c8d8f..34e98961519 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethodTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethodTests.java
@@ -71,8 +71,8 @@ public class ServletInvocableHandlerMethodTests {
ServletInvocableHandlerMethod handlerMethod = getHandlerMethod("responseStatus");
handlerMethod.invokeAndHandle(webRequest, mavContainer);
- assertFalse("Null return value + @ResponseStatus should result in 'no view resolution'",
- mavContainer.isResolveView());
+ assertTrue("Null return value + @ResponseStatus should result in 'request handled'",
+ mavContainer.isRequestHandled());
assertEquals(HttpStatus.BAD_REQUEST.value(), response.getStatus());
assertEquals("400 Bad Request", response.getErrorMessage());
@@ -85,8 +85,8 @@ public class ServletInvocableHandlerMethodTests {
ServletInvocableHandlerMethod handlerMethod = getHandlerMethod("httpServletResponse", HttpServletResponse.class);
handlerMethod.invokeAndHandle(webRequest, mavContainer);
- assertFalse("Null return value + HttpServletResponse arg should result in 'no view resolution'",
- mavContainer.isResolveView());
+ assertTrue("Null return value + HttpServletResponse arg should result in 'request handled'",
+ mavContainer.isRequestHandled());
}
@Test
@@ -98,8 +98,8 @@ public class ServletInvocableHandlerMethodTests {
ServletInvocableHandlerMethod handlerMethod = getHandlerMethod("notModified");
handlerMethod.invokeAndHandle(webRequest, mavContainer);
- assertFalse("Null return value + 'not modified' request should result in 'no view resolution'",
- mavContainer.isResolveView());
+ assertTrue("Null return value + 'not modified' request should result in 'request handled'",
+ mavContainer.isRequestHandled());
}
@Test
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/DefaultMethodReturnValueHandlerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/DefaultMethodReturnValueHandlerTests.java
index b29e8a701a6..acd37973db4 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/DefaultMethodReturnValueHandlerTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/DefaultMethodReturnValueHandlerTests.java
@@ -17,6 +17,7 @@
package org.springframework.web.servlet.mvc.method.annotation.support;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -70,7 +71,7 @@ public class DefaultMethodReturnValueHandlerTests {
assertEquals("viewName", mavContainer.getViewName());
assertSame(testBean, mavContainer.getModel().get("modelAttrName"));
- assertTrue(mavContainer.isResolveView());
+ assertFalse(mavContainer.isRequestHandled());
}
@Test(expected=UnsupportedOperationException.class)
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessorTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessorTests.java
index f9a1b8c8dee..47467740cf2 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessorTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessorTests.java
@@ -138,7 +138,7 @@ public class HttpEntityMethodProcessorTests {
Object result = processor.resolveArgument(paramHttpEntity, mavContainer, webRequest, null);
assertTrue(result instanceof HttpEntity);
- assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
+ assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
assertEquals("Invalid argument", body, ((HttpEntity>) result).getBody());
verify(messageConverter);
}
@@ -179,7 +179,7 @@ public class HttpEntityMethodProcessorTests {
processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest);
- assertFalse(mavContainer.isResolveView());
+ assertTrue(mavContainer.isRequestHandled());
verify(messageConverter);
}
@@ -197,7 +197,7 @@ public class HttpEntityMethodProcessorTests {
processor.handleReturnValue(returnValue, returnTypeResponseEntityProduces, mavContainer, webRequest);
- assertFalse(mavContainer.isResolveView());
+ assertTrue(mavContainer.isRequestHandled());
verify(messageConverter);
}
@@ -245,7 +245,7 @@ public class HttpEntityMethodProcessorTests {
processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest);
- assertFalse(mavContainer.isResolveView());
+ assertTrue(mavContainer.isRequestHandled());
assertEquals("headerValue", servletResponse.getHeader("headerName"));
}
@@ -264,7 +264,7 @@ public class HttpEntityMethodProcessorTests {
processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest);
- assertFalse(mavContainer.isResolveView());
+ assertTrue(mavContainer.isRequestHandled());
assertEquals("headerValue", outputMessage.getValue().getHeaders().get("header").get(0));
verify(messageConverter);
}
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandlerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandlerTests.java
index cffbc6630f3..4d88b14bbba 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandlerTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandlerTests.java
@@ -79,7 +79,7 @@ public class ModelAndViewMethodReturnValueHandlerTests {
public void handleReturnValueNull() throws Exception {
handler.handleReturnValue(null, getReturnValueParam("modelAndView"), mavContainer, webRequest);
- assertFalse(mavContainer.isResolveView());
+ assertTrue(mavContainer.isRequestHandled());
}
private MethodParameter getReturnValueParam(String methodName) throws Exception {
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolverTests.java
index 966b33e2091..231ce95b674 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolverTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolverTests.java
@@ -245,7 +245,7 @@ public class RequestPartMethodArgumentResolverTests {
Object actualValue = resolver.resolveArgument(parameter, mavContainer, webRequest, new ValidatingBinderFactory());
assertEquals("Invalid argument value", argValue, actualValue);
- assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
+ assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
verify(messageConverter);
}
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java
index e7e2712fefd..a01bc028bc8 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java
@@ -140,7 +140,7 @@ public class RequestResponseBodyMethodProcessorTests {
Object result = processor.resolveArgument(paramRequestBodyString, mavContainer, webRequest, null);
assertEquals("Invalid argument", body, result);
- assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
+ assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
verify(messageConverter);
}
@@ -211,7 +211,7 @@ public class RequestResponseBodyMethodProcessorTests {
processor.handleReturnValue(body, returnTypeString, mavContainer, webRequest);
- assertFalse("The ResolveView flag wasn't turned off", mavContainer.isResolveView());
+ assertTrue("The requestHandled flag wasn't set", mavContainer.isRequestHandled());
verify(messageConverter);
}
@@ -228,7 +228,7 @@ public class RequestResponseBodyMethodProcessorTests {
processor.handleReturnValue(body, returnTypeStringProduces, mavContainer, webRequest);
- assertFalse(mavContainer.isResolveView());
+ assertTrue(mavContainer.isRequestHandled());
verify(messageConverter);
}
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolverTests.java
index 4bc0352ce29..8f9be5cbd59 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolverTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolverTests.java
@@ -75,7 +75,7 @@ public class ServletRequestMethodArgumentResolverTests {
assertTrue("ServletRequest not supported", isSupported);
assertSame("Invalid result", servletRequest, result);
- assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
+ assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
}
@Test
@@ -89,7 +89,7 @@ public class ServletRequestMethodArgumentResolverTests {
assertTrue("Session not supported", isSupported);
assertSame("Invalid result", session, result);
- assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
+ assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
}
@Test
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolverTests.java
index f53ad820f0b..062ec1e6ff3 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolverTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolverTests.java
@@ -67,7 +67,7 @@ public class ServletResponseMethodArgumentResolverTests {
Object result = resolver.resolveArgument(servletResponseParameter, mavContainer, webRequest, null);
assertSame("Invalid result", servletResponse, result);
- assertFalse(mavContainer.isResolveView());
+ assertTrue(mavContainer.isRequestHandled());
}
@Test
@@ -78,7 +78,7 @@ public class ServletResponseMethodArgumentResolverTests {
Object result = resolver.resolveArgument(outputStreamParameter, mavContainer, webRequest, null);
assertSame("Invalid result", servletResponse.getOutputStream(), result);
- assertFalse(mavContainer.isResolveView());
+ assertTrue(mavContainer.isRequestHandled());
}
@Test
@@ -89,7 +89,7 @@ public class ServletResponseMethodArgumentResolverTests {
Object result = resolver.resolveArgument(writerParameter, mavContainer, webRequest, null);
assertSame("Invalid result", servletResponse.getWriter(), result);
- assertFalse(mavContainer.isResolveView());
+ assertTrue(mavContainer.isRequestHandled());
}
public void supportedParams(ServletResponse p0, OutputStream p1, Writer p2) {
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/DefaultFlashMapManagerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/DefaultFlashMapManagerTests.java
index e8cfc5046ec..50cecefe955 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/DefaultFlashMapManagerTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/DefaultFlashMapManagerTests.java
@@ -163,9 +163,7 @@ public class DefaultFlashMapManagerTests {
allMaps.add(flashMap);
flashMap.startExpirationPeriod(0);
}
-
- Thread.sleep(5);
-
+ Thread.sleep(100);
this.flashMapManager.requestStarted(this.request);
assertEquals(0, allMaps.size());
@@ -197,7 +195,7 @@ public class DefaultFlashMapManagerTests {
this.flashMapManager.setFlashMapTimeout(0);
this.flashMapManager.requestCompleted(this.request);
- Thread.sleep(1);
+ Thread.sleep(100);
List allMaps = getFlashMaps();
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java
index 3cb570ceb3b..4f74c5c3928 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java
@@ -129,7 +129,7 @@ public class RedirectViewTests {
assertEquals("http://url.somewhere.com/path?id=1", response.getHeader("Location"));
assertEquals("/path", flashMap.getTargetRequestPath());
- assertEquals(model, flashMap.getTargetRequestParams());
+ assertEquals(model, flashMap.getTargetRequestParams().toSingleValueMap());
}
@Test
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/ModelFactory.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/ModelFactory.java
index b8b2f578af2..24ab6e84a3b 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/ModelFactory.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/ModelFactory.java
@@ -211,7 +211,7 @@ public final class ModelFactory {
this.sessionAttributesHandler.storeAttributes(request, mavContainer.getModel());
}
- if (mavContainer.isResolveView()) {
+ if (!mavContainer.isRequestHandled()) {
updateBindingResult(request, mavContainer.getModel());
}
}
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolver.java b/org.springframework.web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolver.java
index fd16ad96c68..9dafb6d867a 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolver.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolver.java
@@ -22,7 +22,8 @@ import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
/**
- * Strategy interface for resolving method parameters into argument values in the context of a given request.
+ * Strategy interface for resolving method parameters into argument values in
+ * the context of a given request.
*
* @author Arjen Poutsma
* @since 3.1
@@ -30,21 +31,27 @@ import org.springframework.web.context.request.NativeWebRequest;
public interface HandlerMethodArgumentResolver {
/**
- * Whether the given {@linkplain MethodParameter method parameter} is supported by this resolver.
+ * Whether the given {@linkplain MethodParameter method parameter} is
+ * supported by this resolver.
*
* @param parameter the method parameter to check
- * @return {@code true} if this resolver supports the supplied parameter; {@code false} otherwise
+ * @return {@code true} if this resolver supports the supplied parameter;
+ * {@code false} otherwise
*/
boolean supportsParameter(MethodParameter parameter);
/**
- * Resolves a method parameter into an argument value from a given request. A {@link ModelAndViewContainer}
- * provides access to the model for the request. A {@link WebDataBinderFactory} provides a way to create
- * a {@link WebDataBinder} instance when needed for data binding and type conversion purposes.
+ * Resolves a method parameter into an argument value from a given request.
+ * A {@link ModelAndViewContainer} provides access to the model for the
+ * request. A {@link WebDataBinderFactory} provides a way to create
+ * a {@link WebDataBinder} instance when needed for data binding and
+ * type conversion purposes.
*
- * @param parameter the method parameter to resolve. This parameter must have previously been passed to
- * {@link #supportsParameter(org.springframework.core.MethodParameter)} and it must have returned {@code true}
- * @param mavContainer the {@link ModelAndViewContainer} for the current request
+ * @param parameter the method parameter to resolve. This parameter must
+ * have previously been passed to
+ * {@link #supportsParameter(org.springframework.core.MethodParameter)}
+ * and it must have returned {@code true}
+ * @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @param binderFactory a factory for creating {@link WebDataBinder} instances
* @return the resolved argument value, or {@code null}.
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/support/HandlerMethodReturnValueHandler.java b/org.springframework.web/src/main/java/org/springframework/web/method/support/HandlerMethodReturnValueHandler.java
index 9113228eb6e..8def3ac532b 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/support/HandlerMethodReturnValueHandler.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/support/HandlerMethodReturnValueHandler.java
@@ -20,7 +20,8 @@ import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
/**
- * Strategy interface to handle the value returned from the invocation of a handler method .
+ * Strategy interface to handle the value returned from the invocation of a
+ * handler method .
*
* @author Arjen Poutsma
* @since 3.1
@@ -28,24 +29,27 @@ import org.springframework.web.context.request.NativeWebRequest;
public interface HandlerMethodReturnValueHandler {
/**
- * Whether the given {@linkplain MethodParameter method return type} is supported by this handler.
+ * Whether the given {@linkplain MethodParameter method return type} is
+ * supported by this handler.
*
* @param returnType the method return type to check
- * @return {@code true} if this handler supports the supplied return type; {@code false} otherwise
+ * @return {@code true} if this handler supports the supplied return type;
+ * {@code false} otherwise
*/
boolean supportsReturnType(MethodParameter returnType);
/**
- * Handle the given return value by adding attributes to the model, setting the view (or view name),
- * or by writing to the response. {@link HandlerMethodReturnValueHandler} implementations should also
- * consider whether to set {@link ModelAndViewContainer#setResolveView(boolean)}, which is set to
- * {@code true} by default and therefore needs to be set to {@code false} explicitly if view
- * resolution is to be bypassed.
+ * Handle the given return value by adding attributes to the model and
+ * setting a view or setting the
+ * {@link ModelAndViewContainer#setRequestHandled} flag to {@code true}
+ * to indicate the response has been handled directly.
*
* @param returnValue the value returned from the handler method
- * @param returnType the type of the return value. This type must have previously been passed to
- * {@link #supportsReturnType(org.springframework.core.MethodParameter)} and it must have returned {@code true}
- * @param mavContainer the {@link ModelAndViewContainer} for the current request
+ * @param returnType the type of the return value. This type must have
+ * previously been passed to
+ * {@link #supportsReturnType(org.springframework.core.MethodParameter)}
+ * and it must have returned {@code true}
+ * @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @throws Exception if the return value handling results in an error
*/
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/support/ModelAndViewContainer.java b/org.springframework.web/src/main/java/org/springframework/web/method/support/ModelAndViewContainer.java
index 86cd6d17b64..8efcd1a0b8d 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/support/ModelAndViewContainer.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/support/ModelAndViewContainer.java
@@ -28,14 +28,14 @@ import org.springframework.validation.support.BindingAwareModelMap;
* {@link HandlerMethodReturnValueHandler}s during the course of invocation of
* a controller method.
*
- * The {@link #setResolveView(boolean)} flag can be used to indicate that
- * view resolution is not required (e.g. {@code @ResponseBody} method).
+ *
The {@link #setRequestHandled} flag can be used to indicate the request
+ * has been handled directly and view resolution is not required.
*
- *
A default {@link Model} is created at instantiation and used thereafter.
- * The {@link #setRedirectModel(ModelMap)} method can be used to provide a
- * separate model to use potentially in case of a redirect.
- * The {@link #setUseRedirectModel()} can be used to enable use of the
- * redirect model if the controller decides to redirect.
+ *
A default {@link Model} is automatically created at instantiation.
+ * An alternate model instance may be provided via {@link #setRedirectModel}
+ * for use in a redirect scenario. When {@link #setUseRedirectModel} is set
+ * to {@code true} signalling a redirect scenario, the {@link #getModel()}
+ * returns the redirect model instead of the default model.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -44,12 +44,14 @@ public class ModelAndViewContainer {
private Object view;
- private boolean resolveView = true;
+ private boolean requestHandled = false;
private final ModelMap model = new BindingAwareModelMap();
private ModelMap redirectModel;
+ private boolean ignoreDefaultModelOnRedirect = false;
+
private boolean useRedirectModel = false;
/**
@@ -99,7 +101,7 @@ public class ModelAndViewContainer {
}
/**
- * Whether view resolution is required or not.
+ * Signal a scenario where the request is handled directly.
*
A {@link HandlerMethodReturnValueHandler} may use this flag to
* indicate the response has been fully handled and view resolution
* is not required (e.g. {@code @ResponseBody}).
@@ -109,54 +111,64 @@ public class ModelAndViewContainer {
* a complete response depending on the method return value.
*
The default value is {@code true}.
*/
- public void setResolveView(boolean resolveView) {
- this.resolveView = resolveView;
+ public void setRequestHandled(boolean requestHandled) {
+ this.requestHandled = requestHandled;
}
/**
- * Whether view resolution is required or not.
+ * Whether the request is handled directly.
*/
- public boolean isResolveView() {
- return this.resolveView;
+ public boolean isRequestHandled() {
+ return this.requestHandled;
}
/**
- * Return the default model created at instantiation or the one provided
- * via {@link #setRedirectModel(ModelMap)} as long as it has been enabled
- * via {@link #setUseRedirectModel()}.
+ * Return the model to use. This is either the default model created at
+ * instantiation or the redirect model if {@link #setUseRedirectModel}
+ * is set to {@code true}. If a redirect model was never provided via
+ * {@link #setRedirectModel}, return the default model unless
+ * {@link #setIgnoreDefaultModelOnRedirect} is set to {@code true}.
*/
public ModelMap getModel() {
- if ((this.redirectModel != null) && this.useRedirectModel) {
+ if (!this.useRedirectModel) {
+ return this.model;
+ }
+ else if (this.redirectModel != null) {
return this.redirectModel;
}
else {
- return this.model;
+ return this.ignoreDefaultModelOnRedirect ? new ModelMap() : this.model;
}
}
/**
- * Provide a model instance to use in case the controller redirects.
- * Note that {@link #setUseRedirectModel()} must also be called in order
- * to enable use of the redirect model.
+ * Provide a separate model instance to use in a redirect scenario.
+ * The provided additional model however is not used used unless
+ * {@link #setUseRedirectModel(boolean)} gets set to {@code true} to signal
+ * a redirect scenario.
*/
public void setRedirectModel(ModelMap redirectModel) {
this.redirectModel = redirectModel;
}
/**
- * Return the redirect model provided via
- * {@link #setRedirectModel(ModelMap)} or {@code null} if not provided.
+ * When set to {@code true} the default model is never used in a redirect
+ * scenario. So if a redirect model is not available, an empty model is
+ * used instead.
+ *
When set to {@code false} the default model can be used in a redirect
+ * scenario if a redirect model is not available.
+ *
The default setting is {@code false}.
*/
- public ModelMap getRedirectModel() {
- return this.redirectModel;
+ public void setIgnoreDefaultModelOnRedirect(boolean ignoreDefaultModelOnRedirect) {
+ this.ignoreDefaultModelOnRedirect = ignoreDefaultModelOnRedirect;
}
/**
- * Indicate that the redirect model provided via
- * {@link #setRedirectModel(ModelMap)} should be used.
+ * Signal the conditions for using a redirect model are in place -- e.g.
+ * the controller has requested a redirect.
*/
- public void setUseRedirectModel() {
- this.useRedirectModel = true;
+ public void setUseRedirectModel(boolean useRedirectModel) {
+ this.useRedirectModel = useRedirectModel;
}
/**
@@ -210,7 +222,7 @@ public class ModelAndViewContainer {
@Override
public String toString() {
StringBuilder sb = new StringBuilder("ModelAndViewContainer: ");
- if (isResolveView()) {
+ if (!isRequestHandled()) {
if (isViewReference()) {
sb.append("reference to view with name '").append(this.view).append("'");
}
@@ -220,7 +232,7 @@ public class ModelAndViewContainer {
sb.append("; model is ").append(getModel());
}
else {
- sb.append("View resolution not required");
+ sb.append("Request handled directly");
}
return sb.toString();
}
diff --git a/org.springframework.web/src/main/java/org/springframework/web/util/WebUtils.java b/org.springframework.web/src/main/java/org/springframework/web/util/WebUtils.java
index b2e2d222586..fa736be6a75 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/util/WebUtils.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/util/WebUtils.java
@@ -724,29 +724,4 @@ public abstract class WebUtils {
return urlPath.substring(begin, end);
}
- /**
- * Extracts the path from the given URL by removing the query at the end
- * and the scheme and authority in the front, if present.
- * @param url a URL, never {@code null}
- * @return the extracted URL path
- */
- public static String extractUrlPath(String url) {
- // Remove query/fragment
- int end = url.indexOf('?');
- if (end == -1) {
- end = url.indexOf('#');
- if (end == -1) {
- end = url.length();
- }
- }
- url = url.substring(0, end);
- // Remove scheme + authority
- int start = url.indexOf("://");
- if (start != -1) {
- start = url.indexOf('/', start + 3);
- url = (start != -1 ) ? url.substring(start) : "";
- }
- return url;
- }
-
}
diff --git a/org.springframework.web/src/test/java/org/springframework/web/method/support/ModelAndViewContainerTests.java b/org.springframework.web/src/test/java/org/springframework/web/method/support/ModelAndViewContainerTests.java
new file mode 100644
index 00000000000..cd369258b9c
--- /dev/null
+++ b/org.springframework.web/src/test/java/org/springframework/web/method/support/ModelAndViewContainerTests.java
@@ -0,0 +1,75 @@
+/*
+ * 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.method.support;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.ui.ModelMap;
+
+/**
+ * Test fixture for {@link ModelAndViewContainer}.
+ *
+ * @author Rossen Stoyanchev
+ * @since 3.1
+ */
+public class ModelAndViewContainerTests {
+
+ private ModelAndViewContainer mavContainer;
+
+ @Before
+ public void setup() {
+ this.mavContainer = new ModelAndViewContainer();
+ }
+
+ @Test
+ public void getModel() {
+ this.mavContainer.addAttribute("name", "value");
+ assertEquals(1, this.mavContainer.getModel().size());
+ }
+
+ @Test
+ public void getModelRedirectModel() {
+ ModelMap redirectModel = new ModelMap("name", "redirectValue");
+ this.mavContainer.setRedirectModel(redirectModel);
+ this.mavContainer.addAttribute("name", "value");
+
+ assertEquals("Default model should be used if not in redirect scenario",
+ "value", this.mavContainer.getModel().get("name"));
+
+ this.mavContainer.setUseRedirectModel(true);
+
+ assertEquals("Redirect model should be used in redirect scenario",
+ "redirectValue", this.mavContainer.getModel().get("name"));
+ }
+
+ @Test
+ public void getModelIgnoreDefaultModelOnRedirect() {
+ this.mavContainer.addAttribute("name", "value");
+ this.mavContainer.setUseRedirectModel(true);
+
+ assertEquals("Default model should be used since no redirect model was provided",
+ 1, this.mavContainer.getModel().size());
+
+ this.mavContainer.setIgnoreDefaultModelOnRedirect(true);
+
+ assertEquals("Empty model should be returned if no redirect model is available",
+ 0, this.mavContainer.getModel().size());
+ }
+
+}
diff --git a/org.springframework.web/src/test/java/org/springframework/web/util/WebUtilsTests.java b/org.springframework.web/src/test/java/org/springframework/web/util/WebUtilsTests.java
index cf33f29b640..616dc66686b 100644
--- a/org.springframework.web/src/test/java/org/springframework/web/util/WebUtilsTests.java
+++ b/org.springframework.web/src/test/java/org/springframework/web/util/WebUtilsTests.java
@@ -64,15 +64,4 @@ public class WebUtilsTests {
assertEquals("view.html", WebUtils.extractFullFilenameFromUrlPath("/products/view.html?param=/path/a.do"));
}
- @Test
- public void extractUriPath() {
- assertEquals("", WebUtils.extractUrlPath("http://example.com"));
- assertEquals("/", WebUtils.extractUrlPath("http://example.com/"));
- assertEquals("/rfc/rfc3986.txt", WebUtils.extractUrlPath("http://www.ietf.org/rfc/rfc3986.txt"));
- assertEquals("/over/there", WebUtils.extractUrlPath("http://example.com/over/there?name=ferret#nose"));
- assertEquals("/over/there", WebUtils.extractUrlPath("http://example.com/over/there#nose"));
- assertEquals("/over/there", WebUtils.extractUrlPath("/over/there?name=ferret#nose"));
- assertEquals("/over/there", WebUtils.extractUrlPath("/over/there?url=http://example.com"));
- }
-
}