在Feign中,Client是一个非常重要的组件,Feign最终发送Request请求以及接收Response响应都是由Client组件完成的。Client在Feign源码中是一个接口,在默认的情况下,Client的实现类是Client。Default,Client.Default是由HttpURLConnection来实现网络请求的。另外Client还支持HttpClient和OkhHttp来进行网络请求。
首先查看FeignRibbonClient的自动配置类FeignRibbonClientutoConfiguration,该 类在工程启动时注入一些Bean,其中注入了一个BeanName为feignClient的Client类型的Bean,代码如下
@ConditionalOnClass({ILoadBalancer.class, Feign.class})
@Configuration
@AutoConfigureBefore({FeignAutoConfiguration.class})
public class FeignRibbonClientAutoConfiguration {
public FeignRibbonClientAutoConfiguration() {
}
@Bean
@Primary
@ConditionalOnMissingClass({"org.springframework.retry.support.RetryTemplate"})
public CachingSpringLoadBalancerFactory cachingLBClientFactory(SpringClientFactory factory) {
return new CachingSpringLoadBalancerFactory(factory);
}
@Bean
@Primary
@ConditionalOnClass(
name = {"org.springframework.retry.support.RetryTemplate"}
)
public CachingSpringLoadBalancerFactory retryabeCachingLBClientFactory(SpringClientFactory factory, LoadBalancedRetryPolicyFactory retryPolicyFactory) {
return new CachingSpringLoadBalancerFactory(factory, retryPolicyFactory, true);
}
@Bean
@ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
return new LoadBalancerFeignClient(new Default((SSLSocketFactory)null, (HostnameVerifier)null), cachingFactory, clientFactory);
}
@Bean
@ConditionalOnMissingBean
public Options feignRequestOptions() {
return LoadBalancerFeignClient.DEFAULT_OPTIONS;
}
@Configuration
@ConditionalOnClass({OkHttpClient.class})
@ConditionalOnProperty(
value = {"feign.okhttp.enabled"},
matchIfMissing = true
)
protected static class OkHttpFeignLoadBalancedConfiguration {
@Autowired(
required = false
)
private okhttp3.OkHttpClient okHttpClient;
protected OkHttpFeignLoadBalancedConfiguration() {
}
@Bean
@ConditionalOnMissingBean({Client.class})
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
OkHttpClient delegate;
if (this.okHttpClient != null) {
delegate = new OkHttpClient(this.okHttpClient);
} else {
delegate = new OkHttpClient();
}
return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
}
}
@Configuration
@ConditionalOnClass({ApacheHttpClient.class})
@ConditionalOnProperty(
value = {"feign.httpclient.enabled"},
matchIfMissing = true
)
protected static class HttpClientFeignLoadBalancedConfiguration {
@Autowired(
required = false
)
private HttpClient httpClient;
protected HttpClientFeignLoadBalancedConfiguration() {
}
@Bean
@ConditionalOnMissingBean({Client.class})
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
ApacheHttpClient delegate;
if (this.httpClient != null) {
delegate = new ApacheHttpClient(this.httpClient);
} else {
delegate = new ApacheHttpClient();
}
return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
}
}
}
在缺省配置BeanName为FeignClient的Bean的情况下,会自动注入Client.Default这个对象,跟踪client.default源码,client.default使用的网络请求框架为HttpURLConnection,代码如下:
public Response execute(Request request, Options options) throws IOException {
HttpURLConnection connection = this.convertAndSend(request, options);
return this.convertResponse(connection).toBuilder().request(request).build();
}
那么,如何在Feign中使用HttpClient的网络请求框架呢?下面继续查看FeignRibbonClientAutoConfiguration的源码:
protected static class OkHttpFeignLoadBalancedConfiguration {
@Autowired(
required = false
)
private okhttp3.OkHttpClient okHttpClient;
protected OkHttpFeignLoadBalancedConfiguration() {
}
@Bean
@ConditionalOnMissingBean({Client.class})
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
OkHttpClient delegate;
if (this.okHttpClient != null) {
delegate = new OkHttpClient(this.okHttpClient);
} else {
delegate = new OkHttpClient();
}
return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
}
}
从代码@ConditionalOnClass(ApacheHttpClient.class)注解可知道,只需要在pom文件加上HttpClient的Classpath即可。另外需要在配置文件application.yml中配置feign.httpclient.enabled为true,从@ConditionalOnProperty注解可知,这个配置可以不写,因为在默认的情况下就为true。
在工程的pom文件加上feign-httpclient的依赖,Feign就会采用HttpClient作为网络请求框架,而不是默认的HttpURLConnection。代码如下“
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>RELEASE</version>
</dependency>
同理,如果想要Feign中使用Okhttp作为网络请求框架,则只需要在pom文件上加上feign-okhttp的依赖,代码如下:
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>RELEASE</version>
</dependency>