SpringCloud OpenFeign使用詳解
一、前言
在springcloud微服務生態(tài)體系下,作為服務之間相互調(diào)用的重要組件openfeign,在其中承擔著非常重要的作用,本篇以springcloud中提供的遠程接口調(diào)用組件openfeign為例,來聊聊openfeign的詳細使用。
二、什么是openfeign
2.1 openfeign介紹
- Feign是Netflix開發(fā)的,聲明式、模板化的HTTP客戶端;
- Feign可幫助開發(fā)者更加便捷、優(yōu)雅地調(diào)用HTTP API;
- Feign支持多種注解,例如Feign自帶的注解或者JAX-RS注解等;
2.2 openfeign優(yōu)勢
Feign可以做到使用 HTTP 請求遠程服務時就像調(diào)用本地方法一樣,開發(fā)者完全感知不到這是遠程調(diào)用,更感知不到這是個 HTTP 請求。具體來說:
- 它像 Dubbo 一樣,consumer 直接調(diào)用接口方法調(diào)用 provider,而不需要通過常規(guī)的 Http Client 構造請求再解析返回數(shù)據(jù);
- 它解決了讓開發(fā)者調(diào)用遠程接口就跟調(diào)用本地方法一樣,無需關注與遠程的交互細節(jié),更無需關注分布式環(huán)境開發(fā);
三、Spring Cloud Alibaba整合OpenFeign
以之前的工程案例為基座,在此基礎上繼續(xù)搭建新的模塊,接下來,通過實際的操作,演示如何基于Spring Cloud Alibaba實現(xiàn)與OpenFeign的整合
3.1 前置準備
創(chuàng)建一個新的order模塊,名為:openfign-order,工程目錄如下

3.2 代碼整合過程
3.2.1 添加feign依賴
添加如下依賴,主要是open-feign的依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos-config 配置中心-自帶動態(tài)刷新-->
<!--<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>-->
<!--nacos-discovery 注冊中心-服務發(fā)現(xiàn)與注冊-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>3.2.2 添加feign接口類
使用過dubbo的同學應該對此不陌生,使用服務端提供的接口時只需要注入就可以像調(diào)用本地方法一樣使用了,feign的使用也是類似,只需在調(diào)用方定義一個接口類,里面添加被調(diào)用的接口中的完整的方法名,參數(shù)等,即保持與接口中的方法體參數(shù)一致即可;
比如在order模塊調(diào)用stock模塊時,stock的接口類提供了下面的方法
@GetMapping("/reduct")
public String reduct(){
System.out.println("扣減庫存 : 8021");
return "扣減庫存 : 8021";
}那么在order模塊中,自定義一個接口類,如下
@FeignClient(name = "stock-service",path = "/stock")
public interface StockFeignService {
@GetMapping("/reduct")
public String reduct();
}參數(shù)說明:
- 該接口中的方法名,參數(shù),請求類型等都與接口提供方接口保持一致;
- 接口上面用FeignClient注解修飾,name為服務提供方名稱,path為接口根路徑;
3.2.3 調(diào)整調(diào)用的方法
在之前的調(diào)用中,我們一直使用的是restTemplate的方式調(diào)用,如果使用了feign,調(diào)用看起來就變得簡單了,做一下簡單的改造即可;
@RestController
@RequestMapping("/order")
public class OrderController {
@Value("${service-url.nacos-user-service}")
private String serverURL;
@Autowired
private StockFeignService stockFeignService;
//localhost:8083/order/add
@GetMapping("/add")
public String add(){
System.out.println("下單成功");
String reduct = stockFeignService.reduct();
return "add order :" + reduct;
}
}3.2.4 核心配置文件
這里調(diào)整一下端口即可
server:
port: 8040
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #服務注冊中心地址3.2.5 接口模擬測試
啟動stock-service的兩個工程,再啟動order模塊,啟動完成后,瀏覽器進行接口調(diào)用

反復多次調(diào)用,默認情況下,呈現(xiàn)出的是輪詢效果

四、openfeign自定義配置使用
Feign 提供了很多擴展機制,開發(fā)者可以使用這些機制更靈活的擴展系統(tǒng)功能。
4.1 擴展日志配置 — 全局配置
使用了Feign之后,有時開發(fā)過程中遇到Bug,比如接口調(diào)用失敗、參數(shù)沒收到等問題,或者想看看調(diào)用性能,這就需要配置Feign的日志了,以便讓Feign把請求的完整信息輸出來定位和分析問題。配置過程很簡單,只需添加一個配置類, 定制Feign提供的Logger級別即可。
4.1.1 添加一個日志配置類
添加如下配置類,指定level的級別為FULL,表示輸出完整的日志信息
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}也可以根據(jù)自身的需求配置其他的日志級別,從源碼中可以看到內(nèi)置了多種級別的日志

