SPR-8214 Javadoc and polish

This commit is contained in:
Rossen Stoyanchev
2011-04-13 23:15:19 +00:00
parent 62d40dc7aa
commit aa065e8310
40 changed files with 466 additions and 420 deletions

View File

@@ -24,7 +24,7 @@ import org.springframework.web.servlet.ModelAndView;
/**
* Abstract base class for {@link org.springframework.web.servlet.HandlerExceptionResolver HandlerExceptionResolver}
* implementations that support {@link HandlerMethod HandlerMethod}s.
* implementations that support handling exceptions from {@link HandlerMethod}s rather than handlers.
*
* @author Rossen Stoyanchev
* @since 3.1

View File

@@ -26,10 +26,11 @@ import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.WebContentGenerator;
/**
* Abstract base class for {@link HandlerAdapter} implementations that support {@link HandlerMethod}s.
* Contains template methods for handling these handler method.
* Abstract base class for {@link HandlerAdapter} implementations that support the handling of requests through
* the execution of {@link HandlerMethod}s rather than handlers.
*
* @author Arjen Poutsma
* @since 3.1
*/
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {

View File

@@ -374,7 +374,7 @@ public class RequestMappingHandlerMethodAdapter extends AbstractHandlerMethodAda
resolvers.add(new RequestParamMethodArgumentResolver(beanFactory, false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver(beanFactory));
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(messageConverters));
resolvers.add(new RequestHeaderMethodArgumentResolver(beanFactory));
@@ -404,7 +404,7 @@ public class RequestMappingHandlerMethodAdapter extends AbstractHandlerMethodAda
// Annotation-based resolvers
resolvers.add(new RequestParamMethodArgumentResolver(beanFactory, false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver(beanFactory));
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new ExpressionValueMethodArgumentResolver(beanFactory));
// Type-based resolvers

View File

@@ -25,7 +25,7 @@ import org.springframework.web.method.annotation.InitBinderMethodDataBinderFacto
import org.springframework.web.method.support.InvocableHandlerMethod;
/**
* An {@link InitBinderMethodDataBinderFactory} for Servlet environments.
* An {@link InitBinderMethodDataBinderFactory} that creates a {@link ServletRequestDataBinder}.
*
* @author Rossen Stoyanchev
* @since 3.1

View File

@@ -30,16 +30,19 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandlerCom
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.method.annotation.support.ServletResponseMethodArgumentResolver;
/**
* Extends {@link InvocableHandlerMethod} with the ability to handle the return value through registered
* {@link HandlerMethodArgumentResolver}s.
* Extends {@link InvocableHandlerMethod} with the ability to handle the value returned from the method through
* a registered {@link HandlerMethodArgumentResolver} that supports the given return value type.
* Return value handling may include writing to the response or updating the {@link ModelAndViewContainer} structure.
*
* <p>The {@link ModelAndViewContainer} for the request contains the results from the handling of the return value.
* It can be used to access model attributes and view selection and to check if view resolution is needed.
* <p>If the underlying method has a {@link ResponseStatus} instruction, the status on the response is set
* accordingly after the method is invoked but before the return value is handled.
*
* @author Rossen Stoyanchev
* @since 3.1
* @see #invokeAndHandle(NativeWebRequest, ModelAndViewContainer, Object...)
*/
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
@@ -65,25 +68,23 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
if (annotation != null) {
this.responseStatus = annotation.value();
this.responseReason = annotation.reason();
}
}
/**
* Invokes the method and handles the return value through registered {@link HandlerMethodReturnValueHandler}s.
* If the handler method is annotated with {@link ResponseStatus}, the status on the response is set accordingly
* after method invocation but before return value handling.
* <p>Return value handling may be skipped entirely if the handler method returns a {@code null} (or is a
* {@code void} method) and one of the following other conditions is true:
* Invokes the method and handles the return value through a registered {@link HandlerMethodReturnValueHandler}.
* <p>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:
* <ul>
* <li>One of the {@link HandlerMethodArgumentResolver}s set the {@link ModelAndViewContainer#setResolveView(boolean)}
* flag to {@code false}. This is the case when a method argument allows the handler method access to the response.
* <li>The request qualifies as being not modified according to {@link ServletWebRequest#isNotModified()}.
* This is used in conjunction with a "Last-Modified" header or ETag.
* <li>The status on the response was set as a result of a {@link ResponseStatus} annotation
* <li>A {@link HandlerMethodArgumentResolver} has set the {@link ModelAndViewContainer#setResolveView(boolean)}
* flag to {@code false} -- e.g. method arguments providing access to the response.
* <li>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
* headers will be automatically generated without the need for return value handling.
* <li>The status on the response is set due to a @{@link ResponseStatus} instruction.
* </ul>
* <p>After the call, use the {@link ModelAndViewContainer} parameter to access model attributes and view selection
* and to determine if view resolution is needed.
* <p>After the return value is handled, callers of this method can use the {@link ModelAndViewContainer}
* to gain access to model attributes, view selection choices, and to check if view resolution is even needed.
*
* @param request the current request
* @param mavContainer the {@link ModelAndViewContainer} for the current request
@@ -131,17 +132,18 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
}
/**
* Does the request qualify as not modified?
* Does the given request qualify as "not modified"?
* @see ServletWebRequest#checkNotModified(long)
* @see ServletWebRequest#checkNotModified(String)
*/
private boolean isRequestNotModified(NativeWebRequest request) {
return ((ServletWebRequest) request).isNotModified();
}
/**
* Does the method set the response status?
* Does this method have the response status instruction?
*/
private boolean hasResponseStatus() {
return responseStatus != null;
}
}

