Merge branch '3.1.x'
This commit is contained in:
@@ -815,7 +815,7 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
}
|
||||
}
|
||||
|
||||
this.flashMapManager.requestStarted(request);
|
||||
this.flashMapManager.requestStarted(request, response);
|
||||
|
||||
// Make framework objects available to handlers and view objects.
|
||||
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
|
||||
@@ -827,7 +827,7 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
doDispatch(request, response);
|
||||
}
|
||||
finally {
|
||||
this.flashMapManager.requestCompleted(request);
|
||||
this.flashMapManager.requestCompleted(request, response);
|
||||
|
||||
// Restore the original attribute snapshot, in case of an include.
|
||||
if (attributesSnapshot != null) {
|
||||
|
||||
@@ -63,6 +63,8 @@ public final class FlashMap extends HashMap<String, Object> implements Comparabl
|
||||
/**
|
||||
* Create a new instance with an id uniquely identifying the creator of
|
||||
* this FlashMap.
|
||||
* @param createdBy identifies the FlashMapManager instance that created
|
||||
* and will manage this FlashMap instance (e.g. via a hashCode)
|
||||
*/
|
||||
public FlashMap(int createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.web.servlet;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* A strategy interface for storing, retrieving, and managing {@code FlashMap}
|
||||
@@ -64,8 +65,9 @@ public interface FlashMapManager {
|
||||
* <li>Clean expired FlashMap instances.
|
||||
* </ol>
|
||||
* @param request the current request
|
||||
* @param response the current response
|
||||
*/
|
||||
void requestStarted(HttpServletRequest request);
|
||||
void requestStarted(HttpServletRequest request, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* Start the expiration period of the "output" FlashMap save it in the
|
||||
@@ -73,7 +75,8 @@ public interface FlashMapManager {
|
||||
* <p>The "output" FlashMap should not be saved if it is empty or if it was
|
||||
* not created by the current FlashMapManager instance.
|
||||
* @param request the current request
|
||||
* @param response the current response
|
||||
*/
|
||||
void requestCompleted(HttpServletRequest request);
|
||||
void requestCompleted(HttpServletRequest request, HttpServletResponse response);
|
||||
|
||||
}
|
||||
|
||||
@@ -23,13 +23,14 @@ import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link org.springframework.web.servlet.HandlerExceptionResolver HandlerExceptionResolver}
|
||||
* implementations that support handling exceptions from {@link HandlerMethod}s rather than handlers.
|
||||
* Abstract base class for
|
||||
* {@link org.springframework.web.servlet.HandlerExceptionResolver HandlerExceptionResolver}
|
||||
* implementations that support handling exceptions from handlers of type {@link HandlerMethod}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
*/
|
||||
public class AbstractHandlerMethodExceptionResolver extends AbstractHandlerExceptionResolver {
|
||||
public abstract class AbstractHandlerMethodExceptionResolver extends AbstractHandlerExceptionResolver {
|
||||
|
||||
/**
|
||||
* Checks if the handler is a {@link HandlerMethod} instance and performs the check against the bean
|
||||
@@ -52,10 +53,10 @@ public class AbstractHandlerMethodExceptionResolver extends AbstractHandlerExcep
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final ModelAndView doResolveException(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
Object handler,
|
||||
Exception ex) {
|
||||
protected final ModelAndView doResolveException(
|
||||
HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler, Exception ex) {
|
||||
|
||||
return doResolveHandlerMethodException(request, response, (HandlerMethod) handler, ex);
|
||||
}
|
||||
|
||||
@@ -73,11 +74,8 @@ public class AbstractHandlerMethodExceptionResolver extends AbstractHandlerExcep
|
||||
* @param ex the exception that got thrown during handler execution
|
||||
* @return a corresponding ModelAndView to forward to, or <code>null</code> for default processing
|
||||
*/
|
||||
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
HandlerMethod handlerMethod,
|
||||
Exception ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract ModelAndView doResolveHandlerMethodException(
|
||||
HttpServletRequest request, HttpServletResponse response,
|
||||
HandlerMethod handlerMethod, Exception ex);
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
/**
|
||||
@@ -86,7 +87,8 @@ public abstract class AbstractUrlViewController extends AbstractController {
|
||||
|
||||
/**
|
||||
* Retrieves the URL path to use for lookup and delegates to
|
||||
* {@link #getViewNameForRequest}.
|
||||
* {@link #getViewNameForRequest}. Also adds the content of
|
||||
* {@link RequestContextUtils#getInputFlashMap} to the model.
|
||||
*/
|
||||
@Override
|
||||
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
|
||||
@@ -95,7 +97,7 @@ public abstract class AbstractUrlViewController extends AbstractController {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Returning view name '" + viewName + "' for lookup path [" + lookupPath + "]");
|
||||
}
|
||||
return new ModelAndView(viewName);
|
||||
return new ModelAndView(viewName, RequestContextUtils.getInputFlashMap(request));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
|
||||
/**
|
||||
* <p>Trivial controller that always returns a named view. The view
|
||||
@@ -87,12 +88,13 @@ public class ParameterizableViewController extends AbstractController {
|
||||
|
||||
/**
|
||||
* Return a ModelAndView object with the specified view name.
|
||||
* The content of {@link RequestContextUtils#getInputFlashMap} is also added to the model.
|
||||
* @see #getViewName()
|
||||
*/
|
||||
@Override
|
||||
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
|
||||
throws Exception {
|
||||
return new ModelAndView(getViewName());
|
||||
return new ModelAndView(getViewName(), RequestContextUtils.getInputFlashMap(request));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
||||
* <ol>
|
||||
* <li>Sort 'Accept' header media types by quality value via
|
||||
* {@link MediaType#sortByQualityValue(List)} and iterate the list.
|
||||
* <li>Get the lowest index of matching media types from each "produces"
|
||||
* <li>Get the first index of matching media types in each "produces"
|
||||
* condition first matching with {@link MediaType#equals(Object)} and
|
||||
* then with {@link MediaType#includes(MediaType)}.
|
||||
* <li>If a lower index is found, the condition at that index wins.
|
||||
@@ -220,7 +220,9 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
||||
|
||||
private int indexOfEqualMediaType(MediaType mediaType) {
|
||||
for (int i = 0; i < getExpressionsToCompare().size(); i++) {
|
||||
if (mediaType.equals(getExpressionsToCompare().get(i).getMediaType())) {
|
||||
MediaType currentMediaType = getExpressionsToCompare().get(i).getMediaType();
|
||||
if (mediaType.getType().equalsIgnoreCase(currentMediaType.getType()) &&
|
||||
mediaType.getSubtype().equalsIgnoreCase(currentMediaType.getSubtype())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -39,13 +39,13 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
/**
|
||||
* Resolves {@link HttpEntity} method argument values and also handles
|
||||
* both {@link HttpEntity} and {@link ResponseEntity} return values.
|
||||
*
|
||||
* <p>An {@link HttpEntity} return type has a set purpose. Therefore this
|
||||
* handler should be configured ahead of handlers that support any return
|
||||
* both {@link HttpEntity} and {@link ResponseEntity} return values.
|
||||
*
|
||||
* <p>An {@link HttpEntity} return type has a set purpose. Therefore this
|
||||
* handler should be configured ahead of handlers that support any return
|
||||
* value type annotated with {@code @ModelAttribute} or {@code @ResponseBody}
|
||||
* to ensure they don't take over.
|
||||
*
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
@@ -66,10 +66,9 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
|
||||
return HttpEntity.class.equals(parameterType) || ResponseEntity.class.equals(parameterType);
|
||||
}
|
||||
|
||||
public Object resolveArgument(MethodParameter parameter,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest,
|
||||
WebDataBinderFactory binderFactory)
|
||||
public Object resolveArgument(
|
||||
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||
throws IOException, HttpMediaTypeNotSupportedException {
|
||||
|
||||
HttpInputMessage inputMessage = createInputMessage(webRequest);
|
||||
@@ -100,11 +99,11 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
|
||||
+ "in method " + parameter.getMethod() + "is not parameterized");
|
||||
}
|
||||
|
||||
public void handleReturnValue(Object returnValue,
|
||||
MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest) throws Exception {
|
||||
|
||||
public void handleReturnValue(
|
||||
Object returnValue, MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||
throws Exception {
|
||||
|
||||
mavContainer.setRequestHandled(true);
|
||||
|
||||
if (returnValue == null) {
|
||||
@@ -135,4 +134,4 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,15 +25,15 @@ 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
|
||||
* information to the {@link ModelAndViewContainer}.
|
||||
*
|
||||
* <p>If the return value is {@code null}, the
|
||||
* {@link ModelAndViewContainer#setRequestHandled(boolean)} flag is set to
|
||||
*
|
||||
* <p>If the return value is {@code null}, the
|
||||
* {@link ModelAndViewContainer#setRequestHandled(boolean)} flag is set to
|
||||
* {@code false} to indicate the request was handled directly.
|
||||
*
|
||||
* <p>A {@link ModelAndView} return type has a set purpose. Therefore this
|
||||
* handler should be configured ahead of handlers that support any return
|
||||
*
|
||||
* <p>A {@link ModelAndView} return type has a set purpose. Therefore this
|
||||
* handler should be configured ahead of handlers that support any return
|
||||
* value type annotated with {@code @ModelAttribute} or {@code @ResponseBody}
|
||||
* to ensure they don't take over.
|
||||
*
|
||||
@@ -41,20 +41,21 @@ import org.springframework.web.servlet.View;
|
||||
* @since 3.1
|
||||
*/
|
||||
public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
|
||||
|
||||
|
||||
public boolean supportsReturnType(MethodParameter returnType) {
|
||||
return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
|
||||
}
|
||||
|
||||
public void handleReturnValue(Object returnValue,
|
||||
MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest) throws Exception {
|
||||
public void handleReturnValue(
|
||||
Object returnValue, MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||
throws Exception {
|
||||
|
||||
if (returnValue == null) {
|
||||
mavContainer.setRequestHandled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ModelAndView mav = (ModelAndView) returnValue;
|
||||
if (mav.isReference()) {
|
||||
String viewName = mav.getViewName();
|
||||
@@ -75,4 +76,4 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
|
||||
mavContainer.addAllAttributes(mav.getModel());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -29,25 +29,25 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
|
||||
|
||||
/**
|
||||
* This return value handler is intended to be ordered after all others as it
|
||||
* This return value handler is intended to be ordered after all others as it
|
||||
* attempts to handle _any_ return value type (i.e. returns {@code true} for
|
||||
* all return types).
|
||||
*
|
||||
*
|
||||
* <p>The return value is handled either with a {@link ModelAndViewResolver}
|
||||
* or otherwise by regarding it as a model attribute if it is a non-simple
|
||||
* type. If neither of these succeeds (essentially simple type other than
|
||||
* or otherwise by regarding it as a model attribute if it is a non-simple
|
||||
* type. If neither of these succeeds (essentially simple type other than
|
||||
* String), {@link UnsupportedOperationException} is raised.
|
||||
*
|
||||
* <p><strong>Note:</strong> This class is primarily needed to support
|
||||
*
|
||||
* <p><strong>Note:</strong> This class is primarily needed to support
|
||||
* {@link ModelAndViewResolver}, which unfortunately cannot be properly
|
||||
* adapted to the {@link HandlerMethodReturnValueHandler} contract since the
|
||||
* adapted to the {@link HandlerMethodReturnValueHandler} contract since the
|
||||
* {@link HandlerMethodReturnValueHandler#supportsReturnType} method
|
||||
* cannot be implemented. Hence {@code ModelAndViewResolver}s are limited
|
||||
* to always being invoked at the end after all other return value
|
||||
* handlers have been given a chance. It is recommended to re-implement
|
||||
* to always being invoked at the end after all other return value
|
||||
* handlers have been given a chance. It is recommended to re-implement
|
||||
* a {@code ModelAndViewResolver} as {@code HandlerMethodReturnValueHandler},
|
||||
* which also provides better access to the return type and method information.
|
||||
*
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
*/
|
||||
@@ -71,10 +71,10 @@ public class ModelAndViewResolverMethodReturnValueHandler implements HandlerMeth
|
||||
return true;
|
||||
}
|
||||
|
||||
public void handleReturnValue(Object returnValue,
|
||||
MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest request) throws Exception {
|
||||
public void handleReturnValue(
|
||||
Object returnValue, MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer, NativeWebRequest request)
|
||||
throws Exception {
|
||||
|
||||
if (this.mavResolvers != null) {
|
||||
for (ModelAndViewResolver mavResolver : this.mavResolvers) {
|
||||
@@ -93,7 +93,7 @@ public class ModelAndViewResolverMethodReturnValueHandler implements HandlerMeth
|
||||
}
|
||||
}
|
||||
|
||||
// No suitable ModelAndViewResolver..
|
||||
// No suitable ModelAndViewResolver..
|
||||
|
||||
if (this.modelAttributeProcessor.supportsReturnType(returnType)) {
|
||||
this.modelAttributeProcessor.handleReturnValue(returnValue, returnType, mavContainer, request);
|
||||
@@ -104,4 +104,4 @@ public class ModelAndViewResolverMethodReturnValueHandler implements HandlerMeth
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -30,8 +30,8 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap;
|
||||
|
||||
/**
|
||||
* Resolves method arguments of type {@link RedirectAttributes}.
|
||||
*
|
||||
* Resolves method arguments of type {@link RedirectAttributes}.
|
||||
*
|
||||
* <p>This resolver must be listed ahead of {@link org.springframework.web.method.annotation.ModelMethodProcessor} and
|
||||
* {@link org.springframework.web.method.annotation.MapMethodProcessor}, which support {@link Map} and {@link Model}
|
||||
* arguments both of which are "super" types of {@code RedirectAttributes}
|
||||
@@ -46,10 +46,11 @@ public class RedirectAttributesMethodArgumentResolver implements HandlerMethodAr
|
||||
return RedirectAttributes.class.isAssignableFrom(parameter.getParameterType());
|
||||
}
|
||||
|
||||
public Object resolveArgument(MethodParameter parameter,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest,
|
||||
WebDataBinderFactory binderFactory) throws Exception {
|
||||
public Object resolveArgument(
|
||||
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||
throws Exception {
|
||||
|
||||
DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null);
|
||||
ModelMap redirectAttributes = new RedirectAttributesModelMap(dataBinder);
|
||||
mavContainer.setRedirectModel(redirectAttributes);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -89,9 +89,9 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
||||
* @param mavContainer the {@link ModelAndViewContainer} for the current request
|
||||
* @param providedArgs argument values to try to use without the need for view resolution
|
||||
*/
|
||||
public final void invokeAndHandle(NativeWebRequest request,
|
||||
ModelAndViewContainer mavContainer,
|
||||
Object...providedArgs) throws Exception {
|
||||
public final void invokeAndHandle(
|
||||
NativeWebRequest request, ModelAndViewContainer mavContainer,
|
||||
Object... providedArgs) throws Exception {
|
||||
|
||||
Object returnValue = invokeForRequest(request, mavContainer, providedArgs);
|
||||
|
||||
@@ -124,7 +124,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
||||
sb.append("[value=" + returnValue + "]");
|
||||
return getDetailedErrorMessage(sb.toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the response status according to the {@link ResponseStatus} annotation.
|
||||
*/
|
||||
@@ -157,4 +157,4 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
||||
private boolean hasResponseStatus() {
|
||||
return responseStatus != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -37,7 +37,7 @@ import org.springframework.web.multipart.MultipartRequest;
|
||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
|
||||
/**
|
||||
* Resolves request-related method argument values of the following types:
|
||||
* Resolves request-related method argument values of the following types:
|
||||
* <ul>
|
||||
* <li>{@link WebRequest}
|
||||
* <li>{@link ServletRequest}
|
||||
@@ -57,20 +57,20 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
|
||||
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
return WebRequest.class.isAssignableFrom(paramType) ||
|
||||
return WebRequest.class.isAssignableFrom(paramType) ||
|
||||
ServletRequest.class.isAssignableFrom(paramType) ||
|
||||
MultipartRequest.class.isAssignableFrom(paramType) ||
|
||||
HttpSession.class.isAssignableFrom(paramType) ||
|
||||
HttpSession.class.isAssignableFrom(paramType) ||
|
||||
Principal.class.isAssignableFrom(paramType) ||
|
||||
Locale.class.equals(paramType) ||
|
||||
Locale.class.equals(paramType) ||
|
||||
InputStream.class.isAssignableFrom(paramType) ||
|
||||
Reader.class.isAssignableFrom(paramType);
|
||||
}
|
||||
|
||||
public Object resolveArgument(MethodParameter parameter,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest,
|
||||
WebDataBinderFactory binderFactory) throws IOException {
|
||||
public Object resolveArgument(
|
||||
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||
throws IOException {
|
||||
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
if (WebRequest.class.isAssignableFrom(paramType)) {
|
||||
@@ -108,4 +108,4 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -47,20 +47,20 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
return ServletResponse.class.isAssignableFrom(paramType)
|
||||
|| OutputStream.class.isAssignableFrom(paramType)
|
||||
|| OutputStream.class.isAssignableFrom(paramType)
|
||||
|| Writer.class.isAssignableFrom(paramType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set {@link ModelAndViewContainer#setRequestHandled(boolean)} to
|
||||
* {@code false} to indicate that the method signature provides access
|
||||
* to the response. If subsequently the underlying method returns
|
||||
* Set {@link ModelAndViewContainer#setRequestHandled(boolean)} to
|
||||
* {@code false} to indicate that the method signature provides access
|
||||
* to the response. If subsequently the underlying method returns
|
||||
* {@code null}, the request is considered directly handled.
|
||||
*/
|
||||
public Object resolveArgument(MethodParameter parameter,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest,
|
||||
WebDataBinderFactory binderFactory) throws IOException {
|
||||
public Object resolveArgument(
|
||||
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||
throws IOException {
|
||||
|
||||
mavContainer.setRequestHandled(true);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -28,7 +28,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Resolvers argument values of type {@link UriComponentsBuilder}.
|
||||
*
|
||||
*
|
||||
* <p>The returned instance is initialized via
|
||||
* {@link ServletUriComponentsBuilder#fromServletMapping(HttpServletRequest)}.
|
||||
*
|
||||
@@ -41,11 +41,11 @@ public class UriComponentsBuilderMethodArgumentResolver implements HandlerMethod
|
||||
return UriComponentsBuilder.class.isAssignableFrom(parameter.getParameterType());
|
||||
}
|
||||
|
||||
public Object resolveArgument(MethodParameter parameter,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest,
|
||||
WebDataBinderFactory binderFactory) throws Exception {
|
||||
|
||||
public Object resolveArgument(
|
||||
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||
throws Exception {
|
||||
|
||||
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||
return ServletUriComponentsBuilder.fromServletMapping(request);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -27,14 +27,14 @@ import org.springframework.web.servlet.View;
|
||||
/**
|
||||
* Handles return values that are of type {@link View}.
|
||||
*
|
||||
* <p>A {@code null} return value is left as-is leaving it to the configured
|
||||
* {@link RequestToViewNameTranslator} to select a view name by convention.
|
||||
* <p>A {@code null} return value is left as-is leaving it to the configured
|
||||
* {@link RequestToViewNameTranslator} to select a view name by convention.
|
||||
*
|
||||
* <p>A {@link View} return type has a set purpose. Therefore this handler
|
||||
* should be configured ahead of handlers that support any return value type
|
||||
* <p>A {@link View} return type has a set purpose. Therefore this handler
|
||||
* should be configured ahead of handlers that support any return value type
|
||||
* annotated with {@code @ModelAttribute} or {@code @ResponseBody} to ensure
|
||||
* they don't take over.
|
||||
*
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
*/
|
||||
@@ -44,10 +44,11 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan
|
||||
return View.class.isAssignableFrom(returnType.getParameterType());
|
||||
}
|
||||
|
||||
public void handleReturnValue(Object returnValue,
|
||||
MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest) throws Exception {
|
||||
public void handleReturnValue(
|
||||
Object returnValue, MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||
throws Exception {
|
||||
|
||||
if (returnValue == null) {
|
||||
return;
|
||||
}
|
||||
@@ -62,7 +63,7 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan
|
||||
}
|
||||
else {
|
||||
// should not happen
|
||||
throw new UnsupportedOperationException("Unexpected return type: " +
|
||||
throw new UnsupportedOperationException("Unexpected return type: " +
|
||||
returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -26,12 +26,12 @@ import org.springframework.web.servlet.RequestToViewNameTranslator;
|
||||
* Handles return values of types {@code void} and {@code String} interpreting
|
||||
* them as view name reference.
|
||||
*
|
||||
* <p>A {@code null} return value, either due to a {@code void} return type or
|
||||
* as the actual return value is left as-is allowing the configured
|
||||
* <p>A {@code null} return value, either due to a {@code void} return type or
|
||||
* as the actual return value is left as-is allowing the configured
|
||||
* {@link RequestToViewNameTranslator} to select a view name by convention.
|
||||
*
|
||||
* <p>A String return value can be interpreted in more than one ways depending
|
||||
* on the presence of annotations like {@code @ModelAttribute} or
|
||||
* <p>A String return value can be interpreted in more than one ways depending
|
||||
* on the presence of annotations like {@code @ModelAttribute} or
|
||||
* {@code @ResponseBody}. Therefore this handler should be configured after
|
||||
* the handlers that support these annotations.
|
||||
*
|
||||
@@ -45,10 +45,11 @@ public class ViewNameMethodReturnValueHandler implements HandlerMethodReturnValu
|
||||
return (void.class.equals(paramType) || String.class.equals(paramType));
|
||||
}
|
||||
|
||||
public void handleReturnValue(Object returnValue,
|
||||
MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest) throws Exception {
|
||||
public void handleReturnValue(
|
||||
Object returnValue, MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||
throws Exception {
|
||||
|
||||
if (returnValue == null) {
|
||||
return;
|
||||
}
|
||||
@@ -61,7 +62,7 @@ public class ViewNameMethodReturnValueHandler implements HandlerMethodReturnValu
|
||||
}
|
||||
else {
|
||||
// should not happen
|
||||
throw new UnsupportedOperationException("Unexpected return type: " +
|
||||
throw new UnsupportedOperationException("Unexpected return type: " +
|
||||
returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
|
||||
}
|
||||
}
|
||||
@@ -69,7 +70,7 @@ public class ViewNameMethodReturnValueHandler implements HandlerMethodReturnValu
|
||||
/**
|
||||
* Whether the given view name is a redirect view reference.
|
||||
* @param viewName the view name to check, never {@code null}
|
||||
* @return "true" if the given view name is recognized as a redirect view
|
||||
* @return "true" if the given view name is recognized as a redirect view
|
||||
* reference; "false" otherwise.
|
||||
*/
|
||||
protected boolean isRedirectViewName(String viewName) {
|
||||
|
||||
@@ -22,10 +22,12 @@ import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -47,24 +49,46 @@ public class DefaultFlashMapManager implements FlashMapManager {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DefaultFlashMapManager.class);
|
||||
|
||||
private int flashTimeout = 180;
|
||||
private int flashMapTimeout = 180;
|
||||
|
||||
private final UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
private UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
|
||||
/**
|
||||
* Set the amount of time in seconds after a {@link FlashMap} is saved
|
||||
* (at request completion) and before it expires.
|
||||
* <p>The default value is 180 seconds.
|
||||
*/
|
||||
public void setFlashMapTimeout(int flashTimeout) {
|
||||
this.flashTimeout = flashTimeout;
|
||||
public void setFlashMapTimeout(int flashMapTimeout) {
|
||||
this.flashMapTimeout = flashMapTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the amount of time in seconds before a FlashMap expires.
|
||||
*/
|
||||
public int getFlashMapTimeout() {
|
||||
return flashMapTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UrlPathHelper to use to obtain the request URI.
|
||||
*/
|
||||
public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
|
||||
Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
|
||||
this.urlPathHelper = urlPathHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the UrlPathHelper implementation for the request URI.
|
||||
*/
|
||||
public UrlPathHelper getUrlPathHelper() {
|
||||
return urlPathHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>An HTTP session is never created by this method.
|
||||
*/
|
||||
public void requestStarted(HttpServletRequest request) {
|
||||
public final void requestStarted(HttpServletRequest request, HttpServletResponse response) {
|
||||
if (request.getAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE) != null) {
|
||||
return;
|
||||
}
|
||||
@@ -164,9 +188,9 @@ public class DefaultFlashMapManager implements FlashMapManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate all flash maps and remove expired ones.
|
||||
* Check and remove expired FlashMaps instances.
|
||||
*/
|
||||
private void removeExpiredFlashMaps(HttpServletRequest request) {
|
||||
protected void removeExpiredFlashMaps(HttpServletRequest request) {
|
||||
List<FlashMap> allMaps = retrieveFlashMaps(request, false);
|
||||
if (CollectionUtils.isEmpty(allMaps)) {
|
||||
return;
|
||||
@@ -189,7 +213,7 @@ public class DefaultFlashMapManager implements FlashMapManager {
|
||||
* {@inheritDoc}
|
||||
* <p>An HTTP session is never created if the "output" FlashMap is empty.
|
||||
*/
|
||||
public void requestCompleted(HttpServletRequest request) {
|
||||
public void requestCompleted(HttpServletRequest request, HttpServletResponse response) {
|
||||
FlashMap flashMap = (FlashMap) request.getAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE);
|
||||
if (flashMap == null) {
|
||||
throw new IllegalStateException("requestCompleted called but \"output\" FlashMap was never created");
|
||||
@@ -198,24 +222,35 @@ public class DefaultFlashMapManager implements FlashMapManager {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Saving FlashMap=" + flashMap);
|
||||
}
|
||||
onSaveFlashMap(flashMap, request);
|
||||
retrieveFlashMaps(request, true).add(flashMap);
|
||||
onSaveFlashMap(flashMap, request, response);
|
||||
saveFlashMap(flashMap, request, response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a FlashMap before it is stored in the HTTP Session.
|
||||
* Update a FlashMap before it is stored in the underlying storage.
|
||||
* <p>The default implementation starts the expiration period and ensures the
|
||||
* target request path is decoded and normalized if it is relative.
|
||||
* @param flashMap the flash map to be saved
|
||||
* @param request the current request
|
||||
* @param response the current response
|
||||
*/
|
||||
protected void onSaveFlashMap(FlashMap flashMap, HttpServletRequest request) {
|
||||
protected void onSaveFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) {
|
||||
String targetPath = flashMap.getTargetRequestPath();
|
||||
flashMap.setTargetRequestPath(decodeAndNormalizePath(targetPath, request));
|
||||
flashMap.startExpirationPeriod(this.flashTimeout);
|
||||
flashMap.startExpirationPeriod(this.flashMapTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the FlashMap in the underlying storage.
|
||||
* @param flashMap the FlashMap to save
|
||||
* @param request the current request
|
||||
* @param response the current response
|
||||
*/
|
||||
protected void saveFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) {
|
||||
retrieveFlashMaps(request, true).add(flashMap);
|
||||
}
|
||||
|
||||
private String decodeAndNormalizePath(String path, HttpServletRequest request) {
|
||||
if (path != null) {
|
||||
path = this.urlPathHelper.decodeRequestString(request, path);
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.servlet.mvc;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.servlet.FlashMapManager;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Test fixture with a ParameterizableViewController.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public class ParameterizableViewControllerTests {
|
||||
|
||||
private ParameterizableViewController controller;
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.controller = new ParameterizableViewController();
|
||||
this.request = new MockHttpServletRequest("GET", "/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleRequestWithViewName() throws Exception {
|
||||
String viewName = "testView";
|
||||
this.controller.setViewName(viewName);
|
||||
ModelAndView mav = this.controller.handleRequest(this.request, new MockHttpServletResponse());
|
||||
assertEquals(viewName, mav.getViewName());
|
||||
assertTrue(mav.getModel().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleRequestWithoutViewName() throws Exception {
|
||||
ModelAndView mav = this.controller.handleRequest(this.request, new MockHttpServletResponse());
|
||||
assertNull(mav.getViewName());
|
||||
assertTrue(mav.getModel().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleRequestWithFlashAttributes() throws Exception {
|
||||
this.request.setAttribute(FlashMapManager.INPUT_FLASH_MAP_ATTRIBUTE, new ModelMap("name", "value"));
|
||||
ModelAndView mav = this.controller.handleRequest(this.request, new MockHttpServletResponse());
|
||||
assertEquals(1, mav.getModel().size());
|
||||
assertEquals("value", mav.getModel().get("name"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,8 +20,10 @@ import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.servlet.FlashMapManager;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@@ -150,6 +152,17 @@ public class UrlFilenameViewControllerTests extends TestCase {
|
||||
assertTrue(mv.getModel().isEmpty());
|
||||
}
|
||||
|
||||
public void testWithFlashAttributes() throws Exception {
|
||||
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index");
|
||||
request.setAttribute(FlashMapManager.INPUT_FLASH_MAP_ATTRIBUTE, new ModelMap("name", "value"));
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||
assertEquals("index", mv.getViewName());
|
||||
assertEquals(1, mv.getModel().size());
|
||||
assertEquals("value", mv.getModel().get("name"));
|
||||
}
|
||||
|
||||
private void exposePathInMapping(MockHttpServletRequest request, String mapping) {
|
||||
String pathInMapping = this.pathMatcher.extractPathWithinPattern(mapping, request.getRequestURI());
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathInMapping);
|
||||
|
||||
@@ -218,6 +218,20 @@ public class ProducesRequestConditionTests {
|
||||
assertTrue(condition2.compareTo(condition1, request) > 0);
|
||||
}
|
||||
|
||||
// SPR-9021
|
||||
|
||||
@Test
|
||||
public void compareToMediaTypeAllWithParameter() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "*/*;q=0.9");
|
||||
|
||||
ProducesRequestCondition condition1 = new ProducesRequestCondition();
|
||||
ProducesRequestCondition condition2 = new ProducesRequestCondition("application/json");
|
||||
|
||||
assertTrue(condition1.compareTo(condition2, request) < 0);
|
||||
assertTrue(condition2.compareTo(condition1, request) > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToEqualMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
@@ -37,7 +37,7 @@ import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
/**
|
||||
* Test fixture with {@link ModelAndViewMethodReturnValueHandler}.
|
||||
*
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ModelAndViewMethodReturnValueHandlerTests {
|
||||
@@ -57,7 +57,7 @@ public class ModelAndViewMethodReturnValueHandlerTests {
|
||||
this.webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||
this.returnParamModelAndView = getReturnValueParam("modelAndView");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void supportsReturnType() throws Exception {
|
||||
assertTrue(handler.supportsReturnType(returnParamModelAndView));
|
||||
@@ -68,7 +68,7 @@ public class ModelAndViewMethodReturnValueHandlerTests {
|
||||
public void handleViewReference() throws Exception {
|
||||
ModelAndView mav = new ModelAndView("viewName", "attrName", "attrValue");
|
||||
handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
|
||||
|
||||
|
||||
assertEquals("viewName", mavContainer.getView());
|
||||
assertEquals("attrValue", mavContainer.getModel().get("attrName"));
|
||||
}
|
||||
@@ -77,7 +77,7 @@ public class ModelAndViewMethodReturnValueHandlerTests {
|
||||
public void handleViewInstance() throws Exception {
|
||||
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"));
|
||||
}
|
||||
@@ -85,7 +85,7 @@ public class ModelAndViewMethodReturnValueHandlerTests {
|
||||
@Test
|
||||
public void handleNull() throws Exception {
|
||||
handler.handleReturnValue(null, returnParamModelAndView, mavContainer, webRequest);
|
||||
|
||||
|
||||
assertTrue(mavContainer.isRequestHandled());
|
||||
}
|
||||
|
||||
@@ -93,10 +93,10 @@ public class ModelAndViewMethodReturnValueHandlerTests {
|
||||
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,
|
||||
@@ -107,24 +107,24 @@ public class ModelAndViewMethodReturnValueHandlerTests {
|
||||
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());
|
||||
@@ -136,7 +136,7 @@ public class ModelAndViewMethodReturnValueHandlerTests {
|
||||
Method method = getClass().getDeclaredMethod(methodName);
|
||||
return new MethodParameter(method, -1);
|
||||
}
|
||||
|
||||
|
||||
ModelAndView modelAndView() {
|
||||
return null;
|
||||
}
|
||||
@@ -144,5 +144,5 @@ public class ModelAndViewMethodReturnValueHandlerTests {
|
||||
String viewName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.web.servlet.FlashMap;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
@@ -46,15 +47,18 @@ public class DefaultFlashMapManagerTests {
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.flashMapManager = new DefaultFlashMapManager();
|
||||
this.request = new MockHttpServletRequest();
|
||||
this.response = new MockHttpServletResponse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestStarted() {
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
|
||||
|
||||
assertNotNull("Current FlashMap not found", flashMap);
|
||||
@@ -64,7 +68,7 @@ public class DefaultFlashMapManagerTests {
|
||||
public void requestStartedAlready() {
|
||||
FlashMap flashMap = new FlashMap();
|
||||
this.request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertSame(flashMap, RequestContextUtils.getOutputFlashMap(request));
|
||||
}
|
||||
@@ -79,7 +83,7 @@ public class DefaultFlashMapManagerTests {
|
||||
allMaps.add(flashMap);
|
||||
|
||||
this.request.setRequestURI("/path");
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
||||
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
||||
@@ -98,7 +102,7 @@ public class DefaultFlashMapManagerTests {
|
||||
|
||||
this.request.setAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE, "/accounts");
|
||||
this.request.setRequestURI("/mvc/accounts");
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
||||
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
||||
@@ -114,7 +118,7 @@ public class DefaultFlashMapManagerTests {
|
||||
allMaps.add(flashMap);
|
||||
|
||||
this.request.setRequestURI("/path/");
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
||||
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
||||
@@ -130,21 +134,21 @@ public class DefaultFlashMapManagerTests {
|
||||
allMaps.add(flashMap);
|
||||
|
||||
this.request.setParameter("number", (String) null);
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertNull(RequestContextUtils.getInputFlashMap(this.request));
|
||||
assertEquals("FlashMap should not have been removed", 1, getFlashMaps().size());
|
||||
|
||||
clearFlashMapRequestAttributes();
|
||||
this.request.setParameter("number", "two");
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertNull(RequestContextUtils.getInputFlashMap(this.request));
|
||||
assertEquals("FlashMap should not have been removed", 1, getFlashMaps().size());
|
||||
|
||||
clearFlashMapRequestAttributes();
|
||||
this.request.setParameter("number", "one");
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
||||
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
||||
@@ -163,14 +167,14 @@ public class DefaultFlashMapManagerTests {
|
||||
allMaps.add(flashMap);
|
||||
|
||||
this.request.setParameter("id", "1");
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertNull(RequestContextUtils.getInputFlashMap(this.request));
|
||||
assertEquals("FlashMap should not have been removed", 1, getFlashMaps().size());
|
||||
|
||||
clearFlashMapRequestAttributes();
|
||||
this.request.addParameter("id", "2");
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
||||
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
||||
@@ -196,7 +200,7 @@ public class DefaultFlashMapManagerTests {
|
||||
Collections.shuffle(allMaps);
|
||||
|
||||
this.request.setRequestURI("/one/two");
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertEquals(flashMapTwo, request.getAttribute(INPUT_FLASH_MAP_ATTRIBUTE));
|
||||
}
|
||||
@@ -210,15 +214,15 @@ public class DefaultFlashMapManagerTests {
|
||||
flashMap.startExpirationPeriod(0);
|
||||
}
|
||||
Thread.sleep(100);
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
|
||||
assertEquals(0, allMaps.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveFlashMapWithoutAttributes() throws InterruptedException {
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestCompleted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||
|
||||
assertNull(getFlashMaps());
|
||||
}
|
||||
@@ -227,19 +231,19 @@ public class DefaultFlashMapManagerTests {
|
||||
public void saveFlashMapNotCreatedByThisManager() throws InterruptedException {
|
||||
FlashMap flashMap = new FlashMap();
|
||||
this.request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
|
||||
this.flashMapManager.requestCompleted(this.request);
|
||||
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||
|
||||
assertNull(getFlashMaps());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveFlashMapWithAttributes() throws InterruptedException {
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(this.request);
|
||||
flashMap.put("name", "value");
|
||||
|
||||
this.flashMapManager.setFlashMapTimeout(0);
|
||||
this.flashMapManager.requestCompleted(this.request);
|
||||
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||
|
||||
Thread.sleep(100);
|
||||
|
||||
@@ -252,49 +256,49 @@ public class DefaultFlashMapManagerTests {
|
||||
|
||||
@Test
|
||||
public void decodeTargetPath() throws InterruptedException {
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(this.request);
|
||||
flashMap.put("key", "value");
|
||||
|
||||
flashMap.setTargetRequestPath("/once%20upon%20a%20time");
|
||||
this.flashMapManager.requestCompleted(this.request);
|
||||
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||
|
||||
assertEquals("/once upon a time", flashMap.getTargetRequestPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void normalizeTargetPath() throws InterruptedException {
|
||||
this.flashMapManager.requestStarted(this.request);
|
||||
this.flashMapManager.requestStarted(this.request, this.response);
|
||||
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(this.request);
|
||||
flashMap.put("key", "value");
|
||||
|
||||
flashMap.setTargetRequestPath(".");
|
||||
this.request.setRequestURI("/once/upon/a/time");
|
||||
this.flashMapManager.requestCompleted(this.request);
|
||||
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||
|
||||
assertEquals("/once/upon/a", flashMap.getTargetRequestPath());
|
||||
|
||||
flashMap.setTargetRequestPath("./");
|
||||
this.request.setRequestURI("/once/upon/a/time");
|
||||
this.flashMapManager.requestCompleted(this.request);
|
||||
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||
|
||||
assertEquals("/once/upon/a/", flashMap.getTargetRequestPath());
|
||||
|
||||
flashMap.setTargetRequestPath("..");
|
||||
this.request.setRequestURI("/once/upon/a/time");
|
||||
this.flashMapManager.requestCompleted(this.request);
|
||||
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||
|
||||
assertEquals("/once/upon", flashMap.getTargetRequestPath());
|
||||
|
||||
flashMap.setTargetRequestPath("../");
|
||||
this.request.setRequestURI("/once/upon/a/time");
|
||||
this.flashMapManager.requestCompleted(this.request);
|
||||
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||
|
||||
assertEquals("/once/upon/", flashMap.getTargetRequestPath());
|
||||
|
||||
flashMap.setTargetRequestPath("../../only");
|
||||
this.request.setRequestURI("/once/upon/a/time");
|
||||
this.flashMapManager.requestCompleted(this.request);
|
||||
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||
|
||||
assertEquals("/once/only", flashMap.getTargetRequestPath());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user