一 概述

实现如下效果代码,且可正常获取到返回数据:

ResponseEntity<JsonObject> resEntity = restTemplate
.exchange(url, HttpMethod.GET, requestEntity, JsonObject.class,uriVariables);

restTemplate的get和POST请求都有类型参数设置,所以可以直接返回转换成自定义的格式.比如:

restTemplate.getForObject("http://www.baiud.com",JsonObject.class);

但是exchange是无法指定返回类型的,只能使用spring默认提供的几种转换器转换的格式,定义其他格式会报错或者返回实体body为空

restTemplate的post方法支持设置header,但是get方法不支持,假如现在有个需求,使用get方法需要设置header权限,且返回我想要的格式,那么自定义HttpMessageConverter就派上用场了

也提现了spring非常强大的可扩展性

二 步骤

新建自定义转换类:

/**
* 接口请求返回数据格式转换处理类,只处理String->JsonObject
*/
public class StringToJsonObjectMessageConverter extends AbstractHttpMessageConverter<JsonObject> { public StringToJsonObjectMessageConverter() {
super(StandardCharsets.UTF_8,MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML); //设置支付类型
}
/**
* HttpMessageConvert是否处理接受的这个类
*/
@Override
protected boolean supports(Class<?> aClass) {
//isAssignableFrom: 判定此Class对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口
return JsonObject.class==aClass;
} //对数据进行处理并返回
@Override
protected JsonObject readInternal(Class<? extends JsonObject> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
//数据转换
String temp = StreamUtils.copyToString(httpInputMessage.getBody(),Charset.forName("UTF-8"));
return Tools.getGsonInstance().fromJson(temp, JsonObject.class);
} //处理如何输出数据到response
@Override
protected void writeInternal(JsonObject jsonObject, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
//可继续处理转换后的格式数据
httpOutputMessage.getBody().write(jsonObject.getAsByte());
}
}

配置修改自定义类顺序:

    @Bean
public RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectionRequestTimeout(30 * 1000);
httpRequestFactory.setConnectTimeout(30 * 3000);
httpRequestFactory.setReadTimeout(30 * 3000);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
// 支持返回JsonObject类型数据,需要在String之前,因为String支付所有的类型会直接解析
restTemplate.getMessageConverters().set(1,new StringToJsonObjectMessageConverter());
//spring转换默认编码是ISO_8859_1,如果乱码可修改支持中文编码
restTemplate.getMessageConverters().add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}

断点查看:

三 原理

exchage方法源码点进去,看一下就知道了

        //获取HttpMessageConverter集合
Iterator var8 = RestTemplate.this.getMessageConverters().iterator();
//按照索引顺序进行迭代循环解析
while(var8.hasNext()) {
HttpMessageConverter<?> messageConverter = (HttpMessageConverter)var8.next();
if (messageConverter instanceof GenericHttpMessageConverter) {
GenericHttpMessageConverter<Object> genericConverter = (GenericHttpMessageConverter)messageConverter;
if (genericConverter.canWrite((Type)requestBodyType, requestBodyClass, requestContentType)) {
if (!requestHeadersx.isEmpty()) {
requestHeadersx.forEach((key, values) -> {
httpHeadersx.put(key, new LinkedList(values));
});
} if (RestTemplate.this.logger.isDebugEnabled()) {
if (requestContentType != null) {
RestTemplate.this.logger.debug("Writing [" + requestBody + "] as \"" + requestContentType + "\" using [" + messageConverter + "]");
} else {
RestTemplate.this.logger.debug("Writing [" + requestBody + "] using [" + messageConverter + "]");
}
}
//解析成功直接返回,不会走后面解析器
genericConverter.write(requestBody, (Type)requestBodyType, requestContentType, httpRequest);
return;
}
} else if (messageConverter.canWrite(requestBodyClass, requestContentType)) {
if (!requestHeadersx.isEmpty()) {
requestHeadersx.forEach((key, values) -> {
httpHeadersx.put(key, new LinkedList(values));
});
} if (RestTemplate.this.logger.isDebugEnabled()) {
if (requestContentType != null) {
RestTemplate.this.logger.debug("Writing [" + requestBody + "] as \"" + requestContentType + "\" using [" + messageConverter + "]");
} else {
RestTemplate.this.logger.debug("Writing [" + requestBody + "] using [" + messageConverter + "]");
}
} messageConverter.write(requestBody, requestContentType, httpRequest);
return;
}
}
//如果都没有解析成功.抛异常
String message = "Could not write request: no suitable HttpMessageConverter found for request type [" + requestBodyClass.getName() + "]";
if (requestContentType != null) {
message = message + " and content type [" + requestContentType + "]";
} throw new RestClientException(message);

