返回值解析器

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


结构

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

调用

完整调用链

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

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

  1. public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
  2. Object... providedArgs) throws Exception {
  3. // 调用handler(controller+method),得到返回值
  4. Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
  5. setResponseStatus(webRequest);
  6. 。。。。。。
  7. try {
  8. // 处理返回值方法
  9. // returnValueHandlers是HandlerMethodReturnValueHandlerComposite类
  10. this.returnValueHandlers.handleReturnValue(
  11. returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
  12. }
  13. catch (Exception ex) {
  14. if (logger.isTraceEnabled()) {
  15. logger.trace(formatErrorForReturnValue(returnValue), ex);
  16. }
  17. throw ex;
  18. }
  19. }

接下来,就轮到HandlerMethodReturnValueHandlerComposite表演了

  1. // 处理返回值
  2. public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
  3. ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
  4. // 查找处理器
  5. HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
  6. if (handler == null) {
  7. throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
  8. }
  9. // 此处handler就是HandlerMethodReturnValueHandler的实现类
  10. // HandlerMethodReturnValueHandler#handleReturnValue处理返回值
  11. handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
  12. }
  13. // 查找处理器
  14. private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
  15. boolean isAsyncValue = isAsyncReturnValue(value, returnType);
  16. // returnValueHandlers就是HandlerMethodReturnValueHandler的实现类集合,默认有15个实现类
  17. // 注意:returnValueHandlers是有顺序的
  18. for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
  19. if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
  20. continue;
  21. }
  22. // 使用supportsReturnType方法判断该处理器是否支持解析当前返回值
  23. if (handler.supportsReturnType(returnType)) {
  24. return handler;
  25. }
  26. }
  27. return null;
  28. }

执行顺序

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. DirectX11 With Windows SDK--39 阴影技术(VSM、ESM)

    前言 上一章我们介绍了级联阴影贴图.刚开始的时候我尝试了给CSM直接加上PCSS,但不管怎么调难以达到说得过去的效果.然后文章越翻越觉得阴影就是一个巨大的坑,考虑到时间关系,本章只实现了方差阴影贴图( ...

  2. k8s系列--node(k8s节点介绍,新增节点,移除节点)

    一.简介 Node是Pod真正运行的主机,可以是物理机也可以是虚拟机. Node本质上不是Kubernetes来创建的, Kubernetes只是管理Node上的资源. 为了管理Pod,每个Node节 ...

  3. Java高并发-多线程基础

    一.什么是线程 线程是进程内的执行单元. 二.线程的基本操作 2.1 状态与操作 2.2 新建线程 Thread t1 = new Thread(new CreateThread()); t1.sta ...

  4. 139_Power BI之某制造企业HR相关数据年度复盘

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 最近在忙一个关于制造企业HR年度数据复盘分析:数据已脱敏. 先来看看效果. 1.视频效果 [video widt ...

  5. [codeforces] 暑期训练之打卡题(三)

    每个标题都做了题目原网址的超链接 Day21<Alphabetic Removals> 题意: 给定一个字符串,要求按照字典序按照出现的前后顺序删除 k 个字母 题解: 记录字符串中各个字 ...

  6. Redis(1)- Redis数据库的安装和配置

    1.Redis安装 1.1.Linux环境安装Redis step-1:下载Redis 进入官网找到下载地址 https://redis.io/download wget https://github ...

  7. 前端向后端传递formData类型的二进制文件

    // 获取到的文件file类型转换为formData类型 let formData = new FormData(); formData.append("file", file文件 ...

  8. 深入C++02:深入学习C++还必须掌握的基础

    深入学习C++还必须掌握的基础 掌握形参带默认的函数 1.给默认值方向:从右向左给默认值: 2.调用效率:如果传默认值或者立即数(不需要从容器或内存取取的数字)的话都是直接将数字直接push进栈:没有 ...

  9. 对于vjudge在有些网络下无法打开的问题

    因为有些网络会屏蔽vjudge,所以打开 镜像网址 不行再试试这个:最新镜像网址

  10. IDEA windows版本快捷键

    使用本快捷键前,可以在idea使用下面方法确认版本! Ctrl 快捷键 介绍 Ctrl + F 在当前文件进行文本查找 (必备)Ctrl + R 在当前文件进行文本替换 (必备) Ctrl + Z 撤 ...