【问题标题】:How to set custom Jackson ObjectMapper with Spring Cloud Netflix Feign如何使用 Spring Cloud Netflix Feign 设置自定义 Jackson ObjectMapper
【发布时间】: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,我开始工作,如下面的答案所示。谢谢你的帮助。

标签: spring spring-mvc spring-cloud feign spring-cloud-netflix


【解决方案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);
            };
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-02-01
      • 2017-11-07
      • 2021-10-24
      • 2017-01-20
      • 2015-09-26
      • 1970-01-01
      • 2016-03-31
      • 2011-07-12
      • 2016-12-17
      相关资源
      最近更新 更多