返回值解析器

用于对controller的返回值进行二次处理


结构

// 返回值解析器
public interface HandlerMethodReturnValueHandler { // 判断 HandlerMethodReturnValueHandler 是否支持 MethodParameter
boolean supportsReturnType(MethodParameter returnType); // 处理给定的返回值
void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}

调用

完整调用链

DispatcherServlet#doDispatch()
AbstractHandlerMethodAdapter#handle()
RequestMappingHandlerAdapter#handleInternal()
// 在这里会创建ServletInvocableHandlerMethod,此时已经将controller的函数(HandlerMethod)的参数注入到InvocableHandlerMethod(类变量)中
RequestMappingHandlerAdapter#invokeHandlerMethod()
// 在这里,invokeForRequest通过反射的方式调用controller中的方法并返回returnValue
ServletInvocableHandlerMethod#invokeAndHandle()
// 处理返回值方法
HandlerMethodReturnValueHandlerComposite#handleReturnValue
// 获取返回值处理器
HandlerMethodReturnValueHandlerComposite#selectHandler
// 处理返回值
HandlerMethodReturnValueHandler#handleReturnValue

RequestMappingHandlerAdapter#invokeHandlerMethod()中调用了controller,并得到了返回值

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 调用handler(controller+method),得到返回值
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest); 。。。。。。
try {
// 处理返回值方法
// returnValueHandlers是HandlerMethodReturnValueHandlerComposite类
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}

接下来,就轮到HandlerMethodReturnValueHandlerComposite表演了

// 处理返回值
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 查找处理器
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
// 此处handler就是HandlerMethodReturnValueHandler的实现类
// HandlerMethodReturnValueHandler#handleReturnValue处理返回值
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
} // 查找处理器
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
// returnValueHandlers就是HandlerMethodReturnValueHandler的实现类集合,默认有15个实现类
// 注意:returnValueHandlers是有顺序的
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
// 使用supportsReturnType方法判断该处理器是否支持解析当前返回值
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
}

执行顺序

HandlerMethodReturnValueHandler的调用是有执行顺序的,如果自定义的HandlerMethodReturnValueHandler没有被触发,请检查是否被其他handler抢先了

处理器 处理类型 处理种类
ModelAndViewMethodReturnValueHandler ModelAndView 一种类型
ModelMethodProcessor Model 一种类型
ViewMethodReturnValueHandler View 一种类型
ResponseBodyEmitterReturnValueHandler ResponseEntity 一种类型
StreamingResponseBodyReturnValueHandler ResponseEntity 一种类型
HttpHeadersReturnValueHandler HttpHeaders 一种类型
CallableMethodReturnValueHandler Callable 一种类型
DeferredResultMethodReturnValueHandler DeferredResult、ListenableFuture、CompletionStage 一种类型
AsyncTaskMethodReturnValueHandler WebAsyncTask 一种类型
ModelAttributeMethodProcessor @ModelAttribute(require=false) 针对注解
RequestResponseBodyMethodProcessor @ResponseBody 针对注解
ViewNameMethodReturnValueHandler void、CharSequence(V4.2) 多种类型
MapMethodProcessor Map 多种类型
自定义返回值处理器 自定义
ServletModelAttributeMethodProcessor 兜底方法

