一、概述
A项目调用B项目时,B项目返回固定的结构{"code":"","msg":"","data",""}。每次调用后A项目都需要手动拆包获取data中的数据,非常麻烦,所以需要在openfeign获取返回结果后自动获取data中的数据并返回。
二、问题描述
1、在openfeign接口的@FeignClient注解中指定了configuration = {UnDataFormatConfig.class}
2、UnDataFormatConfig代码如下:
@Slf4j
@Configuration
public class UnDataFormatConfig {
@Bean
public OkHttpClient.Builder okHttpClientBuilder() {
return new OkHttpClient.Builder().addInterceptor(new FeignOkHttpClientResponseInterceptor());
}
/**
* okHttp响应拦截器
*/
public static class FeignOkHttpClientResponseInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Response response = chain.proceed(originalRequest);
MediaType mediaType = response.body().contentType();
String content = response.body().string();
log.info("openfeign返回结果==================={}", content);
ObjectMapper objectMapper = new ObjectMapper();
HashMap baseResult = objectMapper.readValue(content, HashMap.class);
if ("200".equals(baseResult.get("code"))) {
String noformatKey = originalRequest.header(Constant.HEADER_NOFORMAT_KEY);
if (StringUtils.isEmpty(noformatKey) || Constant.HEADER_NOFORMAT_TRUE.equals(noformatKey)) {
// 不传或者解析content
Object data = baseResult.get("data");
if (data instanceof String) {
content = String.valueOf(data);
} else {
content = objectMapper.writeValueAsString(data);
}
}
} else {
AssertUtil.throwErrorMessage(new CodeMsg(String.valueOf(baseResult.get("code")), String.valueOf(baseResult.get("msg"))));
}
//生成新的response返回,网络请求的response如果取出之后,直接返回将会抛出异常
return response.newBuilder()
.body(ResponseBody.create(mediaType, content))
.build();
}
}
}
3、项目项目启动后调用openfeign接口发现此返回的结果并没有自动拆包,打断点后发现配置代码没有运行。
三、解决方案
1、经排查发现上述代码中Interceptor是okhttp包下的类,加上openfeign支持httpclient和okhttp两种方式发起调用,默认是httpclient。于是猜想可能是因为没有手动将httpclient切换为okhttp的原因。
2、于是在yml中添加如下配置,发现生效了
feign:
httpclient:
enabled: false
okhttp:
enabled: true