【老王读SpringMVC-6】Controller method 的正常返回值处理

handler method 的返回值处理包含两个方面:
一是:返回值对象的处理;
二是:视图的渲染。

返回值对象的处理

通过前面的分析,我们知道, 被 @RequestMapping 标记 handler method 的执行是通过调用 RequestMappingHandlerAdapter#handle()
其中,参数解析、handler method 的执行 和 对返回值的处理,最终是通过 ServletInvocableHandlerMethod#invokeAndHandle() 来处理的。

具体的调用过程如下:
RequestMappingHandlerAdapter2

ServletInvocableHandlerMethod#invokeAndHandle() 的处理过程如下:
ServletInvocableHandlerMethod

所以,handler method 返回的值对象会被 HandlerMethodReturnValueHandler 来处理。

HandlerMethodReturnValueHandler

HandlerMethodReturnValueHandler 是处理 handler method 返回值的策略接口。

HandlerMethodReturnValueHandler

其中,RequestResponseBodyMethodProcessor 是用来处理 @ResponseBody 类型的返回值的;
ModelAndViewResolverMethodReturnValueHandler 是一个最终兜底的返回值处理类,它是在所有其他的处理器之后执行的。

此处略去了跟异步请求相关的 ReturnValueHandler :

StreamingResponseBodyReturnValueHandler
CallableMethodReturnValueHandler
AsyncTaskMethodReturnValueHandler

视图的渲染

视图的渲染过程是在 DispatcherServlet 中进行处理的,具体的处理代码如下:

processDispatchResult

DispatcherServlet#render() 会将 ModelAndView 进行渲染。 这是处理请求的最后一个阶段。

render

可以看到,视图渲染的过程如下:
1、通过 ViewResolver 解析 viewName 对应的 View 对象
2、调用 View#render() 渲染视图,呈现给用户

@ResponseBody 标记的方法会经过视图解析吗?

先说结论:@ResponseBody 标记的方法不会经过视图解析。
原因分析:
@ResponseBody 类型的返回值是通过 RequestResponseBodyMethodProcessor 来处理的。
RequestResponseBodyMethodProcessor#handleReturnValue 会设置标志位 requestHandled=true,标记请求已被直接处理,不需要视图解析。
这样的话,RequestMappingHandlerAdapter#invokeHandlerMethod() 返回的 ModelAndView 就是 null,DispatcherServlet 就不会进行视图解析。

RequestResponseBodyMethodProcessor 的处理过程如下:

// RequestResponseBodyMethodProcessor#handleReturnValue
public void handleReturnValue(Object returnValue, MethodParameter returnType,
        ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
        throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

    // 标记标记请求已被直接处理,不需要视图解析
    mavContainer.setRequestHandled(true);
    ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
    ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
    
    writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}

小结

返回值的处理包括返回值对象的处理和视图的渲染。
其中,handler method 的返回值对象会通过 HandlerMethodReturnValueHandler 来处理。
如果需要视图渲染的话,就会在 DispatcherServlet#processDispatchResult() 中进行统一处理,通过 ViewResolver 解析出相应的 View 视图,最终调用 View#render() 渲染视图,呈现给用户。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老王学源码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值