当前位置:网站首页>RestTemplate源码debug:可变形参引发的问题
RestTemplate源码debug:可变形参引发的问题
2022-07-29 17:50:00 【ZJH'blog】
今天在做一个跨域请求的时候遇到一个问题,我需要同时从JDK7版本的项目接口中取出设置的请求头和响应的二进制流数据,按着源码分析了半天,把API倒是玩明白了,最后发现是因为没有注意可变形参引发的问题。。因为之前没有用过这个API,所以出这个问题的时候也没往这方面想,纯属是debug排除了所有问题。。。记录一下吧
1.环境模拟
1.1接口提供
提供一个接口,设置一个请求头给response,把图片二进制流写入response
@GetMapping("/pic1")
public void getPic(HttpServletRequest request,HttpServletResponse response) throws IOException {
response.setHeader("keyy","valuee");
System.out.println(response.getHeader("keyy"));
File file = new File("C:\\Users\\zhangjiahao\\Desktop\\变更图片\\班级活动.jpg");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] buf = new byte[2048];
ServletOutputStream os = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(os);
while(bis.read(buf) != -1){
bos.write(buf);
}
bos.flush();
bos.close();
bis.close();
}
1.2工具类(2个)
前提须知:
getForEntity()和exchange()本质上都是调用的excute()
返回值都是ResponseEntity
产生的问题是,这个ResponseEntity最后在getBody()的时候,一个能读取到二进制流,一个读取不到
1.2.1使用getForEntity()
public static String getStreamAndHeader(String url,String headKey,HttpServletResponse response) {
RestTemplate restTemplate = getSingleRestTemplate();
ResponseEntity<byte[]> responseEntity = restTemplate.getForEntity(url, null, byte[].class, (Object) null);
byte[] res = responseEntity.getBody();//获取不到。res=null
HttpHeaders headers = responseEntity.getHeaders();
String value = headers.getFirst(headKey);
try {
ServletOutputStream os = response.getOutputStream();
os.write(res);
os.flush();
os.close();
}
catch (IOException e) {
logger.error("请求接口二进制流写入response时异常{}",e);
}
return value;
}

1.2.2使用exchange()
public static void getStreamWithNoParam(String url, HttpMethod method, HttpServletResponse response) {
RestTemplate restTemplate = getSingleRestTemplate();
try {
ResponseEntity<byte[]> exchange = restTemplate.exchange(url, method, null, byte[].class, (Object) null);
byte[] body = exchange.getBody();//正常获取
String value = exchange.getHeaders().getFirst("keyy");
response.setHeader("keyy",value);
response.getOutputStream().write(body);
}
catch (IOException e) {
logger.error("RestTemplateUtils获取接口二进制流异常");
}
}

2.源码分析思路
2.1方法本身区别
调用exchange()的时候,内部调用的方法是需要携带请求参数的,不过可以设为null


两个方法本身的区别就是:requestEntity,即请求参数
2.2分别看两个内部的方法
2.2.1 exchange-带参的:httpEntityCallback

到目前为止没有看到对返回值response进行操作的内容
2.2.2getFroEntity-无参:acceptHeaderRequestCallback


3.到此没有分析出异常,则看request回调相关的execute
3.1分析理由
因为两个方法的区别就是在于回调RequestCallback,本身分析不出来问题,就去找其他RequestCallback相关的即execute()执行方法本身
3.2doExecute()
doWithRequest()对于这两个方法来说,其实都是会执行的

debug的时候能正常进去

虽然这里没有指定requestEntity
但是内部造了一个requestCallBack,和requestEntity没有关系

4.定位到doWithRequest()

这两个实现类其实是父子类关系,都会调用(内部用的super)
4.1 debug 发现支持的媒体类型
发现在使用getForEntity()的时候,走到这里是false,因此没有指定返回值的类型
而正常正确的应该是这样

4.2回去看参数是否正确
发现这里给responseType指定为了null,那么问题来了,为什么参数写错了但是没提示?

这是因为最后最后一个形参是Object... uriVariables,这种形参放在最后一位就支持这种很多逗号的写法
5.修改参数

然后就跑通了
6.结论
其实这两个方法本质只有“是否携带请求参数”的区别,其他的所有东西都一样,执行的过程一样,返回值一样,返回值的使用方式一样。
唯一值得需要注意的是,以后遇到这种最后一个形参是Object... uriVariables的,就要对形参的个数比较敏感一点
边栏推荐
- The 14th day of the special assault version of the sword offer
- [网络]WAN技术 PPP
- UNIX Environment Advanced Programming Chapter 3
- 本周投融报:CeFi积聚风投吸引力
- 分批数据遍历的优化
- Thread、Runnable、Callable、Future ... 的关系?
- DTSE Tech Talk丨第2期:解读云原生技术下,SaaS应用技术架构设计
- 闻泰科技携手格力集团收购欧菲光旗下广州得尔塔等资产
- 机器学习:知道模型评估中的SSE、“肘”部法、SC系数和CH系数的实现原理
- 请问跑sql任务调度必须得设置依赖的上游节点嘛?比如说我sql里面a b两张表join出来的结果写入
猜你喜欢

字节跳动 Flink 状态查询实践与优化

【码蹄集新手村600题】pow()函数详解

数字化来势汹汹,低代码起势,JNPF助力企业定制专属BIM

【深度学习】使用yolov5对数据进行预标注

StarRocks 2.3 新版本特性介绍

mysql存储过程 实现全量同步数据并自动创建表

十大企业数据安全优秀实践

redis学习三redis里的list、set、hash、sorted_set、skiplist

Babbitt | Metaverse Daily Must Read: Seven consecutive quarters of losses, Meta Metaverse division Q2 loss of $ 2.8 billion, Zuckerberg said this situation may continue for years ...

疫情驱动医疗数字化新业态,ActiveReports强力助推医院LIMS系统升级换代!
随机推荐
Network Effects in Web3
闻泰科技携手格力集团收购欧菲光旗下广州得尔塔等资产
2022开放原子全球开源峰会OpenAnolis分论坛圆满落幕
实时数仓:知乎实时数仓的架构演进
FPGA设计16位二进制全加器模块
I don't feel rested in the morning on a rest day
Matplotlib(三)通过plt.subplots创建子绘图
The problem that crontab executes scheduled tasks and reports errors
go的堆内存结构分析
免费创建一个令人惊叹的网站的7个技巧
疫情驱动医疗数字化新业态,ActiveReports强力助推医院LIMS系统升级换代!
分析师:百度到2030年可能成为中国市值最高的公司
Batch_Normalization 、Layer_Normalization 、Group_Normalization你分的清楚吗
Mathematical Analysis_Proof_Two Important Limits (Tongji Version)
mysql存储过程 实现全量同步数据并自动创建表
赠书|《软硬件融合》带你学习从CPU、DSP到软硬件融合的计算创新之路
有效供应链管理的八大绩效分析指标(下)
使用LIMIT分页
平行坐标图:高维数据可视化必备图形
【码蹄集新手村600题】求所给数据的平方根