如何使用 Spring Cloud Netflix Feign 设置自定义 Jackson ObjectMapper

Posted

技术标签:

【中文标题】如何使用 Spring Cloud Netflix Feign 设置自定义 Jackson ObjectMapper【英文标题】:How to set custom Jackson ObjectMapper with Spring Cloud Netflix Feign 【发布时间】:2016-06-21 14:28:59 【问题描述】:

我遇到了一种情况,我需要为第三方 API 定义一次性的 @FeignClient。在这个客户端中,我想使用与我的@Primary 不同的自定义 Jackson ObjectMapper。我知道可以覆盖 spring 的 feign 配置默认值,但是我不清楚如何仅通过这个特定的客户端简单地覆盖 ObjectMapper。

【问题讨论】:

你试过了还是不行? Spring Cloud Feign 使用与 Spring MVC 相同的 HttpMessageConverters 对象。以正常的 Spring Boot 方式配置它应该“正常工作”(以为我自己没有尝试过)。 docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/… @spencergibb 我可以覆盖 ObjectMapper,它被所有 Spring MVC 控制器和所有 Feign 客户端正确使用。但是,我需要一个特定的 feign 客户端,在众多客户端中,使用与默认配置的对象映射器不同的对象映射器。我什至不知道如何开始做这项工作。 你必须使用之前发布的文档链接创建一个SpringDecoder bean,然后在那里搞砸。 @spencergibb,我开始工作,如下面的答案所示。谢谢你的帮助。 【参考方案1】:

根据documentation,您可以为您的 Feign 客户端提供自定义解码器,如下所示。

Feign 客户端接口:

@FeignClient(value = "foo", configuration = FooClientConfig.class)
public interface FooClient
    //Your mappings

Feign 客户端自定义配置:

@Configuration
public class FooClientConfig 

    @Bean
    public Decoder feignDecoder() 
        HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
        ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
        return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
    

    public ObjectMapper customObjectMapper()
        ObjectMapper objectMapper = new ObjectMapper();
        //Customize as much as you want
        return objectMapper;
    

【讨论】:

简单地为我工作return new JacksonDecoder(customObjectMapper());【参考方案2】:

关注@NewBie 的回答,我可以给出更好的答案...

  @Bean
  public Decoder feignDecoder() 
    return new JacksonDecoder();
  

如果你想在feign客户端使用jackson消息转换器,请使用JacksonDecoder,因为SpringDecoder会增加feignclient调用的平均延迟在生产中

    <!-- feign-jackson decoder -->
    <dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-jackson</artifactId>
      <version>10.1.0</version>
    </dependency>

【讨论】:

依赖是什么?和版本?您可以为此显示 pom.xml 条目吗? 你能以百分比或毫秒或其他方式量化延迟的增加吗?我想要一个参考点来了解这有多大的不同。不过看起来很干净。 在我的印象中进步很大,生产中 8k qps 平均提高了 10 毫秒。【参考方案3】:

@NewBie 的回答存在严重的性能问题。在new HttpMessageConverters过程中,会执行loadclass,导致大量线程阻塞。如果您使用过此代码,请修改如下:

ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);

改成

HttpMessageConverters httpMessageConverters = new HttpMessageConverters(jacksonConverter);
ObjectFactory<HttpMessageConverters> objectFactory = () -> httpMessageConverters;

你可以使用JMeter和Arthas来重现这个现象,修改后的程序有了很大的改进。

【讨论】:

【参考方案4】:

定义一个自定义解码器如下,注解@Configuration并设置为feign客户端接口的参数configuration = CustomFeignClientConfig.class

@Configuration
public class CustomFeignClientConfig 
    @Bean
    public Decoder feignDecoder() 
        return (response, type) -> 
            String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));
            JavaType javaType = TypeFactory.defaultInstance().constructType(type);
            return new ObjectMapper().readValue( bodyStr, javaType);
        ;
    

【讨论】:

以上是关于如何使用 Spring Cloud Netflix Feign 设置自定义 Jackson ObjectMapper的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AWS Beanstalk 和 Spring Cloud Netflix 在 Docker 容器之间建立连接

Spring Cloud Netflix—使用EurekaClient

Netflix之后,如何用Spring Cloud 新组件构建微服务架构?

Spring Cloud Netflix(网飞)

将 apache kafka 与 Spring Cloud netflix 堆栈一起使用

spring-cloud-starter-eureka-server 和 spring-cloud-starter-netflix-eureka-server的区别