springmvc源码笔记-HandlerMethodReturnValueHandler的更多相关文章

  1. springmvc源码笔记-RequestMappingHandlerMapping

    下图是springmvc的执行流程 图片来源:https://www.jianshu.com/p/8a20c547e245 DispatcherServlet根据url定位到Controller和方法 ...

  2. springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)

    HandlerMethodReturnValueHandler是用于对Controller中函数执行的返回值进行处理操作的,springMVC提供了多个HandlerMethodReturnValue ...

  3. springMVC源码笔记

    springMVC 设计总览 下图来源:https://www.cnblogs.com/fangjian0423/p/springMVC-directory-summary.html 下图来源:htt ...

  4. springmvc源码笔记-HandlerMapping注入

    在springmvc中,如何根据url找到controller以及对应方法,依赖的是HandlerMapping接口的getHandler方法 在spring容器中默认注册的HandlerMappin ...

  5. springMVC源码分析--ViewNameMethodReturnValueHandler返回值处理器(三)

    之前两篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)和springMVC源码分析--HandlerMethodReturnValu ...

  6. springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)

    在上一篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)我们介绍了返回值解析器HandlerMethodReturnValueHand ...

  7. springMVC源码分析--HttpMessageConverter写write操作(三)

    上一篇博客springMVC源码分析--HttpMessageConverter参数read操作中我们已经简单介绍了参数值转换的read操作,接下来我们介绍一下返回值的处理操作.同样返回值的操作操作也 ...

  8. springMVC源码分析--HttpMessageConverter数据转化(一)

    之前的博客我们已经介绍了很多springMVC相关的模块,接下来我们介绍一下springMVC在获取参数和返回结果值方面的处理.虽然在之前的博客老田已经分别介绍了参数处理器和返回值处理器: (1)sp ...

  9. SpringMVC源码分析系列

    说到java的mvc框架,struts2和springmvc想必大家都知道,struts2的设计基本上完全脱离了Servlet容器,而springmvc是依托着Servlet容器元素来设计的,同时sp ...

随机推荐

  1. RabbitMQ 3.9( 续 )

    前言 基础篇链接:https://www.cnblogs.com/xiegongzi/p/16229678.html 3.9.延迟队列 - 重要 3.9.1.延迟队列概念 这个玩意儿要表达的意思其实已 ...

  2. PPP PPOE详解

    PPP协议是在串行线IP协议SLIP(Serial Line Internet Protocol)的基础上发展起来的.由于SLIP协议具有只支持异步传输方式.无协商过程(尤其不能协商如双方IP地址等网 ...

  3. CentOS自动同步时间

    安装ntpdate yum install ntpdate -y 测试是否正常 ntpdate cn.ntp.org.cn # 正常情况 [root@centos7 www]# ntpdate cn. ...

  4. linux篇--mysql数据库备份并删除前一分钟的数据

    linux 中mysql数据库定时备份并删除前一分钟的所有数据 #!/bin/bash #mysqldump -uroot -ppassword01! imaginebase > /home/b ...

  5. 详解TCP四次挥手(断开TCP连接过程)

    在讲述TCP四次挥手,即断开TCP连接的过程之前,需要先介绍一下TCP协议的包结构. TCP协议包结构: 这里只对涉及到四次挥手过程的字段做解释 (1) 序号(Sequence number) 我们通 ...

  6. 2020.10.17【普及组】模拟赛C组 总结

    总结 这次比赛 120 分,老师说上 200 是不容易的,但我觉得这不是我真的水平 改题情况 T1 题目大意:有 N 个小朋友,每个小朋友有 \(B_i\) 个朋友,问从中随机选 3 人使得 3 人关 ...

  7. C#/VB 数据库连接字符串大全

    C#/VB 数据库连接字符串大全 https://www.connectionstrings.com/ SQL Server常用 Standard Security Server=myServerAd ...

  8. 从零开始学Java——个人笔记(持续更新中)

    从零开始学Java 学习流程 第一阶段:建立编程思想 Java概述 变量 运算符 控制结构 数组.排序和查找 面向对象编程(基础) 面向对象编程(中级) 项目&学习以致用 编程之乐 第二阶段: ...

  9. 29.MySQL高级SQL语句

    MySQL高级SQL语句 目录 MySQL高级SQL语句 创建两个表 SELECT DISTINCT WHERE AND OR IN BETWEEN 通配符 LIKE ORDER BY 函数 数学函数 ...

  10. 用QT制作3D点云显示器——QtDataVisualization

    因为QT的三维显示模块QtDataVisualization已经对个人开发免费开放了,所以在制作点云,地图,表格之类的东西的时候,其实我们都不需要使用QtCharts或者QOpenGL模块了.直接使用 ...