4.1.2 配置文件調(diào)整日志級別
默認情況下,服務工程以info級別輸出,但Feign的日志級別為debug,兩者不匹配,所以還需要額外做一下配置,在配置文件中補充下面的配置即可,即針對
logging:
level:
com.congge.feign: debug4.1.3 接口測試
在order模塊的Feign中添加一個新的接口進行調(diào)用
@GetMapping("/get")
public String get(@RequestParam("id") Integer id);接口調(diào)用
//localhost:8040/order/get
@GetMapping("/get")
public String get(){
String stockInfo = stockFeignService.get(1);
return stockInfo;
}瀏覽器執(zhí)行調(diào)用:localhost:8040/order/get,說明調(diào)用成功

再看控制臺,發(fā)現(xiàn)輸出了詳細的調(diào)用日志信息

4.2 擴展日志配置之局部配置
上面配置的這種方式是針對全局生效的,即Feign包路徑下的所有類都生效,如果僅僅是針對某個具體的類生效,該怎么做呢?其實也很簡單,只需要下面的兩步;
4.2.1 自定義日志配置類
與上面的想必,去掉那個@Configuration注解即可
import feign.Logger;
import org.springframework.context.annotation.Bean;
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}4.2.2 在目標Feign接口指定日志配置類
在@FeignClient注解中有一個configuration的熟悉,使用上面的配置類即可
@FeignClient(name = "stock-service",path = "/stock",configuration = FeignConfig.class)
public interface StockFeignService {
@GetMapping("/reduct")
public String reduct();
@GetMapping("/get")
public String get(@RequestParam("id") Integer id);
}4.2.3 配置文件方式實現(xiàn)局部日志擴展
在5.2.1的基礎上,也可以不用通過5.2.2的方式通過指定配置類添加,而是在配置文件中指定,只需要在配置文件中添加下面的配置即可;
feign:
client:
config:
stock-service:
loggerLevel: FULL配置完成后再次調(diào)用一下,控制臺仍然可以輸出完整的調(diào)用日志信息

五、openfeign契約配置
Spring Cloud 在 Feign 的基礎上做了擴展,使用 Spring MVC 的注解來完成Feign的功能,以減少使用者的學習成本。
而原生的 Feign 是不支持 Spring MVC 注解的,如果你想在 Spring Cloud 中使用原生的注解方式來定義客戶端也是可以的,通過配置契約來改變這個配置,Spring Cloud 中默認的
是 SpringMvcContract。
Spring Cloud 1 早期版本就是用的原生Fegin. 隨著netflix的停更替換成了Open feign
5.1 具體操作步驟
5.1.1 使用配置類的方式
在配置類中添加Contract 的bean
@SpringBootApplication
//@EnableDiscoveryClient
@EnableFeignClients
public class FeignOrderApp {
public static void main(String[] args) {
SpringApplication.run(FeignOrderApp.class, args);
}
@Bean
public Contract feignContract() {
return new Contract.Default();
}
}5.1.2 修改Feign接口的方法調(diào)用
注意:修改契約配置后,OrderFeignService 不再支持springmvc的注解,需要使用Feign原生的注解
接口中的調(diào)用改為如下(更多語法配置可以參閱相關資料)
@FeignClient(name = "stock-service",path = "/stock")
public interface StockFeignServiceV2 {
@RequestLine("GET /reduct")
public String reduct();
@RequestLine("GET /get")
public String get(@Param("id") Integer id);
}5.1.3 模擬測試
再次啟動order模塊服務,然后在瀏覽器調(diào)用

5.1.4 通過yml配置文件配置契約
在5.1.1 基礎上,將契約的配置配置到配置文件中也可以實現(xiàn)相同的效果,具體配置如下
feign:
client:
config:
stock-service:
loggerLevel: FULL
#配置契約
concontract: feign.Contract.Default六、openfeign超時配置
客戶端微服務通過Fiegn調(diào)用其他微服務接口時,可能因為某些原因導致接口響應超時達到默認的設置時間而調(diào)用失敗,如果業(yè)務允許超時時長更長一點的話,就可以考慮手動配置openfeign的超時時間;
6.1 通過代碼方式配置
在上述的配置類中添加下面的超時配置bean;
- 通過 Options 可以配置連接超時時間和讀取超時時間;
- Options 的第一個參數(shù)是連接的超時時間(ms),默認值是 2s;
- Options 的第一個參數(shù)是連接的超時,第二個是請求處理的超時時間(ms),默認值是 5s;
@Bean
public Request.Options options() {
return new Request.Options(5000, 10000);
}6.2 通過配置文件方式配置
6.2.1 添加配置文件
核心配置如下
feign:
client:
config:
stock-service:
loggerLevel: FULL
#配置契約
#concontract: feign.Contract.Default
connectTimeout: 5000
readTimeout: 3000補充說明: Feign的底層用的是Ribbon,但超時時間以Feign配置為準
6.2.2 修改被調(diào)用方接口
為了模擬效果,將調(diào)用的stock-service中的接口加一個sleep時間
@GetMapping("/get")
public String get(@RequestParam("id") Integer id) throws InterruptedException {
Thread.sleep(4000);
return "查詢到的庫存商品ID : " + id;
}6.2.3 模擬測試調(diào)用
啟動兩個模塊的工程,瀏覽器調(diào)用接口:localhost:8040/order/get,將會看到下面的效果

