ModelAndViewContainer related refinements

This commit is contained in:
Rossen Stoyanchev
2011-04-07 18:09:28 +00:00
parent 3d8b476f58
commit 6fe0ff9e7b
47 changed files with 547 additions and 1073 deletions

View File

@@ -41,7 +41,6 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter;
import org.springframework.ui.ModelMap;
import org.springframework.util.ReflectionUtils.MethodFilter;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -67,13 +66,14 @@ import org.springframework.web.method.annotation.support.RequestHeaderMapMethodA
import org.springframework.web.method.annotation.support.RequestHeaderMethodArgumentResolver;
import org.springframework.web.method.annotation.support.RequestParamMapMethodArgumentResolver;
import org.springframework.web.method.annotation.support.RequestParamMethodArgumentResolver;
import org.springframework.web.method.annotation.support.WebArgumentResolverAdapter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
import org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter;
import org.springframework.web.servlet.mvc.method.annotation.support.DefaultMethodReturnValueHandler;
@@ -459,13 +459,25 @@ public class RequestMappingHandlerMethodAdapter extends AbstractHandlerMethodAda
ServletWebRequest webRequest = new ServletWebRequest(request, response);
SessionStatus sessionStatus = new SimpleSessionStatus();
ModelMap implicitModel = modelFactory.createModel(webRequest, requestMethod);
ModelAndView mav = requestMethod.invokeAndHandle(webRequest, implicitModel, sessionStatus);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
modelFactory.initModel(webRequest, mavContainer, requestMethod);
requestMethod.invokeAndHandle(webRequest, mavContainer, sessionStatus);
ModelMap actualModel = (mav != null) ? mav.getModelMap() : null;
modelFactory.updateAttributes(webRequest, sessionStatus, actualModel, implicitModel);
return mav;
modelFactory.updateModel(webRequest, mavContainer, sessionStatus);
if (!mavContainer.isResolveView()) {
return null;
}
else {
ModelAndView mav = new ModelAndView().addAllObjects(mavContainer.getModel());
mav.setViewName(mavContainer.getViewName());
if (mavContainer.getView() != null) {
mav.setView((View) mavContainer.getView());
}
return mav;
}
}
private WebDataBinderFactory createDataBinderFactory(HandlerMethod handlerMethod) {

View File

@@ -32,8 +32,6 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.ModelMap;
import org.springframework.util.ReflectionUtils.MethodFilter;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.support.WebArgumentResolver;
@@ -47,9 +45,10 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver;
import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
import org.springframework.web.servlet.mvc.method.annotation.support.DefaultMethodReturnValueHandler;
import org.springframework.web.servlet.mvc.method.annotation.support.HttpEntityMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.support.ModelAndViewMethodReturnValueHandler;
@@ -60,17 +59,15 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebA
import org.springframework.web.servlet.mvc.method.annotation.support.ViewMethodReturnValueHandler;
/**
* An extension of {@link AbstractHandlerMethodExceptionResolver} that matches thrown exceptions to
* {@link ExceptionHandler @ExceptionHandler} methods in the handler. If a match is found the
* exception-handling method is invoked to process the request.
* A {@link AbstractHandlerMethodExceptionResolver} that matches thrown exceptions to {@link ExceptionHandler}-annotated
* methods. If a match is found the exception-handling method is invoked to process the request.
*
* <p>See {@link ExceptionHandler} for information on supported method arguments and return values
* for exception-handling methods. You can customize method argument resolution and return value
* processing through the various bean properties in this class.
* <p>See {@link ExceptionHandler} for information on supported method arguments and return values for exception-handling
* methods. You can customize method argument resolution and return value processing through the various bean properties
* in this class.
*
* @author Rossen Stoyanchev
* @since 3.1
* @see #setMessageConverters(HttpMessageConverter[])
*/
public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandlerMethodExceptionResolver implements
InitializingBean {
@@ -79,8 +76,6 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle
private HttpMessageConverter<?>[] messageConverters;
private ModelAndViewResolver[] customModelAndViewResolvers;
private final Map<Class<?>, ExceptionMethodMapping> exceptionMethodMappingCache =
new ConcurrentHashMap<Class<?>, ExceptionMethodMapping>();
@@ -102,9 +97,11 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle
}
/**
* Set a custom ArgumentResolvers to use for special method parameter types.
* Set a custom ArgumentResolver to use for special method parameter types.
* <p>Such a custom ArgumentResolver will kick in first, having a chance to resolve
* an argument value before the standard argument handling kicks in.
* <p>Note: this is provided for backward compatibility. The preferred way to do this is to
* implement a {@link HandlerMethodArgumentResolver}.
*/
public void setCustomArgumentResolver(WebArgumentResolver argumentResolver) {
this.customArgumentResolvers = new WebArgumentResolver[]{argumentResolver};
@@ -114,6 +111,8 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle
* Set one or more custom ArgumentResolvers to use for special method parameter types.
* <p>Any such custom ArgumentResolver will kick in first, having a chance to resolve
* an argument value before the standard argument handling kicks in.
* <p>Note: this is provided for backward compatibility. The preferred way to do this is to
* implement a {@link HandlerMethodArgumentResolver}.
*/
public void setCustomArgumentResolvers(WebArgumentResolver[] argumentResolvers) {
this.customArgumentResolvers = argumentResolvers;
@@ -127,24 +126,6 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle
this.messageConverters = messageConverters;
}
/**
* Set a custom ModelAndViewResolvers to use for special method return types.
* <p>Such a custom ModelAndViewResolver will kick in first, having a chance to resolve
* a return value before the standard ModelAndView handling kicks in.
*/
public void setCustomModelAndViewResolver(ModelAndViewResolver customModelAndViewResolver) {
this.customModelAndViewResolvers = new ModelAndViewResolver[] {customModelAndViewResolver};
}
/**
* Set one or more custom ModelAndViewResolvers to use for special method return types.
* <p>Any such custom ModelAndViewResolver will kick in first, having a chance to resolve
* a return value before the standard ModelAndView handling kicks in.
*/
public void setCustomModelAndViewResolvers(ModelAndViewResolver[] customModelAndViewResolvers) {
this.customModelAndViewResolvers = customModelAndViewResolvers;
}
/**
* Set the {@link HandlerMethodArgumentResolver}s to use to resolve argument values for
* {@link ExceptionHandler} methods. This is an optional property.
@@ -207,9 +188,14 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle
returnValueHandlers.registerReturnValueHandler(new HttpEntityMethodProcessor(messageConverters));
// Default handler
returnValueHandlers.registerReturnValueHandler(new DefaultMethodReturnValueHandler(customModelAndViewResolvers));
returnValueHandlers.registerReturnValueHandler(new DefaultMethodReturnValueHandler(null));
}
/**
* Attempts to find an {@link ExceptionHandler}-annotated method that can handle the thrown exception.
* The exception-handling method, if found, is invoked resulting in a {@link ModelAndView}.
* @return a {@link ModelAndView} if a matching exception-handling method was found, or {@code null} otherwise
*/
@Override
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
HttpServletResponse response,
@@ -226,13 +212,25 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle
exceptionHandler.setHandlerMethodReturnValueHandlers(returnValueHandlers);
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ModelMap model = new ExtendedModelMap();
try {
if (logger.isDebugEnabled()) {
logger.debug("Invoking exception-handling method: " + exceptionHandler);
}
ModelAndView mav = exceptionHandler.invokeAndHandle(webRequest , model , ex);
return (mav != null) ? mav : new ModelAndView();
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
exceptionHandler.invokeAndHandle(webRequest, mavContainer, ex);
if (!mavContainer.isResolveView()) {
return new ModelAndView();
}
else {
ModelAndView mav = new ModelAndView().addAllObjects(mavContainer.getModel());
mav.setViewName(mavContainer.getViewName());
if (mavContainer.getView() != null) {
mav.setView((View) mavContainer.getView());
}
return mav;
}
}
catch (Exception invocationEx) {
logger.error("Invoking exception-handling method resulted in exception : " +
@@ -244,6 +242,9 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle
return null;
}
/**
* @return an {@link ExceptionMethodMapping} for the the given handler method, never {@code null}
*/
private ExceptionMethodMapping getExceptionMethodMapping(HandlerMethod handlerMethod) {
Class<?> handlerType = handlerMethod.getBeanType();
ExceptionMethodMapping mapping = exceptionMethodMappingCache.get(handlerType);
@@ -256,7 +257,7 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle
}
/**
* Pre-built MethodFilter that matches {@link ExceptionHandler @ExceptionHandler} methods.
* MethodFilter that matches {@link ExceptionHandler @ExceptionHandler} methods.
*/
public static MethodFilter EXCEPTION_HANDLER_METHODS = new MethodFilter() {

View File

@@ -43,7 +43,7 @@ public class ServletInitBinderMethodDataBinderFactory extends InitBinderMethodDa
}
/**
* {@inheritDoc} creates a Servlet data binder.
* Creates a Servlet data binder.
*/
@Override
protected WebDataBinder createBinderInstance(Object target, String objectName) {

View File

@@ -20,23 +20,31 @@ import java.io.IOException;
import java.lang.reflect.Method;
import org.springframework.http.HttpStatus;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
/**
* Extends {@link InvocableHandlerMethod} with the ability to handle the return value of the invocation
* resulting in a {@link ModelAndView} according to the {@link HandlerAdapter} contract.
* Extends {@link InvocableHandlerMethod} with the ability to handle the return value through registered
* {@link HandlerMethodArgumentResolver}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:
* <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
* </ul>
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -70,36 +78,47 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
}
/**
* Invokes the method via {@link #invokeForRequest(NativeWebRequest, ModelMap, Object...)} and also handles the
* return value by invoking one of the {@link HandlerMethodReturnValueHandler} instances registered via
* {@link #setHandlerMethodReturnValueHandlers(HandlerMethodReturnValueHandlerComposite)}.
* If the method is annotated with {@link SessionStatus} the response status will be set.
* 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:
* <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
* </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.
*
* @param request the current request
* @param model the model used throughout the current request
* @param providedArgs argument values to use as-is if they match to a method parameter's type
* @return ModelAndView object with the name of the view and the required model data, or <code>null</code>
* if the response was handled
* @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 ModelAndView invokeAndHandle(NativeWebRequest request,
ModelMap model,
Object... providedArgs) throws Exception {
public final void invokeAndHandle(NativeWebRequest request,
ModelAndViewContainer mavContainer,
Object...providedArgs) throws Exception {
if (!returnValueHandlers.supportsReturnType(getReturnType())) {
throw new IllegalStateException("No suitable HandlerMethodReturnValueHandler for method " + toString());
}
Object returnValue = invokeForRequest(request, model, providedArgs);
Object returnValue = invokeForRequest(request, mavContainer, providedArgs);
setResponseStatus((ServletWebRequest) request);
if (returnValue == null && (isRequestNotModified(request) || usesResponseArgument())) {
return null;
if (returnValue == null) {
if (isRequestNotModified(request) || hasResponseStatus() || !mavContainer.isResolveView()) {
mavContainer.setResolveView(false);
return;
}
}
ModelAndViewContainer mavContainer = new ModelAndViewContainer(model);
returnValueHandlers.handleReturnValue(returnValue, getReturnType(), mavContainer, request);
mavContainer.setResolveView(true);
return getModelAndView(request, mavContainer, returnValue);
returnValueHandlers.handleReturnValue(returnValue, getReturnType(), mavContainer, request);
}
/**
@@ -120,38 +139,17 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
}
/**
* Create a {@link ModelAndView} from a {@link ModelAndViewContainer}.
* Does the request qualify as not modified?
*/
private ModelAndView getModelAndView(NativeWebRequest request,
ModelAndViewContainer mavContainer,
Object returnValue) {
if (returnValueHandlerUsesResponseArgument()) {
return null;
}
else {
ModelAndView mav = new ModelAndView().addAllObjects(mavContainer.getModel());
mav.setViewName(mavContainer.getViewName());
if (mavContainer.getView() != null) {
mav.setView((View) mavContainer.getView());
}
return mav;
}
private boolean isRequestNotModified(NativeWebRequest request) {
return ((ServletWebRequest) request).isNotModified();
}
/**
* Check whether the request qualifies as not modified...
* TODO: document fully including sample user code
* Does the method set the response status?
*/
private boolean isRequestNotModified(NativeWebRequest request) {
ServletWebRequest servletRequest = (ServletWebRequest) request;
return (servletRequest.isNotModified() || (responseStatus != null) || usesResponseArgument());
}
protected boolean usesResponseArgument() {
return (super.usesResponseArgument() || returnValueHandlerUsesResponseArgument() || (responseStatus != null));
private boolean hasResponseStatus() {
return responseStatus != null;
}
private boolean returnValueHandlerUsesResponseArgument() {
return returnValueHandlers.usesResponseArgument(getReturnType());
}
}
}

View File

@@ -68,7 +68,7 @@ public class DefaultMethodReturnValueHandler implements HandlerMethodReturnValue
if (mav != ModelAndViewResolver.UNRESOLVED) {
mavContainer.setView(mav.getView());
mavContainer.setViewName(mav.getViewName());
mavContainer.addModelAttributes(mav.getModel());
mavContainer.addAllAttributes(mav.getModel());
return;
}
}
@@ -78,7 +78,7 @@ public class DefaultMethodReturnValueHandler implements HandlerMethodReturnValue
}
else if (!BeanUtils.isSimpleProperty(returnValue.getClass())) {
String name = ModelFactory.getNameForReturnValue(returnValue, returnType);
mavContainer.addModelAttribute(name, returnValue);
mavContainer.addAttribute(name, returnValue);
}
// should not happen

View File

@@ -35,7 +35,6 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.support.WebDataBinderFactory;
@@ -74,7 +73,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
}
public Object resolveArgument(MethodParameter parameter,
ModelMap model,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory)
throws IOException, HttpMediaTypeNotSupportedException {
@@ -116,19 +115,25 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
MethodParameter returnType,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
mavContainer.setResolveView(false);
if (returnValue == null) {
return;
}
HttpOutputMessage outputMessage = createOutputMessage(webRequest);
Assert.isInstanceOf(HttpEntity.class, returnValue);
HttpEntity<?> responseEntity = (HttpEntity<?>) returnValue;
HttpOutputMessage outputMessage = createOutputMessage(webRequest);
if (responseEntity instanceof ResponseEntity) {
((ServerHttpResponse) outputMessage).setStatusCode(((ResponseEntity<?>) responseEntity).getStatusCode());
}
HttpHeaders entityHeaders = responseEntity.getHeaders();
if (!entityHeaders.isEmpty()) {
outputMessage.getHeaders().putAll(entityHeaders);
}
Object body = responseEntity.getBody();
if (body != null) {
writeWithMessageConverters(body, createInputMessage(webRequest), outputMessage);

View File

@@ -46,10 +46,10 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
ModelAndView mav = (ModelAndView) returnValue;
mavContainer.setView(mav.getView());
mavContainer.setViewName(mav.getViewName());
mavContainer.addModelAttributes(mav.getModel());
mavContainer.addAllAttributes(mav.getModel());
}
else {
// TODO
mavContainer.setResolveView(false);
}
}

View File

@@ -27,7 +27,6 @@ import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.ui.ModelMap;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.annotation.RequestBody;
@@ -66,7 +65,7 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
}
public Object resolveArgument(MethodParameter parameter,
ModelMap model,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory)
throws IOException, HttpMediaTypeNotSupportedException {
@@ -82,8 +81,8 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException {
NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException {
mavContainer.setResolveView(false);
if (returnValue != null) {
writeWithMessageConverters(webRequest, returnValue);
}

View File

@@ -27,10 +27,10 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.core.MethodParameter;
import org.springframework.ui.ModelMap;
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.multipart.MultipartRequest;
import org.springframework.web.servlet.support.RequestContextUtils;
@@ -55,7 +55,7 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
}
public Object resolveArgument(MethodParameter parameter,
ModelMap model,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws IOException {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);

View File

@@ -24,10 +24,10 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.MethodParameter;
import org.springframework.ui.ModelMap;
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;
/**
* Implementation of {@link HandlerMethodArgumentResolver} that supports {@link ServletResponse} and related arguments.
@@ -47,12 +47,14 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
}
public Object resolveArgument(MethodParameter parameter,
ModelMap model,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws IOException {
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) {
@@ -67,7 +69,9 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
else if (Writer.class.isAssignableFrom(parameterType)) {
return response.getWriter();
}
// should not happen
throw new UnsupportedOperationException();
else {
// should not happen
throw new UnsupportedOperationException();
}
}
}