feignを使用してhttpリクエスト解析エラーを送信
7213 ワード
エラーは次のとおりです.
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()
decode()は要求の復号関数を返す
decodeに入ります.decode()、データの抽出
GenericMessageConverterに入ります.canRead(this.responseType, null, contentType)
ブレークポイントからmediaTypeがインタフェースから返されるcontent-type:text/jsonタイプであることが分かった.一方、supportedMediaTypeはアプリケーション/jsonなのでfalseに戻り、適切なコンバータが見つかりません.
ソリューション1
Feignのデコーダの代わりにjson解析器に[text/plain]のデータを同時に解析させる
参考:Buynow_Zhaoブログhttps://blog.csdn.net/a610786189/article/details/80508353?utm_source=copy
ソリューション2
返されるjson文字列にfastjosn変換を使用
エラー2
リクエスト送信時にオブジェクト変換jsonは自動的にプロパティの頭文字を小文字にします
解決方法:
jsonFieldを使っても機能しないので、
jsonIgnoreを使用しないと大文字と小文字が生成されます
例:{"Header":xxx,"header":xxx}
-----
[ChannelFeign#formRecog] ---> END HTTP (304117-byte body)
[ChannelFeign#formRecog] ] and content type [text/json;charset=UTF-8]] with root cause
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]
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はアプリケーション/jsonなのでfalseに戻り、適切なコンバータが見つかりません.
ソリューション1
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);
}
参考:Buynow_Zhaoブログhttps://blog.csdn.net/a610786189/article/details/80508353?utm_source=copy
ソリューション2
返される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}