微服系列之Feign使用HttpClient和OkHttp网络请求框架

Feign实现了远程调用,底层默认使用的是HttpURLConnection网络请求框架

那Feign支不支持其他的网络请求框架呢,答案那是肯定的,Feign还支持HttpClient和OkHttp,

那Feign中怎么将请求框架切换到另外两种呢,首先我们先查看一下Feign配置类


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

我们着重看一下方法名为:HttpClientFeignLoadBalancedConfiguration,从代码上来看@ConditionalOnClass({ApacheHttpClient.class})这个注解可以知道,只需要在pom文件中加上HttpClient的ClassPath即可,另外需要在配置文件application.yml或application.properties中配置上feign.httpclinet.enabled=true即可,从注解@ConditionalOnProperty注解可知,这个配置可以不写,因为在默认的情况下就是true,接下来实现:

在工程pom文件中添加feign-httpclient的依赖,Feign就会采用HttpClient作为网络请求框架,而不是默认的HttpURLConnection,依赖如下:

<dependency> 
        <groupId>com.netflix.feign</groupId> 
        <artifactid>feign-httpclient</artifactid> 
        <version>RELEASE</version> 
</dependency> 

同理,如果想使用Okhttp作为网络请求框架,只需要在pom中添加feign-okhttp的依赖即可,依赖如下:

<dependency> 
        <groupid>com.netflix.feign</groupid> 
        <artifactid>feign-okhttp</artifactid> 
        <version>RELEASE</version> 
</dependency>