spring-cloud feigin发送请求参数需要进行驼峰和下划线的转换
背景
项目改造为sping-cloud, 依赖别人的feign(fei-api)服务,使用feign发送请求的时候,对方接口参数和返回值都是下划线类型的,所以需要把请求参数和返回值转换为驼峰类型
解决过程
1:使用spring的spring.jackson.property-naming-strategy 配置,
引起的问题,自己的接口和返回值会将驼峰转换为下划线,所以忽略
2:因为这边的feign-api中的参数都是对象,所以新建一个参数的子类加上@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)注解,传参数的时候使用子类,完美解决,但是新建子类返回值下划线/驼峰转换失败
解决方案
为@EnableFeignClients加上encode和decode
@EnableFeignClients(defaultConfiguration = {FeignClientEncoder.class,FeignClientEncoder.FeignClientDecoder.class})
public class FeignClientEncoder extends SpringEncoder {
public FeignClientEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
super(messageConverters);
}
@Override
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
try {
super.encode(object, bodyType, template);
final String s = JSON.toJSONString(object);
final Object jsonObject = JSON.parse(s);
convertToCamelCase(jsonObject);
template.body(JSON.toJSONString(jsonObject));
} catch (Exception ex) {
}
System.out.println();
}
public static class FeignClientDecoder extends SpringDecoder {
public FeignClientDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
super(messageConverters);
}
@Override
public Object decode(Response response, Type type) throws IOException, FeignException {
final Response.Body body = response.body();
final String bodyClassName = body.getClass().getName();
//Response.ByteArrayBody feign.Response$InputStreamBody feign.Response$ByteArrayBody
//因为ByteArrayBody是private 所以不能instance of
if (Objects.equals(bodyClassName, "feign.Response$ByteArrayBody") || Objects.equals(bodyClassName, "feign.Response$InputStreamBody")) {
String result;
if (Objects.equals(bodyClassName, "feign.Response$ByteArrayBody")) {
result = body.toString();
} else {
byte[] bodyData = Util.toByteArray(body.asInputStream());
result = Util.decodeOrDefault(bodyData, UTF_8, "Binary data");
}
final Response.Builder respBuild = Response.builder()
.headers(response.headers())
.reason(response.reason())
.status(response.status())
.request(response.request());
if (StringUtils.isNoneBlank(result) && JSONUtil.isJson(result)) {
final Object jsonObject = JSON.parse(result);
convertToUnderline(jsonObject);
respBuild.body(JSON.toJSONString(jsonObject), Charset.defaultCharset());
} else {
respBuild.body(result, Charset.defaultCharset());
}
return super.decode(respBuild.build(), type);
}
return super.decode(response, type);
}
}
public final static void convertToUnderline(Object json) {
if (json instanceof JSONArray) {
JSONArray arr = (JSONArray) json;
for (Object obj : arr) {
convertToUnderline(obj);
}
} else if (json instanceof JSONObject) {
JSONObject jo = (JSONObject) json;
Set<String> keys = jo.keySet();
String[] array = keys.toArray(new String[keys.size()]);
for (String key : array) {
Object value = jo.get(key);
final String underLineKey = StrUtil.toUnderlineCase(key);
jo.remove(key);
jo.put(underLineKey, value);
convertToUnderline(value);
}
}
}
public final static void convertToCamelCase(Object json) {
if (json instanceof JSONArray) {
JSONArray arr = (JSONArray) json;
for (Object obj : arr) {
convertToCamelCase(obj);
}
} else if (json instanceof JSONObject) {
JSONObject jo = (JSONObject) json;
Set<String> keys = jo.keySet();
String[] array = keys.toArray(new String[keys.size()]);
for (String key : array) {
Object value = jo.get(key);
final String underLineKey = StrUtil.toCamelCase(key);
jo.remove(key);
jo.put(underLineKey, value);
convertToCamelCase(value);
}
}
}
}