我在为OkHttp
bean设置全局@FeignClient
拦截器时遇到问题。我没有遇到任何错误,但是拦截器被忽略了。
我的理解是Spring Cloud的自动配置应该选择我声明的OkHttpClient.Builder
bean,并使用它来创建基础的OkHttpClient
实例,但是我对此可能是错的。
以下是我的Spring应用程序的相关部分:
@SpringBootApplication
@EnableFeignClients(defaultConfiguration = FeignConfig.class)
@EnableCircuitBreaker
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(GeoSigoStarter.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
。
以下是有关dependecies配置和版本的信息...
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>
答案 0 :(得分:2)
您应将OkHttpClient
bean作为stated in the doc:
可以通过将feign.okhttp.enabled或feign.httpclient.enabled分别设置为true并将它们放在类路径中来使用OkHttpClient和ApacheHttpClient feign客户端。您可以通过提供使用Apache时的ClosableHttpClient Bean或使用OK HTTP的OkHttpClient来定制HTTP客户端。
https://github.com/OpenFeign/feign/blob/master/okhttp/src/main/java/feign/okhttp/OkHttpClient.java
答案 1 :(得分:1)
解决方案是让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>
完成此操作后,所提供的配置将按预期完成所有操作。
答案 2 :(得分:0)
解决方案是使用 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
。
From 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(); }