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 ...
随机推荐
- 论文阅读 Dynamic Graph Representation Learning Via Self-Attention Networks
4 Dynamic Graph Representation Learning Via Self-Attention Networks link:https://arxiv.org/abs/1812. ...
- kernel heap bypass smep,smap && 劫持modprobe_path
kernel heap bypass smep,smap && 劫持modprobe_path exp1 smep:smep即用户数据不可执行,当 CPU 处于 ring0 模式时,执 ...
- linux篇-linux iptables配置
1 iptables默认系统自带 setup 2重启防火墙 /etc/init.d/iptables restart 3接受端口 Vi /etc/sysconfig/iptables -A INPUT ...
- 104_Power Query 数据库条件查询
博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载 1.应用场景 底层数据在数据库(sql server数据库,其他数据库同理,下文不再说明.)中,Excel中有查询的字段,需要 ...
- WTF表单验证
WTF表单验证可分为3个步骤: ①导入wtf扩展提供的表单验证器.(from wtforms.validators import DataRequired,EqualTo) ②定义表单类 # 定义表单 ...
- 安装Speedtest到Python
Speedtest模块可以测试主机的网络带宽大小. 运行环境 系统版本:CentOS Linux release 7.3.1611 (Core) 软件版本:无 硬件要求:无 安装过程 1.安装Spee ...
- 20 HTTP 长连接与短连接
20 HTTP 长连接与短连接 每日一句 纸上得来终觉浅,绝知此事要躬行. 每日一句 Never give up until the fight is over. 永远不要放弃,要一直战斗到最后一秒. ...
- vue大型电商项目尚品汇(前台篇)day05终结篇
前台部分到此结束,一路走来还挺怀念,今天主要是对整个项目的完成做一个最后的收尾工作,对于功能上的需求没有什么了,主要就是项目上线的一些注意事项. 一.个人中心二级路由 当我们点击查看订单应该跳转到个人 ...
- Typora使用手册(小白入门级)
Typora软件的简单使用 1.简介 Typora是一款支持Markdown语法的文档编辑器 特点:功能强大.画面极简. 下载地址:https://typoraio.cn/ 2.基础设置 偏 ...
- pycharm相关介绍
一.settings设置 1.搜font 设置字体 2.Keymap------快捷键 二.常用快捷键 1.Ctrl + Enter:在下方新建行但不移动光标: 2.Shift + Enter:在 ...