同時觀察控制臺輸出日志,可以看到輸出了 超時的信息;

?七、openfeign 自定義攔截器
7.1 攔截器概述
使用springmvc攔截器的同學對攔截器應該不陌生,攔截器可以在請求真正到達后端接口之前做一下預處理工作,比如非法請求攔截、參數(shù)校驗過濾、全局token的認證、加解密、審計等等。在openfeign 中也提供了類似的可以自定義的攔截器,其存在的目的主要是針對服務調(diào)用端在調(diào)用服務接口時可以做的一些預處理工作。
接下來演示如何在openfeign 中自定義攔截器;
7.2 操作過程
7.2.1 自定義 FeignInterceptor
主要是實現(xiàn)RequestInterceptor 接口,重寫里面的apply方法即可,比如在下面的apply方法中,給請求頭中添加了兩個參數(shù),這樣的話,服務提供方就可以解析到header中參數(shù)的值;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.UUID;
public class FeignInterceptor implements RequestInterceptor {
static final Logger logger = LoggerFactory.getLogger(FeignInterceptor.class);
@Override
public void apply(RequestTemplate requestTemplate) {
logger.info("enter FeignInterceptor ...");
String accessToken=UUID.randomUUID().toString();
requestTemplate.header("accessToken",accessToken);
requestTemplate.header("username","jerry");
}
}7.2.2 使自定義的攔截器生效
可以通過配置全局bean的方式或者在yaml中配置都可以
配置bean的方式
@Bean
public FeignInterceptor feignInterceptor() {
return new FeignInterceptor();
}配置文件方式
feign:
client:
config:
stock-service:
loggerLevel: FULL
connectTimeout: 5000
readTimeout: 3000
#自定義攔截器
requestInterceptors: com.congge.config.FeignInterceptor7.2.3 改造stock中的get接口
這里將請求中的參數(shù)進行解析,并打印輸出結果
@GetMapping("/get")
public String get(@RequestParam("id") Integer id) throws InterruptedException {
String accessToken = request.getHeader("accessToken");
System.out.println(accessToken);
String username = request.getHeader("username");
System.out.println(username);
//Thread.sleep(4000);
return "查詢到的庫存商品ID : " + id;
}7.2.4 模擬測試
分別啟動stock模塊的工程和order模塊的工程,然后瀏覽器調(diào)用:localhost:8040/order/get
接口可以正常返回結果;

?觀察stock服務控制臺,header中的參數(shù)值也能正確的被解析出來;

?7.2.5 自定義攔截器小結
自定義攔截器一種很有用的技巧,尤其是內(nèi)部各個微服務之間進行調(diào)用的時候,為了確認對方的身份是否授信或者互信,可以通過這種方式傳遞一些可以加解密的參數(shù)進行身份確認。
八、寫在文末
Feign在springcloud微服務生態(tài)體系中具有非常重要的作用,對于習慣使用dubbo服務調(diào)用方式的同學來說,系統(tǒng)在微服務架構演進過程中,可以采用同時兼容dubbo和feign的方式,而且只需要在現(xiàn)用的架構中做少量的適配和改造即可,這是一個很好的嘗試,因此有必要深入了解Feign的技術。
以上就是SpringCloud OpenFeign使用詳解的詳細內(nèi)容,更多關于SpringCloud OpenFeign使用的資料請關注腳本之家其它相關文章!
相關文章
SpringSecurity多表多端賬戶登錄的實現(xiàn)
本文主要介紹了SpringSecurity多表多端賬戶登錄的實現(xiàn)2024-05-05
關于訪問后端接口報404錯誤問題的解決方法(全網(wǎng)最細!)
404頁面的出現(xiàn)會降低用戶體驗,那么導致404頁面出現(xiàn)的原因是什么呢?這篇文章主要給大家介紹了關于訪問后端接口報404錯誤問題的解決方法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-04-04
詳解在SpringBoot中使用MongoDb做單元測試的代碼
這篇文章主要介紹了詳解在SpringBoot中使用MongoDb做單元測試的代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11
SpringBoot?DataSource數(shù)據(jù)源實現(xiàn)自動配置流程詳解
這篇文章主要介紹了SpringBoot?DataSource數(shù)據(jù)源實現(xiàn)自動配置流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-10-10
Spring boot @RequestBody數(shù)據(jù)傳遞過程詳解
這篇文章主要介紹了Spring boot @RequestBody數(shù)據(jù)傳遞過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-12-12
java 高并發(fā)中volatile的實現(xiàn)原理
這篇文章主要介紹了java 高并發(fā)中volatile的實現(xiàn)原理的相關資料,在多線程并發(fā)編程中synchronized和Volatile都扮演著重要的角色,Volatile是輕量級的synchronized,它在多處理器開發(fā)中保證了共享變量的“可見性”,需要的朋友可以參考下2017-03-03

