使用feign发送http请求解析报错的问题

网友投稿 814 2022-08-20


使用feign发送http请求解析报错的问题

目录错误如下错误原因解决方案一解决方案二错误2

错误如下

发送请求开始

-----

[ChannelFeign#formRecog] ---> END HTTP (304117-byte body)

发送请求结束

返回开始

[ChannelFeign#formRecog] <--- HTTP/1.1 200 OK (4948ms)

[ChannelFeign#formRecog] content-length: 5207

[ChannelFeign#formRecog] content-type: text/json;charset=UTF-8

[ChannelFeign#formRecog] date: Mon, 08 Oct 2018 10:47:03 GMT

[ChannelFeign#formRecog] x-vcap-request-id: c323f65a-12e6-4604-7393-a4bf0ca403d5

[ChannelFeign#formRecog]

[ChannelFeign#formRecog] {json格式的数据}

[ChannelFeign#formRecog] <--- END HTTP (5207-byte body)

返回结束

ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.codec.DecodeException: Could not extract response: no suitable HttpMessageConverter found for response type [channel.domain.ChannelResponse] and content type [text/json;charset=UTF-8]] with root causeorg.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [channel.domain.ChannelResponse] and content type [text/json;charset=UTF-8]    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:110) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]    at org.springframework.cloud.netflix.feign.support.SpringDecoder.decode(SpringDecoder.java:59) ~[spring-cloud-netflix-core-1.3.6.RELEASE.jar:1.3.6.RELEASE]    at org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:47) ~[spring-cloud-netflix-core-1.3.6.RELEASE.jar:1.3.6.RELEASE]    at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:165) ~[feign-core-9.5.0.jar:?]    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:133) ~[feign-core-9.5.0.jar:?]    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76) ~[feign-core-9.5.0.jar:?]    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103) ~[feign-core-9.5.0.jar:?]

org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [channel.domain.ChannelResponse] and content type [text/json;charset=UTF-8]

可以看到返回的类型为[ChannelFeign#formRecog] content-type: text/json;charset=UTF-8

错误原因

接口返回为JSON格式数据但却将数据表示为了[text/json]导致Feign没有采用JSON解析器来解析,从而无法将响应数据转化为对应的POJO对象;

源码分析

feign客户端发送请求入口函数invoke()

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if ("equals".equals(method.getName())) {

try {

Object

otherHandler =

args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;

return equals(otherHandler);

} catch (IllegalArgumentException e) {

return false;

}

} else if ("hashCode".equals(method.getName())) {

return hashCode();

} else if ("toString".equals(method.getName())) {

return toString();

}

// 分发请求

return dispatch.get(method).invoke(args);

}

decode()返回请求的解码函数

Object decode(Response response) throws Throwable {

try {

return decoder.decode(response, metadata.returnType());

} catch (FeignException e) {

throw e;

} catch (RuntimeException e) {

throw new DecodeException(e.getMessage(), e);

}

}

进入decode.decode(),提取数据

@Override

@SuppressWarnings({"unchecked", "rawtypes", "resource"})

public T extractData(ClientHttpResponse response) throws IOException {

MessageBodyClientHttpResponseWrapper responseWrapper = new MessageBodyClientHttpResponseWrapper(response);

if (!responseWrapper.hasMessageBody() || responseWrapper.hasEmptyMessageBody()) {

return null;

}

MediaType contentType = getContentType(responseWrapper);

for (HttpMessageConverter> messageConverter : this.messageConverters) {

if (messageConverter instanceof GenericHttpMessageConverter) {

GenericHttpMessageConverter> genericMessageConverter =

(GenericHttpMessageConverter>) messageConverter;

if (genericMessageConverter.canRead(this.responseType, null, contentType)) {

if (logger.isDebugEnabled()) {

logger.debug("Reading [" + this.responseType + "] as \"" +

contentType + "\" using [" + messageConverter + "]");

}

return (T) genericMessageConverter.read(this.responseType, null, responseWrapper);

}

}

if (this.responseClass != null) {

if (messageConverter.canRead(this.responseClass, contentType)) {

if (logger.isDebugEnabled()) {

logger.debug("Reading [" + this.responseClass.getName() + "] as \"" +

contentType + "\" using [" + messageConverter + "]");

}

return (T) messageConverter.read((Class) this.responseClass, responseWrapper);

}

}

}

throw new RestClientException("Could not extract response: no suitable HttpMessageConverter found " +

"for response type [" + this.responseType + "] and content type [" + contentType + "]");

}

进入genericMessageConverter.canRead(this.responseType, null, contentType)

protected boolean canRead(MediaType mediaType) {

if (mediaType == null) {

return true;

}

for (MediaType supportedMediaType : getSupportedMediaTypes()) {

if (supportedMediaType.includes(mediaType)) {

return true;

}

}

return false;

}

通过断点发现mediaType为接口返回的content-type:text/json类型。而supportedMediaType为application/json,所以返回false,找不到合适的转换器。

解决方案一

替代Feign的解码器,使json解析器同时解析[text/plain]的数据

// 创建一个新的转换器 解析微信的 [text/plain]

public class WxMessageConverter extends MappingJackson2HttpMessageConverter {

public WxMessageConverter(){

List mediaTypes = new ArrayList<>();

mediaTypes.add(MediaType.TEXT_PLAIN);

setSupportedMediaTypes(mediaTypes);

}

}

注入新的Decoder Feign将自动 替换

// 解决微信返回参数为[text/plain] 无法转化为json

@Bean

public Decoder feignDecoder(){

WxMessageConverter wxConverter = new WxMessageConverter();

ObjectFactory objectFactory = () -> new HttpMessageConverters(wxConverter);

return new SpringDecoder(objectFactory);

}

解决方案二

对返回的json字符串使用fastjosn转换

String result = channelFeign.formRecogTest(channelRequest);

ChannelResponse hello = JSONObject.parseObject(result,

new TypeReference>() {

});

错误2

发送请求时对象转换json会自动将属性的首字母小写

解决方法:

//@Data

public class ChannelRequest {

//@JSONField(name="Header")

@JsonProperty

private ChannelReqHead Header;

//@JSONField(name="Body")

@JsonProperty

private ChannelReqBody Body;

// 如果get方法上不加JsonIgnore,jason化时小写header也会出现

@JsonIgnore

public ChannelReqHead getHeader() {

return Header;

}

@JsonIgnore

public void setHeader(ChannelReqHead header) {

Header = header;

}

@JsonIgnore

public ChannelReqBody getBody() {

return Body;

}

@JsonIgnore

public void setBody(ChannelReqBody body) {

Body = body;

}

}

使用jsonField不起作用,不使用jsonIgnore会生成大写和小写

如:{“Header”:xxx,"header":xxx}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:关于feign.codec.DecodeException异常的解决方案
下一篇:Java Stream函数式编程管道流结果处理
相关文章

 发表评论

暂时没有评论,来抢沙发吧~