背景
最近使用Spring Cloud OpenFeign組件,訪問第三方開源系統,對方系統的字段都是下划線的,而建模的時候,全部按照駝峰方式。
如果全部JsonProperty方式,每一個Model類,每一個字段都要處理一遍非常麻煩。
更好的辦法(實測可用)
public class FeignClientEncoder extends SpringEncoder {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
objectMapper.disable(JsonGenerator.Feature.IGNORE_UNKNOWN);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
}
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);
template.body(objectMapper.writeValueAsString(object));
} catch (Exception ex) {
throw new CdException(CdExceptionEnum.SYSTEM_ERROR);
}
}
public static class FeignClientDecoder extends SpringDecoder {
public FeignClientDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
super(messageConverters);
}
@Override
public Object decode(Response response, Type type) throws IOException, FeignException {
//FIX:Feign默認Body返回的是String,換成ApacheHttpClient以后是一個匿名類
String result = IOUtils.toString(response.body().asInputStream());
if (type instanceof Class && StringUtils.isNoneBlank(result)) {
Response build = Response.builder()
.body(new ObjectMapper().writeValueAsString(
objectMapper.readValue(result,
(Class<? extends Object>) type)),
StandardCharsets.UTF_8)
.headers(response.headers())
.reason(response.reason())
.status(response.status())
.request(response.request())
.build();
//思考:這里是不是可以直接返回,因為使用這個Decoder的FeignClient應該是某個系統專用的。
//return objectMapper.readValue(result, (Class<? extends Object>) type));
return super.decode(build, type);
}
return super.decode(response, type);
}
}
}
一個小坑
在使用HTTP PATCH請求的時候,發現Feign不識別PATCH請求,則需要添加Feign-HttpClient依賴。
<!--HTTP PATCH SUPPORT-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
在更換HttpClient之后,發現下方這樣寫是不正確的。我參考了其他人的博客,發現這樣寫確實不對。正確的寫法應該是IOUtils.toString(response.body().asInputStream());
@Override
public Object decode(Response response, Type type) throws IOException, FeignException {
//FIX:Feign默認Body返回的是String,換成ApacheHttpClient以后是一個匿名類,而不是String正文。
String result = response.body().toString();