Spring MVC 处理响应返回值

HandlerMethodReturnValueHandlerRequestMappingHandlerAdapter用来处理当含有@RequestMapping的方法调度完成后,后面要进行的事情。
首先是HandlerMethodReturnValueHandler的自定义注册:

1
2
3
4
5
<mvc:annotation-driven>
<mvc:return-value-handlers>
<bean class="org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler"></bean>
</mvc:return-value-handlers>
</mvc:annotation-driven>

在启动AnnotationDrivenBeanDefinitionParser来解析mvc:annotation-driven标签的过程中,会注册我们所配置的HandlerMethodReturnValueHandler,如下:

1
ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, parserContext);
1
2
3
4
5
6
7
private ManagedList<?> getReturnValueHandlers(Element element, ParserContext parserContext) {
Element handlersElement = DomUtils.getChildElementByTagName(element, "return-value-handlers");
if (handlersElement != null) {
return extractBeanSubElements(handlersElement, parserContext);
}
return null;
}

然后将会这些自定义的HandlerMethodReturnValueHandler设置到RequestMappingHandlerAdaptercustomReturnValueHandlers属性中

RequestMappingHandlerAdapter的两个重要属性:

  • customReturnValueHandlers:存放我们自定义的HandlerMethodReturnValueHandler
  • returnValueHandlers:存放最终所有的HandlerMethodReturnValueHandler
1
2
3
4
5
6
7
8
9
10
11
12
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
private HandlerMethodArgumentResolverComposite argumentResolvers;
private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;
//...
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
//...
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;

returnValueHandlers的属性类型为HandlerMethodReturnValueHandlerComposite,里面也有一个list集合,来存放所有的HandlerMethodReturnValueHandler

默认的returnValueHandlers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();
// Single-purpose return value types
// 返回值类型是ModelAndView或其子类
handlers.add(new ModelAndViewMethodReturnValueHandler());
// 返回值类型是Model或其子类
handlers.add(new ModelMethodProcessor());
// 返回值类型是View或其子类
handlers.add(new ViewMethodReturnValueHandler());
// 用来处理返回值类型是HttpEntity的方法
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
handlers.add(new CallableMethodReturnValueHandler());
handlers.add(new DeferredResultMethodReturnValueHandler());
handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
// Annotation-based return value types
// 返回值有@ModelAttribute注解
handlers.add(new ModelAttributeMethodProcessor(false));
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
// Multi-purpose return value types
// 返回值是void或String, 将返回的字符串作为view视图的名字
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());
// Custom return value types
//这里这里会从customReturnValueHandlers属性中获取我们自定的HandlerMethodReturnValueHandler
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
// Catch-all
if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
}
else {
handlers.add(new ModelAttributeMethodProcessor(true));
}
return handlers;
}

使用@ResponseBody注解的话最终返回值会被RequestResponseBodyMethodProcessor这个HandlerMethodReturnValueHandler实现类处理。

至此,所有的HandlerMethodReturnValueHandler的注册已经完成。

执行流程

  • 第一步:获取合适的HandlerAdapter,当方法含有@RequestMapping注释的时候,便选择RequestMappingHandlerAdapter来进行方法的调度处理
  • 第二步:方法的调度处理过程为:首先执行方法体,然后根据返回值来选择一个合适的HandlerMethodReturnValueHandler,如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// RequestMappingHandlerAdapter类
/**
* Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}
* if view resolution is required.
*/
private ModelAndView invokeHandleMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// 创建 ServletInvocableHandlerMethod (HandlerMethod 的子类),并绑定相关属性
ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result);
}
// 执行处理器的方法, 重点。。。。。。(看下面)
requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
// 返回 ModelAndView, 重点。。。。。。
return getModelAndView(mavContainer, modelFactory, webRequest);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ServletInvocableHandlerMethod类(HandlerMethod 的子类)
public final void invokeAndHandle(ServletWebRequest webRequest,
ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// 执行该请求处理方法(包含了获取该请求处理方法参数值),取得返回值
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);
if (returnValue == null) {
if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(this.responseReason)) {
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
try {
// 重点。。。。。。
this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
}
throw ex;
}
}

this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest)会遍历所有的已注册的HandlerMethodReturnValueHandler判断他们支不支持returnValue的返回类型。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// HandlerMethodReturnValueHandlerComposite类(包含了所有的HandlerMethodReturnValueHandler)
public void handleReturnValue(
Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws Exception {
HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType);
Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]");
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
/**
* Find a registered {@link HandlerMethodReturnValueHandler} that supports the given return type.
*/
private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) {
for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) {
if (logger.isTraceEnabled()) {
logger.trace("Testing if return value handler [" + returnValueHandler + "] supports [" +
returnType.getGenericParameterType() + "]");
}
if (returnValueHandler.supportsReturnType(returnType)) {
return returnValueHandler;
}
}
return null;
}

找到支持的HandlerMethodReturnValueHandler后,就要执行它的handleReturnValue方法。假设使用了`@ResponseBody注解,则由RequestResponseBodyMethodProcessor类处理。

1
2
3
4
5
6
7
8
9
10
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException {
mavContainer.setRequestHandled(true);
if (returnValue != null) {
// 由这里处理返回,涉及到HttpMessageConverter处理
writeWithMessageConverters(returnValue, returnType, webRequest);
}
}

注意这里设置mavContainer.setRequestHandled(true),表示请求已被处理,不需要返回ModelAndView。看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# RequestMappingHandlerAdapter
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
modelFactory.updateModel(webRequest, mavContainer);
// 如果isRequestHandled()为true,不需要再做处理
if (mavContainer.isRequestHandled()) {
return null;
}
ModelMap model = mavContainer.getModel();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model);
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
return mav;
}

热评文章