时间:2021-05-20
我就废话不多说了,大家还是直接看代码吧~
<!--web 模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!--排除tomcat依赖 --> <exclusion> <artifactId>spring-boot-starter-tomcat</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!--undertow容器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> <!-- feign-okhttp --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency>注意FeignOkHttpConfig中添加
@Bean public Contract feignContract() { return new feign.Contract.Default(); }feigin请求的@PostMapping @GetMapping等会不受支持
图一,使用默认http
图一,Feign通过jdk中的HttpURLConnection
图二,Feign使用okhttp请求
补充:Feign、httpclient、OkHttp3 结合使用
前面介绍到了常用的Feign客户端实现类,大致如下:
(1) Client.Default类:默认的 feign.Client 客户端实现类,内部使用HttpURLConnnection 完成HTTP URL请求处理;
(2) ApacheHttpClient 类:内部使用 Apache httpclient 开源组件完成HTTP URL请求处理的feign.Client 客户端实现类;
(3) OkHttpClient类:内部使用 OkHttp3 开源组件完成HTTP URL请求处理的feign.Client 客户端实现类。
(4) LoadBalancerFeignClient 类:这是一个特殊的 feign.Client 客户端实现类。内部先使用 Ribbon 负载均衡算法计算server服务器,然后使用包装的 delegate 客户端实例,去完成 HTTP URL请求处理。
Feign 在启动的时候,有两个与feign.Client 客户端实例相关的自动配置类,根据多种条件组合,去创建不同类型的 客户端Spring IOC容器实例。
Feign有两个与Client相关的自动配置类:
(1)org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration
(2)org.springframework.cloud.openfeign.FeignAutoConfiguration
第一个自动配置类,能够配置具有负载均衡能力的FeignClient容器实例;第二自动配置类,只能配置最原始的FeignClient容器实例。
具备负载均衡能力的 FeignClient 容器实例,所对应的类型为 LoadBalancerFeignClient 类型。前面讲到,在SpringCloud中,为了达到高可用,一个微服务至少应该部署两个以上节点,从这个角度来说,LoadBalancerFeignClient 容器实例,已经成为事实上的标配。
事实上,第一个自动配置类 FeignRibbonClientAutoConfiguration,在容器的装配次序上,是优先于第二个自动配置类 FeignAutoConfiguration 的。具体可以参见其源码,节选如下:
import com.netflix.loadbalancer.ILoadBalancer;//….@ConditionalOnClass({ILoadBalancer.class, Feign.class})@Configuration@AutoConfigureBefore({FeignAutoConfiguration.class}) // 本配置类具备优先权@EnableConfigurationProperties({FeignHttpClientProperties.class})@Import({HttpClientFeignLoadBalancedConfiguration.class, //配置:包装ApacheHttpClient实例的负载均衡客户端OkHttpFeignLoadBalancedConfiguration.class, //配置:包装OkHttpClient 实例的负载均衡客户端DefaultFeignLoadBalancedConfiguration.class //配置:包装Client.Default 实例的负载均衡客户端})public class FeignRibbonClientAutoConfiguration { //空的构造器 public FeignRibbonClientAutoConfiguration() { }//….}从源码中可以看到,FeignRibbonClientAutoConfiguration 的自动配置有两个前提条件:
(1)当前的类路径中,存在 ILoadBalancer.class 接口
(2)当前的类路径中,存在 Feign.class 接口
在这里,重点说一下 ILoadBalancer.class 接口,该接口处于 ribbon 的jar包中。如果需要在类路径中导入该jar包,则需要在Maven的pom.xml文件中,增加 ribbon 的相关依赖,具体如下:
<!-- ribbon--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>为了加深大家对客户端负载均衡的理解,这里将 ILoadBalancer.class 接口的两个重要的抽象方法列出来,具体如下:
package com.netflix.loadbalancer;import java.util.List;public interface ILoadBalancer { // 通过负载均衡算法计算server服务器Server chooseServer(Object var1);// 取得全部的服务器List<Server> getAllServers();//…}FeignRibbonClientAutoConfiguration 自动配置类,并没有直接配置LoadBalancerFeignClient 容器实例,而是使用@Import注解,通过导入其他配置类的方式,完成 LoadBalancerFeignClient 客户端容器实例的配置。
分别导入了以下三个自动配置类:
(1) HttpClientFeignLoadBalancedConfiguration.class
该配置类,负责配置一个包装 ApacheHttpClient 实例的 LoadBalancerFeignClient负载均衡客户端。
(2) OkHttpFeignLoadBalancedConfiguration.class
该配置类,负责配置一个包装 OkHttpClient 实例的 LoadBalancerFeignClient负载均衡客户端。
(3) DefaultFeignLoadBalancedConfiguration.class
该配置类,负责配置一个包装 Client.Default 实例的 LoadBalancerFeignClient负载均衡客户端。
首先来看如何配置一个包装 ApacheHttpClient 实例的负载均衡容器实例。这个IOC实例的配置,由 HttpClientFeignLoadBalancedConfiguration 自动配置类完成的,其源码节选如下:
@Configuration@ConditionalOnClass({ApacheHttpClient.class})@ConditionalOnProperty( value = {"feign.httpclient.enabled"}, matchIfMissing = true)class HttpClientFeignLoadBalancedConfiguration { //空的构造器 HttpClientFeignLoadBalancedConfiguration() { } @Bean @ConditionalOnMissingBean({Client.class})public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,SpringClientFactory clientFactory, HttpClient httpClient) { ApacheHttpClient delegate = new ApacheHttpClient(httpClient); return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory); // 进行包装 }//…省略不相干的代码}首先,来看源码中的 feignClient(…)方法,分为两步:
(1)创建一个 ApacheHttpClient 类型的 feign.Client客户端实例,该实例的内部使用 Apache httpclient 开源组件完成HTTP URL请求处理;
(2)创建一个 LoadBalancerFeignClient 负载均衡客户端实例,将 ApacheHttpClient 实例包装起来,然后返回LoadBalancerFeignClient 客户端实例,作为 feign.Client 类型的Spring IOC 容器实例。
然后,再看类 HttpClientFeignLoadBalancedConfiguration 上的两个重要的注解:
(1)@ConditionalOnClass(ApacheHttpClient.class)
(2)@ConditionalOnProperty(value = “feign.httpclient.enabled”, matchIfMissing = true)
这两个条件的含义为:
(1)必须满足 ApacheHttpClient.class 在当前类路径中存在;
(2)必须满足工程配置文件中 feign.httpclient.enabled 配置项的值为 true ;
如果以上两个条件同时满足,则 HttpClientFeignLoadBalancedConfiguration 自动配置工作就会启动。
如何验证呢?
首先在工程配置文件中,将配置项 feign.httpclient.enabled 的值,设置为 false 。
然后,在 HttpClientFeignLoadBalancedConfiguration 的 feignClient(…)方法内的某行打上断点,重新启动项目,注意观察会发现,整个启动过程中,断点没有被命中。
接下来,将配置项 feign.httpclient.enabled 的值设置为 true,再一次启动项目,断点被命中。由此,可以验证 HttpClientFeignLoadBalancedConfiguration 自动配置类被启动。
为了满足 @ConditionalOnClass(ApacheHttpClient.class) 的条件要求,由于ApacheHttpClient类的位置处于feign-httpclient相关的jar包中,所以,需要在pom文件加上 feign-httpclient 以及httpclient 组件相关的 Maven 依赖,具体如下:
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> <version>9.5.1</version> <!--<version>${feign-httpclient.version}</version>--> </dependency><dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>${httpclient.version}</version> </dependency>对于 feign.httpclient.enabled 配置项设置,根据 @ConditionalOnProperty 注解的属性matchIfMissing=true 可知,这个可以不用配置,在默认的情况下就为 true。换句话说,如果不做特别的配置,feign.httpclient.enabled 配置项的值,默认为 true。
接下来,来看如何配置一个包装 OkHttpClient 实例的负载均衡容器实例。这个IOC实例的配置,由 OkHttpFeignLoadBalancedConfiguration 自动配置类完成的,其源码节选如下:
@Configuration@ConditionalOnClass({OkHttpClient.class})@ConditionalOnProperty("feign.okhttp.enabled")class OkHttpFeignLoadBalancedConfiguration { //空的构造器 OkHttpFeignLoadBalancedConfiguration () { } @Bean @ConditionalOnMissingBean({Client.class})public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,SpringClientFactory clientFactory, HttpClient httpClient) { OkHttpClient delegate = new OkHttpClient (httpClient); return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory); // 进行包装 }//…省略不相干的代码}首先,来看源码中的 feignClient(…)方法,分为两步:
(1)创建一个 OkHttpClient 类型的 feign.Client客户端实例,该实例的内部使用 OkHttp3 开源组件完成HTTP URL请求处理;
(2)创建一个 LoadBalancerFeignClient 负载均衡客户端实例,将 OkHttpClient实例包装起来,然后返回LoadBalancerFeignClient 客户端实例,作为 feign.Client 类型的Spring IOC 容器实例。
然后,再看类 OkHttpFeignLoadBalancedConfiguration 上的两个重要的注解:
(1)@ConditionalOnClass(OkHttpClient.class)
(2)@ConditionalOnProperty(“feign.okhttp.enabled”)
这两个条件的含义为:
(1)必须满足 OkHttpClient.class 在当前类路径中存在;
(2)必须满足工程配置文件中 feign.okhttp.enabled 配置项的值为 true 。
如果以上两个条件同时满足,则 OkHttpFeignLoadBalancedConfiguration 自动配置工作就会启动。
为了满足 @ConditionalOnClass(OkHttpClient.class) 的条件要求,由于OkHttpClient.class 类的位置处于 feign-okhttp 相关的jar包中,所以,需要在pom文件加上 feign-okhttp 以及 okhttp3 相关的 Maven 依赖。具体如下:
<!-- OkHttp --><dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId></dependency><!-- feign-okhttp --><dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId></dependency>对于 feign.okhttp.enabled 配置项设置,在默认的情况下就为 false。也就是说,如果需要使用feign-okhttp,则一定需要做特别的配置,在工程配置文件中,加上 feign.okhttp.enabled 配置项的值,并且值必须为 true。
如果需要使用 feign-okhttp,工程配置文件的配置项大致如下:
feign.httpclient.enabled=falsefeign.okhttp.enabled=true最后,来看如何配置一个包装默认Client.Default 客户端实例的负载均衡容器实例。这个IOC实例的配置,由 DefaultFeignLoadBalancedConfiguration 自动配置类所完成的。该配置类,也就是 FeignRibbonClientAutoConfiguration 配置类通过 @import 注解所导入的第3个配置类。
DefaultFeignLoadBalancedConfiguration 的源码节选如下:
package org.springframework.cloud.openfeign.ribbon;//…省略import@Configurationclass DefaultFeignLoadBalancedConfiguration { DefaultFeignLoadBalancedConfiguration() { } @Bean @ConditionalOnMissingBeanpublic Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) { return new LoadBalancerFeignClient(new Default((SSLSocketFactory)null, (HostnameVerifier)null), cachingFactory, clientFactory); }}通过源码可以看出,如果前面的两个配置类的条件没有满足,feign.Client 的 IOC 容器实例没有装配,则:
(1) 创建一个 Client.Default 默认客户端实例,该实例的内部,使用HttpURLConnnection 完成URL请求处理;
(2) 创建一个 LoadBalancerFeignClient 负载均衡客户端实例,将 Client.Default 实例包装起来,然后返回LoadBalancerFeignClient 客户端实例,作为 feign.Client 类型的Spring IOC 容器实例。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
Feign的使用Feign也是网飞开发的,SpringCloud使用Feign非常简单,我下边演示一下:首先服务消费者这边肯定需要一个对应的依赖:compile
事发地原默认的Feign是使用URLConnector进行通信的,当换为okhttp时,直接引入包及配置以下内容根本不生效,还是走原生的。feign:okhtt
在SpringCloud的Feign组件中并不支持文件的传输,会出现这样的错误提示:feign.codec.EncodeException:class[Lorg
使用微服务的时候往往服务之间调用比较麻烦,springcloud提供了Feign接口调用,RestTemplate调用的方式这里我探讨下RestTemplate
使用SpringCloud的Feign组件能够为服务间的调用节省编码时间并提高开发效率,当服务本身不复杂时可以单独将该组件拿出使用。引入依赖org.spring