Как настроить пользовательский объект Jackson ObjectMapper с помощью Spring Cloud Netflix Feign

Я столкнулся со сценарием, в котором мне нужно определить одноразовый @FeignClient для стороннего API. В этом клиенте я хотел бы использовать пользовательский объект Jackson ObjectMapper, который отличается от моего @Primary. Я знаю, что можно переопределить значения по умолчанию для конфигурации Spring, однако мне не ясно, как просто переопределить ObjectMapper только этим конкретным клиентом.


person Newbie    schedule 07.03.2016    source источник
comment
Вы пробовали это, и это не работает? Spring Cloud Feign использует тот же объект HttpMessageConverters, что и Spring MVC. Настройка его обычным способом Spring Boot должна «просто работать» (хотя я сам этого не пробовал). docs.spring .io/spring-boot/docs/current-SNAPSHOT/reference/   -  person spencergibb    schedule 08.03.2016
comment
@spencergibb Я могу переопределить ObjectMapper, и он правильно используется всеми контроллерами Spring MVC и всеми клиентами Feign. Однако мне нужен конкретный фиктивный клиент из многих, чтобы использовать другой сопоставитель объектов, отличный от того, который настроен по умолчанию. Я не уверен, как даже начать, чтобы сделать эту работу.   -  person Newbie    schedule 08.03.2016
comment
Вам нужно будет создать bean-компонент SpringDecoder, используя ссылку на документ, опубликованную ранее, и возиться с ней там.   -  person spencergibb    schedule 08.03.2016
comment
@spencergibb, я приступил к работе, как показано в ответе ниже. Спасибо за помощь.   -  person Newbie    schedule 09.03.2016


Ответы (3)


Согласно документации, вы можете предоставить собственный декодер для своего клиента 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;
    }
}
person Newbie    schedule 09.03.2016
comment
у меня работало просто с return new JacksonDecoder(customObjectMapper()); - person leveluptor; 19.10.2017

следуйте ответу @NewBie, я могу дать лучший...

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

если вы хотите использовать преобразователь сообщений jackson в клиенте feign, используйте JacksonDecoder, потому что SpringDecoder увеличит среднюю задержку вызова feignclient в производстве.

    <!-- feign-jackson decoder -->
    <dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-jackson</artifactId>
      <version>10.1.0</version>
    </dependency>
person suiwenfeng    schedule 08.07.2019
comment
Какая зависимость? А версия? Можете ли вы показать запись pom.xml для этого? - person rios0rios0; 08.04.2021
comment
Можете ли вы количественно оценить увеличение задержки в процентах, мс или что-то в этом роде? Я хотел бы ориентир для того, насколько это имеет значение. Хотя выглядит чистым. - person James Wynn; 07.07.2021
comment
По моему мнению, значительно улучшилось, в среднем 10 мс улучшилось для 8k запросов в секунду в производстве. - person suiwenfeng; 08.07.2021

Определите пользовательский декодер, как показано ниже, с аннотацией @Configuration и установите в качестве параметра для фиктивного клиентского интерфейса 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);
        };
    }
}
person Ömer    schedule 04.08.2021