springmvc源码笔记-HandlerMethodReturnValueHandler
返回值解析器
用于对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的更多相关文章
- springmvc源码笔记-RequestMappingHandlerMapping
下图是springmvc的执行流程 图片来源:https://www.jianshu.com/p/8a20c547e245 DispatcherServlet根据url定位到Controller和方法 ...
- springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)
HandlerMethodReturnValueHandler是用于对Controller中函数执行的返回值进行处理操作的,springMVC提供了多个HandlerMethodReturnValue ...
- springMVC源码笔记
springMVC 设计总览 下图来源:https://www.cnblogs.com/fangjian0423/p/springMVC-directory-summary.html 下图来源:htt ...
- springmvc源码笔记-HandlerMapping注入
在springmvc中,如何根据url找到controller以及对应方法,依赖的是HandlerMapping接口的getHandler方法 在spring容器中默认注册的HandlerMappin ...
- springMVC源码分析--ViewNameMethodReturnValueHandler返回值处理器(三)
之前两篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)和springMVC源码分析--HandlerMethodReturnValu ...
- springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)
在上一篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)我们介绍了返回值解析器HandlerMethodReturnValueHand ...
- springMVC源码分析--HttpMessageConverter写write操作(三)
上一篇博客springMVC源码分析--HttpMessageConverter参数read操作中我们已经简单介绍了参数值转换的read操作,接下来我们介绍一下返回值的处理操作.同样返回值的操作操作也 ...
- springMVC源码分析--HttpMessageConverter数据转化(一)
之前的博客我们已经介绍了很多springMVC相关的模块,接下来我们介绍一下springMVC在获取参数和返回结果值方面的处理.虽然在之前的博客老田已经分别介绍了参数处理器和返回值处理器: (1)sp ...
- SpringMVC源码分析系列
说到java的mvc框架,struts2和springmvc想必大家都知道,struts2的设计基本上完全脱离了Servlet容器,而springmvc是依托着Servlet容器元素来设计的,同时sp ...
随机推荐
- jQuery操作标签,jQuery事件操作,jQuery动画效果,前端框架
jQuery操作标签 jQuery代码查找标签绑定的变量名推荐使用 $xxxEle 样式类操作 addClass();// 添加指定的CSS类名. removeClass();// 移除指定的CSS类 ...
- HCNP Routing&Switching之链路聚合
前文我们了解了MSTP相关话题,回顾清参考https://www.cnblogs.com/qiuhom-1874/p/16268682.html:今天我们来聊一聊链路聚合相关话题: 链路聚合是链路高可 ...
- 无线:SSID
BSSID,SSID,ESSID区别 SSID(Service Set Identifier) SSID,AP唯一的ID码,许多人认为可以将SSID写成ESSID,其实不然,SSID是个笼统的 ...
- 3.0 vue以构造函数形式返回数据
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 200 行代码实现基于 Paxos 的 KV 存储
前言 写完[paxos 的直观解释]之后,网友都说疗效甚好,但是也会对这篇教程中一些环节提出疑问(有疑问说明真的看懂了 ),例如怎么把只能确定一个值的 paxos 应用到实际场景中. 既然 Talk ...
- RabbitMQ 环境安装
每日一句 Wisdom is knowing what to do next, skill is knowing how to do it, and virtue is doing it. 智慧是知道 ...
- Hadoop入门学习笔记(一)
Week2 学习笔记 Hadoop核心组件 Hadoop HDFS(分布式文件存储系统):解决海量数据存储 Hadoop YARN(集群资源管理和任务调度框架):解决资源任务调度 Hadoop Map ...
- 《C Primer Plus》第六版笔记--7~10章
目录 第七章 C控制语句:分支和跳转 第八章 字符输入/输出和输入验证 第九章 函数 第十章 数组和指针 第七章 C控制语句:分支和跳转 if else 用法 if (expression) //ex ...
- 配置中心的设计-nacos vs apollo
简介 前面我们分析了携程的 apollo(见 详解apollo的设计与使用),现在再来看看阿里的 nacos. 和 apollo 一样,nacos 也是一款配置中心,同样可以实现配置的集中管理.分环境 ...
- GDKOI 2021 Day1 PJ 爆炸记
早上睡到 7:10 分才想起今天有 GDKOI ,赶紧去买了一个面包赶去机房 发现隔壁的大奆都过来了.比赛时由于昨晚一直没睡好,打了两个小时的哈欠 T1 :暴力模拟 根据 \(r\) 和 \(c\) ...