当前位置:网站首页>九、响应处理——内容协商底层原理
九、响应处理——内容协商底层原理
2022-08-05 05:16:00 【呆比特】
响应处理——内容协商底层原理
在前边学习返回值解析器时,里边使用了各种 MessageConverter 寻找哪个解析器可以处理我们的返回值,在寻找过程中,非常关键的一步就是内容协商,它通过遍历所有的 MessageConverter 一个一个寻找,接下来,就来看一下整个内容协商的流程。
内容协商:根据客户端接收能力不同,返回不同媒体类型的数据。
接下来,我们使用postman发起请求,分别测试返回json和xml的情况

先以application/xml来测试
前边的请求处理已经很熟悉了,直接下一步来到 ServletInvocableHandlerMethod.class ,
先拿到返回值

我们的请求标注了@ResponseBody,所以下一步就是找到能处理@ResponseBody的Handler,进过寻找,最终找到了 RequestResponseBodyMethodProcessor

step into 进入 writeWithMessageConverters,来到我们的内容协商关键环节
//......代码太多没有全部拿
MediaType selectedMediaType = null;
//首先判断当前响应头中是否已经有确定的媒体类型MediaType,我们没有前置拦截,所以没有
MediaType contentType = outputMessage.getHeaders().getContentType();
boolean isContentTypePreset = contentType != null && contentType.isConcrete();
if (isContentTypePreset) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Found 'Content-Type:" + contentType + "' in response");
}
//如果有的话,就用之前的,我们没有走下边
selectedMediaType = contentType;
} else {
HttpServletRequest request = inputMessage.getServletRequest();
//关键来啦,第一步,获取客户端可接收的媒体类型(accept请求头字段)
List<MediaType> acceptableTypes = this.getAcceptableMediaTypes(request);
这里step into进入看一下是如何获取 acceptableTypes


到这里,就获取到了客户端能接收的值 acceptableTypes 是我们传的 application/xml
//然后获取能产生的媒体类型(写出类型) producibleTypes
List<MediaType> producibleTypes = this.getProducibleMediaTypes(request, valueType, (Type)targetType);
这里step into进入看一下是如何获取 producibleTypes
if (body != null && producibleTypes.isEmpty()) {
throw new HttpMessageNotWritableException("No converter found for return value of type: " + valueType);
}
List<MediaType> mediaTypesToUse = new ArrayList();
Iterator var15 = acceptableTypes.iterator();
//得到客户端需要类型和服务端能处理的类型后,进行最佳匹配,双重循环
MediaType mediaType;
while(var15.hasNext()) {
mediaType = (MediaType)var15.next();
Iterator var17 = producibleTypes.iterator();
while(var17.hasNext()) {
MediaType producibleType = (MediaType)var17.next();
if (mediaType.isCompatibleWith(producibleType)) {
mediaTypesToUse.add(this.getMostSpecificMediaType(mediaType, producibleType));
}
}
}
//.................中间省略处理代码.....................
//拿到我们的对象
body = this.getAdvice().beforeBodyWrite(body, returnType, selectedMediaType, converter.getClass(), inputMessage, outputMessage);
if (body != null) {
LogFormatUtils.traceDebug(this.logger, (traceOn) -> {
return "Writing [" + LogFormatUtils.formatValue(body, !traceOn) + "]";
});
this.addContentDispositionHeader(inputMessage, outputMessage);
if (genericConverter != null) {
//用 支持 将对象转为 最佳匹配媒体类型 的converter。调用它进行转化写出
genericConverter.write(body, (Type)targetType, selectedMediaType, outputMessage);
} else {
converter.write(body, selectedMediaType, outputMessage);
}
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Nothing to write: null body");
}
用最佳converter转化写出
进入 AbstractJackson2HttpMessageConverter.class 的 writeValue 方法

完成之后来到了 write 方法最后一行,看 outputMessage
到这里,我们的内容协商环节就结束了,可以将 Accept 改成 application/json 调试练习。
OVER(∩_∩)O~
边栏推荐
- 【论文精读】R-CNN 之预测框回归(Bounding box regression)问题详述
- PoE视频监控解决方案
- Comparison and summary of Tensorflow2 and Pytorch in terms of basic operations of tensor Tensor
- 【ts】typescript高阶:联合类型与交叉类型
- 【数据库和SQL学习笔记】5.SELECT查询3:多表查询、连接查询
- 【Kaggle项目实战记录】一个图片分类项目的步骤和思路分享——以树叶分类为例(用Pytorch)
- 如何编写一个优雅的Shell脚本(一)
- 数据库期末考试,选择、判断、填空题汇总
- 《基于机器视觉的输电线路交叉点在线测量方法及技术方案》论文笔记
- Spark ML学习相关资料整理
猜你喜欢

发顶会顶刊论文,你应该这样写作

OSPF故障排除办法

2022年中总结关键词:裁员、年终奖、晋升、涨薪、疫情

物联网:LoRa无线通信技术

flink on yarn 集群模式启动报错及解决方案汇总

沁恒MCU从EVT中提取文件建立MounRiver独立工程

CVPR best paper winner Huang Gao's team from Tsinghua University presented the first dynamic network review

Tensorflow2 与 Pytorch 在张量Tensor基础操作方面的对比整理汇总

You should write like this
![[Kaggle project actual combat record] Steps and ideas sharing of a picture classification project - taking leaf classification as an example (using Pytorch)](/img/7d/7f1301c30034f1c247d41f04c40244.png)
[Kaggle project actual combat record] Steps and ideas sharing of a picture classification project - taking leaf classification as an example (using Pytorch)
随机推荐
【Pytorch学习笔记】11.取Dataset的子集、给Dataset打乱顺序的方法(使用Subset、random_split)
Web Component-处理数据
【Pytorch学习笔记】8.训练类别不均衡数据时,如何使用WeightedRandomSampler(权重采样器)
如何编写一个优雅的Shell脚本(三)
网络信息安全运营方法论 (下)
ES6 新特性:Class 的继承
Day1:用原生JS把你的设备变成一台架子鼓!
Comparison and summary of Tensorflow2 and Pytorch in terms of basic operations of tensor Tensor
Flutter 3.0升级内容,该如何与小程序结合
【数据库和SQL学习笔记】4.SELECT查询2:排序(ORDER BY)、聚合函数、分组查询(GROUP BY)
Machine Learning (1) - Machine Learning Fundamentals
AWS 常用服务
数据库期末考试,选择、判断、填空题汇总
Oracle压缩表修改字段的处理方法
CVPR2021 - Inception Convolution with Efficient Dilation Search
MySQL
如何编写一个优雅的Shell脚本(一)
BFC详解(Block Formmating Context)
[Go through 11] Random Forest and Feature Engineering
关于存储IOPS你必须了解的概念