Как декодировать ответ JSon с помощью настраиваемого клиента Feign?

В моем приложении я должен узнать из списка адреса серверов, которые работают. Решение, которое я нашел, - это вызвать конечную точку работоспособности из Spring-Boot Actuator для каждого из них. Ответ JSon:

{
    "status": "UP"
}

В других частях приложения я использую клиентов Feign из Spring-Cloud, определенные с помощью аннотации @FeignClient, которая отлично работает:

    @FeignClient(
            name = "tokenProxy",
            url = "${host}:${port}"
    )

К сожалению, такая конфигурация не позволяет повторно использовать одного и того же клиента для вызова одной и той же конечной точки на разных адресах. Поэтому я должен определить своего собственного клиента (если есть другое решение, не стесняйтесь сообщить мне!):

    @GetMapping(
      value = "/servers"
    )
    public Server discover() {
      MyClient myClient = Feign.builder()
        .target(
          Target.EmptyTarget.create(
            MyClient.class
          )
        );

      return myClient.internalPing(URI.create("http://localhost:8090"));
    }

    interface MyClient {
        @RequestLine("GET /actuator/health")
        Server internalPing(URI baseUrl);
    }

    class Server {
        private final String status;

        @JsonCreator
        public Server(@JsonProperty("status") String status) {
            this.status = status;
        }

        public String getStatus() {
            return status;
        }
    }

Когда я вызываю конечную точку /servers, я получаю следующую ошибку, указывающую, что мой пользовательский клиент Feign не настроен на соответствующий декодер:

feign.codec.DecodeException: class com.xxx.web.Server is not a type supported by this decoder.
    at feign.codec.StringDecoder.decode(StringDecoder.java:34) ~[feign-core-10.10.1.jar:na]
    at feign.codec.Decoder$Default.decode(Decoder.java:92) ~[feign-core-10.10.1.jar:na]
    at feign.AsyncResponseHandler.decode(AsyncResponseHandler.java:115) ~[feign-core-10.10.1.jar:na]
    at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:87) ~[feign-core-10.10.1.jar:na]
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:138) ~[feign-core-10.10.1.jar:na]

Думаю, мне следует использовать JacksonDecoder, но я не могу найти его в своих зависимостях от Spring-Cloud Hoxton.SR5:

      <dependencies>
    ...
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    ...
      </dependencies>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Hoxton.SR5</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
  </dependencyManagement>

Может ли кто-нибудь помочь мне, предложив лучшее решение для моих нужд или объяснив, как правильно настраивать собственные клиенты Feign?

заранее спасибо


person Ticker    schedule 06.06.2020    source источник


Ответы (2)


Фактически, библиотека, которая включает декодер и кодировщик Джексона, не загружалась по умолчанию при использовании зависимостей Spring-Cloud. Чтобы решить эту проблему, мне просто пришлось добавить в мой pom.xml файл следующее:

<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-jackson</artifactId>
</dependency>
person Ticker    schedule 08.06.2020

Другой способ - аннотировать класс с помощью @Import(FeignClientsConfiguration.class), что является конфигурацией по умолчанию, предоставляемой Spring Cloud Netflix.

Тогда становится легко внедрить и кодировщик, и декодер при создании клиента Feign:

    @Import(FeignClientsConfiguration.class)
    @Configuration
    public class MyConfiguration {
    (...)
    Myclient myClient (Decoder feignDecoder, Encoder feignEncoder) {
    return Feign.builder()
        .decoder( feignDecoder )
        .encoder( feignEncoder )
        .target(
          Target.EmptyTarget.create(
            MyClient.class
          )
        );
    }

В классе конфигурации есть два разных определенных кодировщика (страничные или нет), поэтому обратите внимание на то, чтобы четко определить, какой из них вы хотите, по его имени или квалификатору.

person Ticker    schedule 09.06.2020