View File

@@ -37,6 +37,10 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
/**
* A base class for resolving method argument values by reading from the body of a request with
* {@link HttpMessageConverter}s and for handling method return values by writing to the response with
* {@link HttpMessageConverter}s.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.1
@@ -143,4 +147,4 @@ public abstract class AbstractMessageConverterMethodProcessor
return acceptedMediaTypes;
}
}
}

View File

@@ -31,12 +31,21 @@ import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
/**
* A catch-all {@link HandlerMethodReturnValueHandler} to handle return values not handled by any other return
* value handler.
*
* <p>This handler should always be last in the order as {@link #supportsReturnType(MethodParameter)} always returns
* {@code true}. An attempt is made to handle the return value through a custom {@link ModelAndViewResolver}s or
* otherwise by treating it as a single model attribute.
* Attempts to handle return value types not recognized by any other {@link HandlerMethodReturnValueHandler}.
* Intended to be used as the last of a list of registered handlers as {@link #supportsReturnType(MethodParameter)}
* always returns {@code true}.
* <p>Handling takes place in the following order:
* <ul>
* <li>Iterate over the list of {@link ModelAndViewResolver}s provided to the constructor of this class looking
* for a return value that isn't {@link ModelAndViewResolver#UNRESOLVED}.
* <li>If the return value is not a simple type it is treated as a single model attribute to be added to the model
* with a name derived from its type.
* </ul>
* <p>Note that {@link ModelAndViewResolver} is supported for backwards compatibility. Since the only way to check
* if it supports a return value type is to try to resolve the return value, a {@link ModelAndViewResolver} can
* only be invoked from here after no other {@link HandlerMethodReturnValueHandler} has recognized the return
* value. To avoid this limitation change the {@link ModelAndViewResolver} to implement
* {@link HandlerMethodReturnValueHandler} instead.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -65,10 +74,6 @@ public class DefaultMethodReturnValueHandler implements HandlerMethodReturnValue
return true;
}
public boolean usesResponseArgument(MethodParameter parameter) {
return false;
}
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,

View File

@@ -40,13 +40,11 @@ import org.springframework.util.Assert;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
* Implementation of {@link HandlerMethodArgumentResolver} and {@link HandlerMethodReturnValueHandler}
* that supports {@link HttpEntity} and {@link ResponseEntity}.
* Resolves {@link HttpEntity} method argument values.
* Handles {@link HttpEntity} and {@link ResponseEntity} return values.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
@@ -68,27 +66,16 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
return HttpEntity.class.equals(parameterType) || ResponseEntity.class.equals(parameterType);
}
public boolean usesResponseArgument(MethodParameter parameterOrReturnType) {
// only when HttpEntity or ResponseEntity is used as a return type
return parameterOrReturnType.getParameterIndex() == -1;
}
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory)
throws IOException, HttpMediaTypeNotSupportedException {
HttpInputMessage inputMessage = createInputMessage(webRequest);
Class<?> paramType = getHttpEntityType(parameter);
Object body = readWithMessageConverters(webRequest, parameter, paramType);
HttpInputMessage inputMessage = createInputMessage(webRequest);
return new HttpEntity<Object>(body, inputMessage.getHeaders());
}
@Override
protected HttpInputMessage createInputMessage(NativeWebRequest webRequest) {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
return new ServletServerHttpRequest(servletRequest);
}
private Class<?> getHttpEntityType(MethodParameter methodParam) {
Assert.isAssignable(HttpEntity.class, methodParam.getParameterType());
@@ -109,7 +96,12 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
}
throw new IllegalArgumentException(
"HttpEntity parameter (" + methodParam.getParameterName() + ") is not parameterized");
}
@Override
protected HttpInputMessage createInputMessage(NativeWebRequest webRequest) {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
return new ServletServerHttpRequest(servletRequest);
}
public void handleReturnValue(Object returnValue,
@@ -150,4 +142,5 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
HttpServletResponse servletResponse = (HttpServletResponse) webRequest.getNativeResponse();
return new ServletServerHttpResponse(servletResponse);
}
}
}

View File

@@ -23,7 +23,9 @@ import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
/**
* Handles {@link ModelAndView} return values.
* 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
* {@code false} to indicate view resolution is not needed.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -34,10 +36,6 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
}
public boolean usesResponseArgument(MethodParameter parameter) {
return false;
}
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
@@ -53,4 +51,4 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
}
}
}
}

View File

@@ -20,28 +20,33 @@ import java.util.Map;
import javax.servlet.ServletException;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.annotation.support.AbstractNamedValueMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.HandlerMapping;
/**
* Implementation of {@link HandlerMethodArgumentResolver} that supports arguments annotated with
* {@link PathVariable @PathVariable}.
* Resolves method arguments annotated with an @{@link PathVariable}.
*
* <p>An @{@link PathVariable} is a named value that gets resolved from a URI template variable. It is always
* required and does not have a default value to fall back on. See the base class
* {@link AbstractNamedValueMethodArgumentResolver} for more information on how named values are processed.
*
* <p>A {@link WebDataBinder} is invoked to apply type conversion to resolved path variable values that
* don't yet match the method parameter type.
*
* @author Rossen Stoyanchev
* @author Arjen Poutsma
* @since 3.1
*/
public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
public PathVariableMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
super(beanFactory);
public PathVariableMethodArgumentResolver() {
super(null);
}
public boolean supportsParameter(MethodParameter parameter) {
@@ -56,16 +61,16 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
@Override
@SuppressWarnings("unchecked")
protected Object resolveNamedValueArgument(NativeWebRequest webRequest, MethodParameter parameter, String name)
throws Exception {
Map<String, String> uriTemplateVariables = (Map<String, String>) webRequest.getAttribute(
HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
return (uriTemplateVariables != null) ? uriTemplateVariables.get(name) : null;
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
String key = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
int scope = RequestAttributes.SCOPE_REQUEST;
Map<String, String> uriTemplateVars = (Map<String, String>) request.getAttribute(key, scope);
return (uriTemplateVars != null) ? uriTemplateVars.get(name) : null;
}
@Override
protected void handleMissingValue(String name, MethodParameter parameter) throws ServletException {
throw new IllegalStateException("Could not find @PathVariable [" + name + "] in @RequestMapping");
throw new IllegalStateException("Could not find the URL template variable [" + name + "]");
}
private static class PathVariableNamedValueInfo extends NamedValueInfo {
@@ -74,6 +79,4 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
super(annotation.value(), true, ValueConstants.DEFAULT_NONE);
}
}
}
}

