简体   繁体   English

如何使用自定义 Feign 客户端解码 JSon 响应?

[英]How to decode JSon response with custom Feign client?

In my application, I have to know, from a list a server addresses, which are up.在我的应用程序中,我必须从列表中知道一个服务器地址,这些地址已启动。 The solution I found is to call health endpoint from Spring-Boot Actuator, for each of them.我找到的解决方案是从 Spring-Boot 执行器中为每个执行器调用健康端点。 The JSon reponse is: JSon 响应为:

{
    "status": "UP"
}

In other parts of the application, I use Feign clients from Spring-Cloud defined with the @FeignClient annotation, which works perfectly:在应用程序的其他部分,我使用来自 Spring-Cloud 的 Feign 客户端,它使用@FeignClient注释定义,效果很好:

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

Unfortunately this kind of configuration doesn't allow to re-use the same client to call the same endpoint on different addresses.不幸的是,这种配置不允许重复使用同一个客户端来调用不同地址上的同一个端点。 So I have to define my own custom client (If there is another solution, do not hesitate to tell me: ):所以我必须定义自己的自定义客户端(如果有其他解决方案,请随时告诉我:):

    @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;
        }
    }

When I call the endpoint /servers , I get the following error, indicating that my custom Feign client isn't confgured with the appropriate decoder:当我调用端点/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]

I guess i should use JacksonDecoder, but I cannot find it in my dependencies from Spring-Cloud Hoxton.SR5 :我想我应该使用 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>

Could someone help me, either with a better solution for my need or a explanation on how to properly configure custom Feign clients?有人可以帮助我,为我的需要提供更好的解决方案,或者解释如何正确配置自定义 Feign 客户端?

Thanks in advance提前致谢

In fact, the library which includes Jackson decoder and encoder was not loaded by default when using spring-cloud dependencies.事实上,使用 spring-cloud 依赖时,默认没有加载包含 Jackson 解码器和编码器的库。 To fix the issue I simply had to add the following to my pom.xml file:要解决此问题,我只需将以下内容添加到我的pom.xml文件中:

<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-jackson</artifactId>
</dependency>

Another way could be annotating the class with @Import(FeignClientsConfiguration.class) which is the default configuration provided by Spring Cloud Netflix.另一种方法是使用 @Import @Import(FeignClientsConfiguration.class)注释 class,这是 Spring Cloud Netflix 提供的默认配置。

Then it becomes easy to inject both Encoder and Decoder when creating the Feign client:那么在创建 Feign 客户端的时候注入 Encoder 和 Decoder 就变得很容易了:

    @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
          )
        );
    }

There are two different defined encoders in the configuration class (pageable or not), so pay attention to clearly identify which you want, either by its name or a qualifier. class 配置中有两种不同的定义编码器(可分页或不可分页),因此请注意通过名称或限定符清楚地识别您想要的编码器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM