OpenFeign用自定义Decoder解决JSON下划线转驼峰的问题

背景

最近使用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();
posted @ 2020-09-28 18:01  一杯半盏  阅读(4567)  评论(0编辑  收藏  举报