自定义HttpMessageConverter实现RestTemplate的exchange方法返回自定义格式数据的更多相关文章

  1. SpringBoot 使用 RestTemplate 调用exchange方法 显示错误信息

    SpringBoot使用RestTempate SpringBoot使用RestTemplate摘要认证 SpringBoot使用RestTemplate基础认证 SpringBoot使用RestTe ...

  2. Spring MVC 学习笔记11 —— 后端返回json格式数据

    Spring MVC 学习笔记11 -- 后端返回json格式数据 我们常常听说json数据,首先,什么是json数据,总结起来,有以下几点: 1. JSON的全称是"JavaScript ...

  3. 返回json格式数据乱码

    本文为博主原创,未经允许不得转载: 原本返回json格式数据的代码: @ResponseBody @RequestMapping(value = "getListByTime", ...

  4. WebService返回json格式数据供苹果或者安卓程序调用

    1.新建一个WebService. 2. /// <summary> /// DemoToJson 的摘要说明 /// </summary> [WebService(Names ...

  5. 使用jQuery发送POST,Ajax请求返回JSON格式数据

    问题: 使用jQuery POST提交数据到PHP文件, PHP返回的json_encode后的数组数据,但jQuery接收到的数据不能解析为JSON对象,而是字符串{"code" ...

  6. Django 1.8.11 查询数据库返回JSON格式数据

    Django 1.8.11 查询数据库返回JSON格式数据 和前端交互全部使用JSON,如何将数据库查询结果转换成JSON格式 环境 Win10 Python2.7 Django 1.8.11 返回多 ...

  7. Spring RestTemplate 之exchange方法

    ●exchange方法提供统一的方法模板进行四种请求:POST,PUT,DELETE,GET (1)POST请求 String reqJsonStr = "{\"code\&quo ...

  8. SpringMVC第五篇【方法返回值、数据回显、idea下配置虚拟目录、文件上传】

    Controller方法返回值 Controller方法的返回值其实就几种类型,我们来总结一下-. void String ModelAndView redirect重定向 forward转发 数据回 ...

  9. Asp.net mvc返回Xml结果,扩展Controller实现XmlResult以返回XML格式数据

    我们都知道Asp.net MVC自带的Action可以有多种类型,比如ActionResult,ContentResult,JsonResult……,但是很遗憾没有支持直接返回XML的XmlResul ...

随机推荐

  1. Java 8 默认接口实现及其他语言特性

    一.为什么有默认接口实现 1.由于Java 8的API在现存的接口上引入了非常多的新方法(如List接口上的sort方法).在原有语法基础上,如Guava和Apache Commons这样的框架都需要 ...

  2. 银川区域赛 H道路与航线(原题啊)

    按照<算法竞赛进阶指南>写的 哦对了,注意下最后判断,因为开始拓扑的时候,s可能不在里边,所以不一定等于INF,而是应该大于等于INF #include<cstring> #i ...

  3. win32简单的sockeTCP协议通信

    什么也不说了看代码 首先是服务端代码 #include <stdio.h> #include <stdlib.h> #include <WinSock2.h> #i ...

  4. vue报错 [Intervention] Ignored attempt to cancel a touchmove event with cancelable

    在vue开发中使用vue-awesome-swiper制作轮播图,手动拖动时会报错,解决方案: 需要滑动的标签 { touch-action: none; } -------------------- ...

  5. 原生JavaScript实现评分效果

    一.实现原理: 1.要设置一个“大总管变量”,用于记录点击时的星星下标,只声明不赋值. 2.移入每个星星时,先把所有的星星恢复到默认状态:再把当前星星及在它之前的星星设为选中状态. 3.移出每个星星时 ...

  6. CF825G Tree Queries

    [题意] 一棵树有 n个节点,初始均为白色,有两种操作: 1. 1 x 代表把结点 x 设置为黑色 2. 2 x 代表查询 x 到树上任意一个黑色结点的简单路径上的编号最小的结点的编号 输入 t 和 ...

  7. python之嵌套函数调用

    #定义嵌套函数 def func1(): print('this is func1') def func2(): print('this is func2')#调用1func1()输出:this is ...

  8. 更好用的 Python 任务自动化工具:nox 官方教程

    英文| nox tutorial 出处| nox 官方文档 译者| 豌豆花下猫@Python猫 Github地址:https://github.com/chinesehuazhou/nox_doc_c ...

  9. 2019-2020春江云暖你先知,CAE/EDA/高校等CloudHPC领域年均复合增长率超21%

    原创: 灵魂工作室 速石科技 我猜,我们是最早和你说春天来了的人. 一年前,我们还在小心谨慎地定义着Cloud HPC,一脸娇羞地拿Novartis 诺华制药在5年前做的案例当作标杆. 不久前,Hyp ...

  10. 【Java编程思想阅读笔记】Java数据存储位置

    Java数据存储位置 P46页有感 一.前置知识 栈是由系统自动分配的,Java程序员对栈没有直接的操作权限, 堆是所有线程共享的内存区域,栈 是每个线程独享的. 堆是由程序员自己申请的,在使用new ...