RestTemplate调用微信小程接口异常:RestClientException: Could not extract response: no suitable HttpMessageConve
第一次玩微信小程序,调用第一个接口jscode2session居然就出问题了。采用RestTemplate访问https://api.weixin.qq.com/sns/jscode2session,就提示异常:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.solar.app.model.weixin.WxBaseUserInfo] and content type [text/plain]
查询度娘,原因如下:
虽然这里的微信接口返回的是 Json 格式的数据,但是在返回的 Header 里面的 Content-Type 值却是 text/plain,而RestTemplate的消息转换器集合中默认是没有这个类型的,所以需要把这个类型加入到消息转换器中。
分析:
public RestTemplate() {this.messageConverters = new ArrayList();this.errorHandler = new DefaultResponseErrorHandler();this.headersExtractor = new RestTemplate.HeadersExtractor();this.messageConverters.add(new ByteArrayHttpMessageConverter());this.messageConverters.add(new StringHttpMessageConverter());this.messageConverters.add(new ResourceHttpMessageConverter(false));if (!shouldIgnoreXml) {try {this.messageConverters.add(new SourceHttpMessageConverter());} catch (Error var2) {}}this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());if (romePresent) {this.messageConverters.add(new AtomFeedHttpMessageConverter());this.messageConverters.add(new RssChannelHttpMessageConverter());}if (!shouldIgnoreXml) {if (jackson2XmlPresent) {this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());} else if (jaxb2Present) {this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());}}if (jackson2Present) {this.messageConverters.add(new MappingJackson2HttpMessageConverter());} else if (gsonPresent) {this.messageConverters.add(new GsonHttpMessageConverter());} else if (jsonbPresent) {this.messageConverters.add(new JsonbHttpMessageConverter());} else if (kotlinSerializationJsonPresent) {this.messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());}if (jackson2SmilePresent) {this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());}if (jackson2CborPresent) {this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());}this.uriTemplateHandler = initUriTemplateHandler(); }
而springboot内置的就是jackson来进行json的序列化和反序列号,通过debug也可以验证这一点(jackson2Present == true),也就是说RestTemplate会默认加入MappingJackson2HttpMessageConverter这个转换器,它有两个构造方法,我们可以发现其支持的MediaType为application/json
public MappingJackson2HttpMessageConverter() {this(Jackson2ObjectMapperBuilder.json().build()); // 这里调用的是第二个构造方法 }public MappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {super(objectMapper, new MediaType[]{MediaType.APPLICATION_JSON, new MediaType("application", "*+json")}); }
通过debug,发现RestTemplate会执行doExecute方法
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {Assert.notNull(url, "URI is required");Assert.notNull(method, "HttpMethod is required");ClientHttpResponse response = null;Object var14;try {ClientHttpRequest request = this.createRequest(url, method);if (requestCallback != null) {requestCallback.doWithRequest(request);}response = request.execute();this.handleResponse(url, method, response);var14 = responseExtractor != null ? responseExtractor.extractData(response) : null;} catch (IOException var12) {String resource = url.toString();String query = url.getRawQuery();resource = query != null ? resource.substring(0, resource.indexOf(63)) : resource;throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + var12.getMessage(), var12);} finally {if (response != null) {response.close();}}return var14; }
responseExtractor.extractData这个方法负责从httpresponse中获取数据,利用到了消息转换器。实际进入到类HttpMessageConverterExtractor中:
public T extractData(ClientHttpResponse response) throws IOException {MessageBodyClientHttpResponseWrapper responseWrapper = new MessageBodyClientHttpResponseWrapper(response);if (responseWrapper.hasMessageBody() && !responseWrapper.hasEmptyMessageBody()) {MediaType contentType = this.getContentType(responseWrapper);try {Iterator var4 = this.messageConverters.iterator();while(var4.hasNext()) {HttpMessageConverter<?> messageConverter = (HttpMessageConverter)var4.next();if (messageConverter instanceof GenericHttpMessageConverter) {GenericHttpMessageConverter<?> genericMessageConverter = (GenericHttpMessageConverter)messageConverter; //此处即是判断消息转换器的类型是否会http响应的类型相同if (genericMessageConverter.canRead(this.responseType, (Class)null, contentType)) {if (this.logger.isDebugEnabled()) {ResolvableType resolvableType = ResolvableType.forType(this.responseType);this.logger.debug("Reading to [" + resolvableType + "]");}return genericMessageConverter.read(this.responseType, (Class)null, responseWrapper);}}if (this.responseClass != null && messageConverter.canRead(this.responseClass, contentType)) {if (this.logger.isDebugEnabled()) {String className = this.responseClass.getName();this.logger.debug("Reading to [" + className + "] as \"" + contentType + "\"");}return messageConverter.read(this.responseClass, responseWrapper);}}} catch (HttpMessageNotReadableException | IOException var8) {throw new RestClientException("Error while extracting response for type [" + this.responseType + "] and content type [" + contentType + "]", var8);}throw new UnknownContentTypeException(this.responseType, contentType, responseWrapper.getRawStatusCode(), responseWrapper.getStatusText(), responseWrapper.getHeaders(), getResponseBody(responseWrapper));} else {return null;} }
通过红色标记的异常,正是我们程序输出的异常。不难发现,这个方法一开始就会获取所有的消息转换器,然后逐条遍历,判断是否有相应的转换器的类型与http响应类型responseType相同,如果都没有相同的,则会抛出该异常。到这里我们就会容易想到,既然原因是没有这个类型text/plain引起的,我们可以在转换器集合中添加这个类型。
两种解决方法:
1、我们可以仿造MappingJackson2HttpMessageConverter类,创建一个MyMappingJackson2HttpMessageConverter类,将里面的
super(objectMapper, new MediaType[]{MediaType.APPLICATION_JSON, new MediaType("application", "*+json")});
改为
super(objectMapper, new MediaType[]{MediaType.TEXT_PLAIN, new MediaType("text", "*+plain")});
2.也可以直接继承MappingJackson2HttpMessageConverter类,自定义MyMappingJackson2HttpMessageConverter类,在其构造方法中添加Text_PLAIN类型
public class MyMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {public WxMappingJackson2HttpMessageConverter(){List<MediaType> mediaTypes = new ArrayList<>();mediaTypes.add(MediaType.TEXT_PLAIN);setSupportedMediaTypes(mediaTypes);} }
最后在我们的springboot项目中构建RestTemplate对象的地方,添加我们自定义的消息转换器
@Configuration public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate(RestTemplateBuilder builder){RestTemplate restTemplate = builder.build();restTemplate.getMessageConverters().add(new WxMappingJackson2HttpMessageConverter());return restTemplate;} }
到此,分析完毕。
借鉴了下面博主的这个分析,自己也重新做了分析验证和其它的解决方法,不过殊途同归,有不正确的地方还请大佬不吝指教。RestTemplate请求Could not extract response: no suitable HttpMessageConverter found for response type.._z69183787的专栏-CSDN博客
RestTemplate调用微信小程接口异常:RestClientException: Could not extract response: no suitable HttpMessageConve相关推荐
- 使用RestTemplate:报错Could not extract response: no suitable HttpMessageConverter found for response typ
项目中需要调用微信接口获取access_token等一系列和微信接口相关的操作,我使用了Spring自带的RestTemplate类来发送Get或Post请求,直接在Spring配置文件中依赖注入 & ...
- RestTemplate请求Could not extract response: no suitable HttpMessageConverter found for response type..
使用 Spring Boot 写项目,需要用到微信接口获取用户信息. 在 Jessey 和 Spring RestTemplate 两个 Rest 客户端中,想到尽量不引入更多的东西,然后就选择了 S ...
- 【spring boot】使用RestTemplate调用微信code2Session接口
前言 spring boot 2.1.1.RELEASE 使用RestTemplate调用微信code2Session接口 spring boot中使用RestTemplate,参考这里. 调用方法 ...
- 微信小程序快递java_java调用微信小程序统一下单接口
java调用微信小程序统一下单接口 今天项目中对接微信支付这一块,记录一下 这是对接微信支付的开发文档地址 微信支付流程 流程分析: 我们可以看到,前端人员只用给我们一个code,我们通过code去获 ...
- uni-app开发微信小程使用腾讯位置服务获取用户的位置信息
uni-app开发微信小程使用腾讯位置服务获取用户的位置信息 一.开通腾讯位置服务 二.编码实现 (一)获取定位坐标 (二).在项目中使用 一.开通腾讯位置服务 在这里我们先要登录腾讯我i之服务的官网 ...
- 微信小程热映电影导演等数据获取
微信小程热映电影导演等数据获取 微信小程电影数据读取与呈现 我们获取了豆瓣API的电影图片,现在我们重接口在获取导演,主角,电影名等数据. 获取导演,主角,电影名等数据我们要进行封装,就要定义一个数组 ...
- 微信小程序接口实现加密
微信小程序接口实现加密教程: 场景 小程序请求的所有接口参数必须加密,后台返回数据也需要加密,并且增加Token验证 一.小程序端功能编写 1.下载一份Js版的aesUtil.js源码.[注:文章末尾 ...
- python写的小程序怎么封装_Promise实现微信小程序接口封装过程
Promise实现微信小程序接口封装过程 发布时间:2020-06-15 13:40:43 来源:亿速云 阅读:419 作者:鸽子 相信很多开发者都遇到过回调地狱的问题.由于微信小程序的API基本都是 ...
- 微信小程序支付异常:requestPayment:fail no permission
微信小程序支付异常:requestPayment:fail no permission 参考文章: (1)微信小程序支付异常:requestPayment:fail no permission (2) ...
最新文章
- 计算机转进制怎么看平方,计算机数制转换
- 李进良/丁守谦:希望TD-LTE成为4G的统一标准
- 这是我的第一个python程序怎么打-我的第一个Python程序(运行)
- python费用结算系统_python 全栈开发,Day104(DRF用户认证,结算中心,django-redis)
- Intel Realsense D435 pyrealsense2 get_option_range() 获取rs.option中参数值取值范围 获取默认值
- python android自动化测试框架_appium+python搭建自动化测试框架_Tools安装(一)
- 数据库问题6-將系統資料表對應至系統檢視
- Echar的学习记录
- 文件相似度比对工具的设计与实现
- HDU 2825 AC自动机+状压dp
- 揭秘 | Akuna工作体验大揭秘
- 已解决:Torch not compiled with CUDA enabled
- Spring Cloud Gateway 服务网关的部署与使用详细介绍
- 数据分析常用的Excel函数合集
- go语言sql转struct在线工具
- java项目生成多个条码_java – 生成随机条形码 – 一个设计问题
- [枚举]Stormwind 2022杭电多校第8场 1011
- 解放前端工程师——手把手教你开发自己的自定义列表和自定义表单系列之一缘起
- C语言速成笔记 —— 考点详解 知识点图解
- html5怎么让图片垂直居中显示,css中如何实现图片垂直居中显示?