[英]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.