Feign可以做到使用 HTTP 请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。它像 Dubbo 一样,consumer 直接调用接口方法调用 provider,而不需要通过常规的 Http Client 构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。
添加feign 的依赖
<!-- 引入open feign 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
使用,在接口上添加注解 @FeignClient("") 进行配置
@FeignClient(value = "order-server", path = "order")public interface OrderFeignService {@GetMapping("/findOrderByUserId/{id}")R findOrderByUserId(@PathVariable("id") Integer id);}
在启动类中加入注解 @EnableFeignClients
@SpringBootApplication@EnableFeignClientspublic class StudyuserApplication {public static void main(String[] args) {SpringApplication.run(StudyuserApplication.class, args);}}
在UserController 调用 , 跟普通接口一样的写法。
@Autowiredprivate OrderFeignService orderFeignService;@GetMapping("/findOrderByUserIdWithFeign/{id}")public R findOrderByUserIdWithFeign(@PathVariable("id") Integer id) {// feign调用R result = orderFeignService.findOrderByUserId(id);return result;}
测试,验证

spring cloud feign 的自定义配置及使用
日志配置
有时候我们遇到 Bug,比如接口调用失败、参数没收到等问题,或者想看看调用性能,就需要配置 Feign 的日志了,以此让 Feign 把请求信息输出来。
日志等级有 4 种,分别是:
NONE【性能最佳,适用于生产】:不记录任何日志(默认值)。
BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间。
HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据
全局配置
加入配置类 FeignConfig
package com.jiuge.user.config;import feign.Logger;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** @author jiuge* @version 1.0* @date 2021/8/5 11:16*/@Configurationpublic class FeignConfig {@Beanpublic Logger.Level feignLoggerLevel() {return Logger.Level.FULL;}}
配置好后在yml 文件加入对应feign目录的日志级别
logging:level:com.jiuge.user.feign: debug
请求接口 http://localhost:8010/user/findOrderByUserIdWithFeign/1 测试,验证, 把日志请求信息打印出来了
2021-08-05 11:22:08.205 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] ---> GET http://order-server/order/findOrderByUserId/1 HTTP/1.12021-08-05 11:22:08.205 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] ---> END HTTP (0-byte body)2021-08-05 11:22:08.562 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] <--- HTTP/1.1 200 (356ms)2021-08-05 11:22:08.562 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] connection: keep-alive2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] content-type: application/json2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] date: Thu, 05 Aug 2021 03:22:08 GMT2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] keep-alive: timeout=602021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] transfer-encoding: chunked2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId]2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] {"msg":"success","code":0,"orders":[{"id":1,"userId":"1","commodityCode":"UT2191929213903","count":1,"amount":2}]}2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] <--- END HTTP (114-byte body)
局部配置 去除FeignConfig 上的Configuration 注解
// @Configurationpublic class FeignConfig {@Beanpublic Logger.Level feignLoggerLevel() {return Logger.Level.FULL;}}
修改OrderFeignService 接口的注解,接口头加入 configuration 注解
// feignConfig 的局部配置@FeignClient(value = "order-server", path = "order",configuration = FeignConfig.class)public interface OrderFeignService {@RequestMapping("/findOrderByUserId/{id}")R findOrderByUserId(@PathVariable("id") Integer id);}
请求接口http://localhost:8010/user/findOrderByUserIdWithFeign/1测试,验证

局部配置2,可以在yml 进行配置
logging:level:com.jiuge.user.feign: debugfeign:client:config:order-server:loggerLevel: FULL
OrderFeignService 类上去除 configuration 配置
@FeignClient(value = "order-server", path = "order",configuration = FeignConfig.class)
换成
@FeignClient(value = "order-server", path = "order")
测试验证

契约配置
Spring Cloud 在 Feign 的基础上做了扩展,可以让 Feign 支持 Spring MVC 的注解来调用。原生的 Feign 是不支持 Spring MVC 注解的,如果你想在 Spring Cloud 中使用原生的注解方式来定义客户端也是可以的,通过配置契约来改变这个配置,Spring Cloud 中默认的是 SpringMvcContract。
修改契约配置,支持原生的配置
在FeignConfig 上添加如下内容
/*** 修改契约配置,支持Feign原生的注解* @return*/@Beanpublic Contract feignContract() {return new Contract.Default();}
修改OrderFeignService 类内容
使用原生的feign 注解 @RequestLine
// feignConfig 的局部配置@FeignClient(value = "order-server", path = "order")public interface OrderFeignService {// @RequestMapping("/findOrderByUserId/{id}")@RequestLine("GET /findOrderByUserId/{userId}")R findOrderByUserId(@PathVariable("userId") Integer userId);}
局部配置 上面配置需要加这个
修改application.yml 文件 添加contract
feign:client:config:order-server:loggerLevel: FULLcontract: feign.Contract.Default #指定Feign原生注解契约配置

