【SpringBoot2—Web请求返回值处理源码解析】

源码解析

版本信息:SpringBoot 2.6.1

每一部分的最后,我都放了所有断点信息的截图,只要你跟着debug下来,相信你一定收获满满

1. 返回值处理源码解析

1.1 测试 controller 编写

我们简单编写一个 controller 里面包含一个查询用户信息的方法,返回一个

@RestController
@Slf4j
public class TestController {

    @GetMapping("/user/{id}")
    public User user(@PathVariable Integer id) {
        log.info("查询用户信息id={}", id);
        User user = new User();
        user.setName("张三");
        user.setAge(18);
        return user;
    }
}

接下来我们用 postman 发起请求来看一下返回值的处理过程
在这里插入图片描述

1.2 源码debug

本次 debug 会直接进入到返回值处理部分,前面的寻找方法处理器、请求参数处理等等在我的另一篇文章中有详细讲解 【SpringBoot2—Web请求处理源码解析】

我们从 org.springframework.web.servlet.DispatcherServlet#doDispatch 开始看
在这里插入图片描述
接下来直接来到 ha.handle()
在这里插入图片描述
接下来执行 handleInternal()
在这里插入图片描述
接下来直接来到 invokeHandlerMethod()
在这里插入图片描述
接下来直接来到 invocableMethod.invokeAndHandle()
在这里插入图片描述
从这里开始就真正到了返回值处理流程了,invokeForRequest() 执行了目标方法并获得了返回值
在这里插入图片描述
接下来判断了我们的返回值是否为空,是否有响应异常的原因
在这里插入图片描述
前面的判断通过之后,并且返回值不为空,就到了调用返回值处理器处理返回值的步骤了 this.returnValueHandlers.handleReturnValue()
在这里插入图片描述

处理返回值首先要获取到可以处理当前返回值的处理器,调用 selectHandler()在这里插入图片描述
遍历所有的返回值处理器目前看到的有15个,找到合适的处理器
在这里插入图片描述在这里插入图片描述

最终我们找到 RequestResponseBodyMethodProcessor 这个返回值处理器,我们的 controller 使用了 @RestController 注解,所以返回值相当于被 @ResponseBody 标注,从这个解析器的名称也可以看出就是用来处理返回值为responseBody 的方法
在这里插入图片描述

RequestResponseBodyMethodProcessor 是如何处理的![在这里插入图片描述](https://img-blog.csdnimg.cn/7459af76711c4ae485ff65fcb88b4364.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,te
接下来调用 writeWithMessageConverters()
在这里插入图片描述
接下来判断是否为 Resource 类型,我们是 User 类型不符合
在这里插入图片描述
判断响应类型是否已经被决定,这里并没有将走 else 里的逻辑内容协商
在这里插入图片描述

内容协商
首先获取客户端可以接收的类型为 */* ,可以去查看 postman 的 headers 中的 Accept 值
在这里插入图片描述
在这里插入图片描述
然后获取服务端可以响应的类型,可以看到目前有4种
在这里插入图片描述
使用两层 for 循环找到可以用于响应给客户端的类型
在这里插入图片描述
经过内容协商,还有4中类型可以用于响应,因为客户端可接受类型是 */*
在这里插入图片描述
由于客户端再发送请求时是可以对每一个类型的响应设置权重的,例如 application/xml;q=0.8 application/json;q=0.9,所以要进行排序
在这里插入图片描述

决定了最终的响应类型之后,就会遍历所有的 messageConverters 消息转换器,找到可以将 返回值类型转化为响应类型的转换器,对于本次请求就是找到能够将 User 转换为 application/json
在这里插入图片描述
放行断点可以看到最终找到了 MappingJackson2HttpMessageConvert
在这里插入图片描述
调用消息转换器的 write() 方法,将响应写出
在这里插入图片描述
然后调用 writeInternal()

在这里插入图片描述

在 writeInternal() 中使用 ObjectWriter 将返回值写入了流中
在这里插入图片描述
可以看到返回值已经被写入到了 outMessage
在这里插入图片描述

至此对于返回值的处理过程我们就 debug 结束了,本次debug 涉及的断点如下所示
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值