View File

@@ -34,13 +34,11 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
* Implementation of {@link HandlerMethodArgumentResolver} and {@link HandlerMethodReturnValueHandler} that supports
* parameters annotated with {@link RequestBody} and return values annotated with {@link ResponseBody}.
* Resolves method arguments annotated with @{@link RequestBody}.
* Handles return values from methods annotated with @{@link ResponseBody}.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
@@ -60,11 +58,6 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
return returnType.getMethodAnnotation(ResponseBody.class) != null;
}
public boolean usesResponseArgument(MethodParameter parameterOrReturnType) {
return parameterOrReturnType.getParameterIndex() == -1 &&
parameterOrReturnType.getMethodAnnotation(ResponseBody.class) != null;
}
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,

View File

@@ -22,35 +22,41 @@ import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.support.CookieValueMethodArgumentResolver;
import org.springframework.web.method.annotation.support.AbstractCookieValueMethodArgumentResolver;
import org.springframework.web.util.UrlPathHelper;
import org.springframework.web.util.WebUtils;
/**
* A {@link CookieValueMethodArgumentResolver} for Servlet environments.
* A {@link AbstractCookieValueMethodArgumentResolver} that resolves the cookie value through the {@link HttpServletRequest}.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
public class ServletCookieValueMethodArgumentResolver extends CookieValueMethodArgumentResolver {
public class ServletCookieValueMethodArgumentResolver extends AbstractCookieValueMethodArgumentResolver {
private UrlPathHelper urlPathHelper = new UrlPathHelper();
public ServletCookieValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
super(beanFactory);
}
public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
this.urlPathHelper = urlPathHelper;
}
@Override
protected Object resolveNamedValueArgument(NativeWebRequest webRequest,
MethodParameter parameter,
String cookieName) throws Exception {
protected Object resolveName(String cookieName, MethodParameter parameter, NativeWebRequest webRequest)
throws Exception {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
Cookie cookieValue = WebUtils.getCookie(servletRequest, cookieName);
if (Cookie.class.isAssignableFrom(parameter.getParameterType())) {
return cookieValue;
}
else if (cookieValue != null) {
return getUrlPathHelper().decodeRequestString(servletRequest, cookieValue.getValue());
return this.urlPathHelper.decodeRequestString(servletRequest, cookieValue.getValue());
}
else {
return null;
}
}
}
}

View File

@@ -21,11 +21,13 @@ import javax.servlet.ServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.support.ModelAttributeMethodProcessor;
/**
* A {@link ModelAttributeMethodProcessor} for Servlet environments.
* A Servlet-specific {@link ModelAttributeMethodProcessor} variant that casts the {@link WebDataBinder}
* instance to {@link ServletRequestDataBinder} prior to invoking data binding.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -33,13 +35,12 @@ import org.springframework.web.method.annotation.support.ModelAttributeMethodPro
public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodProcessor {
/**
* Creates a {@link ServletModelAttributeMethodProcessor} instance.
* @param resolveWithoutAnnotations enable default resolution mode in which parameters without
* annotations that aren't simple types (see {@link BeanUtils#isSimpleProperty(Class)})
* are also treated as model attributes with a default name based on the model attribute type.
* @param useDefaultResolution in default resolution mode a method argument that isn't a simple type, as
* defined in {@link BeanUtils#isSimpleProperty(Class)}, is treated as a model attribute even if it doesn't
* have an @{@link ModelAttribute} annotation with its name derived from the model attribute type.
*/
public ServletModelAttributeMethodProcessor(boolean resolveWithoutAnnotations) {
super(resolveWithoutAnnotations);
public ServletModelAttributeMethodProcessor(boolean useDefaultResolution) {
super(useDefaultResolution);
}
/**

View File

@@ -36,61 +36,74 @@ import org.springframework.web.multipart.MultipartRequest;
import org.springframework.web.servlet.support.RequestContextUtils;
/**
* Implementation of {@link HandlerMethodArgumentResolver} that supports {@link ServletRequest} and related arguments.
* Resolves request-related method argument values of the following types:
* <ul>
* <li>{@link WebRequest}
* <li>{@link ServletRequest}
* <li>{@link MultipartRequest}
* <li>{@link HttpSession}
* <li>{@link Principal}
* <li>{@link Locale}
* <li>{@link InputStream}
* <li>{@link Reader}
* </ul>
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.1
*/
public class ServletRequestMethodArgumentResolver implements HandlerMethodArgumentResolver {
public boolean supportsParameter(MethodParameter parameter) {
Class<?> parameterType = parameter.getParameterType();
return WebRequest.class.isAssignableFrom(parameterType) ||
ServletRequest.class.isAssignableFrom(parameterType) ||
MultipartRequest.class.isAssignableFrom(parameterType) ||
HttpSession.class.isAssignableFrom(parameterType) || Principal.class.isAssignableFrom(parameterType) ||
Locale.class.equals(parameterType) || InputStream.class.isAssignableFrom(parameterType) ||
Reader.class.isAssignableFrom(parameterType);
}
public boolean usesResponseArgument(MethodParameter parameter) {
return false;
Class<?> paramType = parameter.getParameterType();
return WebRequest.class.isAssignableFrom(paramType) ||
ServletRequest.class.isAssignableFrom(paramType) ||
MultipartRequest.class.isAssignableFrom(paramType) ||
HttpSession.class.isAssignableFrom(paramType) ||
Principal.class.isAssignableFrom(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 {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
Class<?> parameterType = parameter.getParameterType();
if (WebRequest.class.isAssignableFrom(parameterType)) {
Class<?> paramType = parameter.getParameterType();
if (WebRequest.class.isAssignableFrom(paramType)) {
return webRequest;
}
if (ServletRequest.class.isAssignableFrom(parameterType) ||
MultipartRequest.class.isAssignableFrom(parameterType)) {
Object nativeRequest = webRequest.getNativeRequest(parameterType);
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
if (ServletRequest.class.isAssignableFrom(paramType) || MultipartRequest.class.isAssignableFrom(paramType)) {
Object nativeRequest = webRequest.getNativeRequest(paramType);
if (nativeRequest == null) {
throw new IllegalStateException(
"Current request is not of type [" + parameterType.getName() + "]: " + request);
"Current request is not of type [" + paramType.getName() + "]: " + request);
}
return nativeRequest;
}
else if (HttpSession.class.isAssignableFrom(parameterType)) {
else if (HttpSession.class.isAssignableFrom(paramType)) {
return request.getSession();
}
else if (Principal.class.isAssignableFrom(parameterType)) {
else if (Principal.class.isAssignableFrom(paramType)) {
return request.getUserPrincipal();
}
else if (Locale.class.equals(parameterType)) {
else if (Locale.class.equals(paramType)) {
return RequestContextUtils.getLocale(request);
}
else if (InputStream.class.isAssignableFrom(parameterType)) {
else if (InputStream.class.isAssignableFrom(paramType)) {
return request.getInputStream();
}
else if (Reader.class.isAssignableFrom(parameterType)) {
else if (Reader.class.isAssignableFrom(paramType)) {
return request.getReader();
}
// should not happen
throw new UnsupportedOperationException();
else {
// should not happen
throw new UnsupportedOperationException();
}
}
}
}

View File

@@ -28,33 +28,46 @@ import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod;
/**
* Implementation of {@link HandlerMethodArgumentResolver} that supports {@link ServletResponse} and related arguments.
* Resolves response-related method argument values of types:
* <ul>
* <li>{@link ServletResponse}
* <li>{@link OutputStream}
* <li>{@link Writer}
* </ul>
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.1
*/
public class ServletResponseMethodArgumentResolver implements HandlerMethodArgumentResolver {
public boolean supportsParameter(MethodParameter parameter) {
Class<?> parameterType = parameter.getParameterType();
return ServletResponse.class.isAssignableFrom(parameterType) ||
OutputStream.class.isAssignableFrom(parameterType) || Writer.class.isAssignableFrom(parameterType);
}
public boolean usesResponseArgument(MethodParameter parameter) {
return true;
Class<?> paramType = parameter.getParameterType();
return ServletResponse.class.isAssignableFrom(paramType)
|| OutputStream.class.isAssignableFrom(paramType)
|| Writer.class.isAssignableFrom(paramType);
}
/**
* {@inheritDoc}
* <p>Sets the {@link ModelAndViewContainer#setResolveView(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...)
*/
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws IOException {
mavContainer.setResolveView(false);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
Class<?> parameterType = parameter.getParameterType();
mavContainer.setResolveView(false);
if (ServletResponse.class.isAssignableFrom(parameterType)) {
Object nativeResponse = webRequest.getNativeResponse(parameterType);
if (nativeResponse == null) {
@@ -74,4 +87,5 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
throw new UnsupportedOperationException();
}
}
}

View File

@@ -22,15 +22,16 @@ import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.annotation.support.WebArgumentResolverAdapter;
import org.springframework.web.method.annotation.support.AbstractWebArgumentResolverAdapter;
/**
* A Servlet-specific {@link WebArgumentResolverAdapter} that provides access to a {@link NativeWebRequest}.
* A Servlet-specific {@link AbstractWebArgumentResolverAdapter} that creates a {@link NativeWebRequest}
* from {@link ServletRequestAttributes}.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
public class ServletWebArgumentResolverAdapter extends WebArgumentResolverAdapter {
public class ServletWebArgumentResolverAdapter extends AbstractWebArgumentResolverAdapter {
public ServletWebArgumentResolverAdapter(WebArgumentResolver adaptee) {
super(adaptee);
@@ -45,5 +46,4 @@ public class ServletWebArgumentResolverAdapter extends WebArgumentResolverAdapte
}
return null;
}
}
}

View File

@@ -18,12 +18,16 @@ package org.springframework.web.servlet.mvc.method.annotation.support;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.support.ModelAttributeMethodProcessor;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.View;
/**
* Handles {@link View} and view name return values.
* Handles return values that are of type {@link View} or {@link String} (i.e. a logical view name).
* <p>Since {@link String} return value can be interpeted in multiple ways, this resolver should be ordered
* after return value handlers that recognize annotated return values such as the
* {@link ModelAttributeMethodProcessor} and the {@link RequestResponseBodyMethodProcessor}.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -35,10 +39,6 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan
return (View.class.isAssignableFrom(paramType) || (String.class.equals(paramType)));
}
public boolean usesResponseArgument(MethodParameter parameter) {
return false;
}
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,