通过拦截器实现认证
通常我们调用的接口都是有权限控制的,很多时候可能认证的值是通过参数去传递的,还有就是通过请求头去传递认证信息,比如 Basic 认证方式。
添加bean 实例
@Beanpublic BasicAuthRequestInterceptor basicAuthRequestInterceptor(){return new BasicAuthRequestInterceptor("jiuge","123456");}
扩展点 feign.RequestInterceptor
每次 feign 发起http调用之前,会去执行拦截器中的逻辑。
public interface RequestInterceptor {/*** Called for every request. Add data using methods on the supplied {@link}.*/void apply(RequestTemplate template);}
使用场景
统一添加 header 信息;
对 body 中的信息做修改或替换;
自定义拦截实现逻辑
public class FeignAuthRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {// 业务逻辑String access_token = UUID.randomUUID().toString();template.header("Authorization",access_token);}}
order-server 端可以通过 @RequestHeader获取请求参数
全局配置
@Configuration // 全局配置public class FeignConfig {@Beanpublic Logger.Level feignLoggerLevel() {return Logger.Level.FULL;}/*** 自定义拦截器* @return*/@Beanpublic FeignAuthRequestInterceptor feignAuthRequestInterceptor(){return new FeignAuthRequestInterceptor();}}
局部配置
feign:client:config:order-server:loggerLevel: FULLrequestInterceptors[0]:com.jiuge.user.interceptor.FeignAuthRequestInterceptor
超时时间配置
通过 Options 可以配置连接超时时间和读取超时时间,Options 的第一个参数是连接的超时时间(ms),默认值是 2s;第二个是请求处理的超时时间(ms),默认值是 5s。
@Beanpublic Request.Options options() {return new Request.Options(5000, 10000);}
局部配置
feign:client:config:order-server:loggerLevel: FULL# 连接超时时间,默认2sconnectTimeout: 2000# 请求处理超时时间,默认5sreadTimeout: 3000
补充说明:Feign的底层用的是Ribbon,但超时时间以Feign配置为准
客户端组件配置
配置Apache HttpClient
引入依赖
<!-- Apache HttpClient --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.7</version></dependency><dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId><version>10.1.0</version></dependency>
修改yml 文件 ,启用 apache httpclient
feign:#feign 使用 Apache HttpClient 可以忽略,默认开启httpclient:enabled: true
测试,验证 会进入ApacheHttpClient 中的execute 方法

配置OkHttp
引入依赖
<!-- 引入OkHttp --><dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId></dependency>
修改yml,将Feign的HttpClient 禁用, 启用OkHttp
feign:#feign 使用 okhttpokhttp:enabled: true
测试,验证 会进入OkHttpClient 类的 execute 方法

GZIP 接口压缩配置
开启压缩可以有效节约网络资源,提升接口性能,可以配置GZIP 来压缩数据
修改yml 文件,为如下内容
feign:httpclient:enabled: truecompression:request:enabled: true# 配置压缩的类型mime-types: text/xml,application/xml,application/json#最小压缩值min-request-size: 2048response:enabled: true
注意:只有当Feign 的Http client 不是okhttp3的时候,压缩才会生效, 配置源码在 FeignAcceptGzipEncodingAutoConfiguration 上
测试,验证

编码器解码器配置
引入jackson 依赖
<!-- 引入jackson 依赖 --><dependency><groupId>io.github.openfeign</groupId><artifactId>feign-jackson</artifactId></dependency>
java 配置方式
@Beanpublic Decoder decoder() {return new JacksonDecoder();}@Beanpublic Encoder encoder() {return new JacksonEncoder();}
yml 配置方式
feign:client:config:order-server: #对应微服务# 配置编解码器encoder: feign.jackson.JacksonEncoderdecoder: feign.jackson.JacksonDecoder
以上两种,任选一种进行配置。




