一、服务提供者和服务消费者两个服务已经写好启动完毕(未实现消费者调用,目前两个服务毫无关系),如下图:都已注册在Eureka里,起好名字
二、在两个服务的pom文件都引入feign依赖
三、在两个服务启动类上都加入feign注解
四、服务提供者的控制层如下(就是普通的controller),请注意圈出的几个点,在服务消费者里要用到
五、服务消费者利用@FeignClient来调用提供者的controller,如下图,消费者控制层也是普通controller,在消费者的service里调用提供者(@FeignClient的参数就是服务提供者的名字,在eureka里可以看到。@RequestMapping的参数就是上图我圈出的且让注意的路径):
六、补充:如果要调用提供者带参的方法,请使用如下图注解:
如果参数为实体类对象,使用@RequestBody,如下图:
接收参数时也得加:
如果Feign调用失败,直接调用回调函数返回默认值
创建回调类
在调用类上指定回调类是哪个
七、演示:
在8080端口,直接调用提供者
在8088端口,消费者调用提供者
如果springcloud使用的2020,会遇到bug2. 启动报org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'scopedTarget.attrAttrgroupRelationController': Unsatisfied dependency expressed through field 'couponFeignService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.furenqiang.gulimall.product.feign.CouponFeignService': Unexpected exception during bean creation; nested exception is java.lang.IllegalStateException: No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?
解决:pom.xml中添加下面依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
如果报远程调用失败,需要排除一个依赖
<dependency>
<groupId>com.furenqiang.gulimall</groupId>
<artifactId>gulimall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
八、feign流程解析
feign调用流程底层源码解析:重试机制默认次数为5
feign远程调用时可能出现的问题:
①请求头丢失。
上步feign远程调用接口时候,创建了一个新的请求模板RequestTemplate,这个模板是不带请求头的。假设一个场景,服务A如果本地请求的时候带有请求头,比如一个用户的sessionID,在处理此请求的时候A使用了feign远程调用B服务,此时请求RequestTemplate是新建的,请求头是不能带去的。
解决方式:加上feign远程调用的请求拦截器
新建配置类MyFeignConfig,注入一个RequestInterceptor拦截器接口的bean,重写apply方法,在方法里用ThreadLocal封装的RequestContextHolder获取原始request,代码如下
②异步编排取不到上下文。
如果是异步编排异步执行的任务,线程不一样时,是不能共享ThreadLocal的信息的,所以得在异步编排之前的主线程取得需要的信息,然后设置到请求request里