簡體   English   中英

將 OkHttp 自定義攔截器添加到 Feign 客戶端

[英]Adding OkHttp custom interceptor to Feign client

我在為@FeignClient bean 設置全局OkHttp攔截器時遇到問題。 我沒有遇到任何錯誤,但是攔截器被忽略了。

我的理解是 Spring Cloud 的自動配置應該選擇我聲明的OkHttpClient.Builder bean 並使用它來創建底層OkHttpClient實例,但我可能對此有誤。

以下是我的 Spring 應用程序的相關部分:

@SpringBootApplication
@EnableFeignClients(defaultConfiguration = FeignConfig.class)    
@EnableCircuitBreaker
public class MyApp {

    public static void main(String[] args) {
        SpringApplication.run(MyApp.class);
    }
}

@Configuration
public class FeignConfig {

    @Bean
    public MyInterceptor myInterceptor() {
        return new MyInterceptor();
    }

    @Bean
    public OkHttpClient.Builder okHttpClientBuilder(MyInterceptor interceptor) {
        return new OkHttpClient.Builder().addInterceptor(interceptor);
    }
}

public class MyInterceptor implements okhttp3.Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {

        Request request = chain.request();

        System.out.println("Hey there, this is my request: " + request);

        Response response = chain.proceed(request);

        System.out.println("Hey there, this is my response: " + response);

        return response;
    }

}

上面的intercept方法永遠不會被調用。 我需要MyInterceptor成為 Spring bean,因為我需要向它注入其他依賴項。


@FeignClient(name = "myClient", fallback = MyClientFallback.class)
public interface MyClient {

    // method declarations
}

@Component
public class MyClientFallback implements MyClient {

    // method fallback implementations
}

這是我的application.properties文件的相關部分:

feign.hystrix.enabled = true
feign.okhttp.enabled = true

ribbon.eureka.enabled = false
ribbon.eager-load.enabled = true
ribbon.eager-load.clients = myClient

myClient.ribbon.listOfServers = <IP_LIST>
myClient.ribbon.ServerListRefreshInterval = 10000

正如您從上面聲明的屬性中看到的,我沒有使用 Eureka,而是使用 Ribbon 來平衡我的休息客戶端。 我還使用 Hystrix 來啟用回退響應,並且我已將feign.okhttp.enabled屬性設置為true


以下是有關依賴項配置和版本的信息...

Spring Boot 版本是2.0.3.RELEASE ,Spring Cloud 版本是Finchley.SR1 ,而OkHttp版本是3.11.0

在我的pom.xml文件中,我有這個spring-cloud-dependencies配置:

<dependencyManagement>
    <dependencies>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        ...

    </dependencies>
</dependencyManagement>

我還包括以下 Spring Boot 和 Spring Cloud 依賴項,以及OkHttp依賴項:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.3.RELEASE</version>
</parent>

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>

    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>3.11.0</version>
    </dependency>

    ...

</dependencies>

您應該提供文檔中所述OkHttpClient bean:

OkHttpClient 和 ApacheHttpClient feign 客戶端可以通過分別將 feign.okhttp.enabled 或 feign.httpclient.enabled 設置為 true 並將它們放在類路徑上來使用。 您可以通過在使用 Apache 時提供 ClosableHttpClient 或使用 OK HTTP 時提供 OkHttpClient 的 bean 來自定義使用的 HTTP 客戶端。

https://github.com/OpenFeign/feign/blob/master/okhttp/src/main/java/feign/okhttp/OkHttpClient.java

解決方案是讓 Spring 自動配置完成它的工作。

為了實現這一點,必須從pom.xml文件中刪除以下依賴項:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.11.0</version>
</dependency>

並且必須手動包含以下一項:

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

完成此操作后,使用提供的配置,一切都會按預期工作。

解決方案是使用 OkHttpClient。 添加 pom.xml 依賴項:

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

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

並配置一個bean:

@Configuration
public class FeignConfiguration {

  @Bean
  public OkHttpClient client() {
    return new OkHttpClient();
  }
}

說明:對於 401、407 和其他一些 HTTP 狀態響應,默認情況下 Open Feign 中使用的 HTTP 客戶端將主體替換為null

來自 OpenFeign :目前在 feign.Default 客戶端中啟用了流模式。 您可以在sun.net.www.protocol.http.HttpURLConnection看到以下代碼行:

if (respCode == HTTP_UNAUTHORIZED) { 
  if (streaming()) { 
    disconnectInternal(); 
    throw new HttpRetryException (RETRY_MSG2, HTTP_UNAUTHORIZED); 
  }
}

因此,如果啟用了流並且您有401 HTTP 響應代碼,您將獲得空的 errorStream,因為沒有初始化。 feign 客戶端會嘗試獲取 errorStream 作為主體,因為有一個檢查

if (status >= 400) { 
  stream = connection.getErrorStream(); 
} else { stream = connection.getInputStream(); }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM