Spring Cloud OpenFeign簡介

1.概述

在本教程中,我們將描述Spring Cloud OpenFeign –用於Spring Boot應用程序的聲明式REST客戶端。

Feign通過可插入註釋支持(包括Feign註釋和JAX-RS註釋)使編寫Web服務客戶端更加容易。

而且,Spring Cloud添加了對Spring MVC註釋的支持,並支持使用與Spring Web中使用的相同的HttpMessageConverters

使用Feign的一大好處是,除了接口定義外,我們無需編寫任何代碼來調用服務。

2. 依賴關係

首先,我們將創建一個Spring Boot Web項目並將spring-cloud-starter-openfeign依賴項添加到我們的pom.xml文件中:

<dependency>

 <groupId>org.springframework.cloud</groupId>

 <artifactId>spring-cloud-starter-openfeign</artifactId>

 </dependency>

另外,我們需要添加spring-cloud-dependencies

 <dependencyManagement>

 <dependencies>

 <dependency>

 <groupId>org.springframework.cloud</groupId>

 <artifactId>spring-cloud-dependencies</artifactId>

 <version>${spring-cloud.version}</version>

 <type>pom</type>

 <scope>import</scope>

 </dependency>

 </dependencies>

 </dependencyManagement>

我們可以在Maven Central上找到[spring-cloud-starter-openfeign](https://search.maven.org/search?q=g:org.springframework.cloud%20AND%20a:spring-cloud-starter-openfeign)spring-cloud-dependencies的最新版本。

3. Feign客戶端

接下來,我們需要在主類中添加@EnableFeignClients

@SpringBootApplication

 @EnableFeignClients

 public class ExampleApplication {



 public static void main(String[] args) {

 SpringApplication.run(ExampleApplication.class, args);

 }

 }

使用此註釋,我們可以對組件聲明為Feign客戶端的接口啟用組件掃描。

然後,我們使用@FeignClient批註聲明一個Feign客戶:

@FeignClient(value = "jplaceholder", url = "https://jsonplaceholder.typicode.com/")

 public interface JSONPlaceHolderClient {



 @RequestMapping(method = RequestMethod.GET, value = "/posts")

 List<Post> getPosts();



 @RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")

 Post getPostById(@PathVariable("postId") Long postId);

 }

在此示例中,我們配置了一個客戶端以從JSONPlaceHolder API讀取。

@FeignClient批註中傳遞的value參數是強制性的任意客戶端名稱,而使用url參數時,我們指定API基本URL。

此外,由於此接口是Feign客戶端,因此我們可以使用Spring Web批註來聲明我們想要聯繫的API。

4.配置

現在,了解每個Feign客戶端由一組可自定義的組件組成非常重要

Spring Cloud使用我們可以自定義的FeignClientsConfiguration類根據需要為每個命名客戶端創建一個新的默認集,如下一節所述。

上面的類包含以下bean:

  • Decoder – ResponseEntityDecoder ,包裝SpringDecoder,用於解碼Response
  • 編碼器– SpringEncoder ,用於編碼RequestBody
  • 記錄器– Slf4jLogger是Feign使用的默認記錄器
  • 合同– SpringMvcContract ,提供註釋處理
  • Feign-Builder – HystrixFeign.Builder用於構造組件
  • 客戶端– LoadBalancerFeignClient或默認的Feign客戶端

4.1。自定義Bean配置

如果要自定義一個或多個這些bean,可以使用@Configuration類覆蓋它們,然後將其添加到FeignClient批註中:

@FeignClient(value = "jplaceholder",

 url = "https://jsonplaceholder.typicode.com/",

 configuration = MyClientConfiguration.class)
@Configuration

 public class MyClientConfiguration {



 @Bean

 public OkHttpClient client() {

 return new OkHttpClient();

 }

 }

在此示例中,我們告訴Feign使用OkHttpClient而不是默認值來支持HTTP / 2。

Feign支持針對不同用例的多個客戶端,包括ApacheHttpClient ,該客戶端隨請求發送更多的標頭,例如某些服務器期望的Content-Length,

要使用這些客戶端,請不要忘記將所需的依賴項添加到我們的pom.xml文件中,例如:

<dependency>

 <groupId>io.github.openfeign</groupId>

 <artifactId>feign-okhttp</artifactId>

 </dependency>



 <dependency>

 <groupId>io.github.openfeign</groupId>

 <artifactId>feign-httpclient</artifactId>

 </dependency>

我們可以在Maven Central上找到最新版本的feign-okhttpfeign-okhttp feign-httpclient

4.2。使用屬性進行配置

無需使用@Configuration類,我們可以使用應用程序屬性來配置Feign客戶端,如以下application.yaml示例所示:

feign:

 client:

 config:

 default:

 connectTimeout: 5000

 readTimeout: 5000

 loggerLevel: basic

使用此配置,我們將應用程序中每個聲明的客戶端的超時設置為5秒,記錄器級別設置為basic

最後,我們可以使用default名稱作為客戶端名稱來創建配置,以配置所有@FeignClient對象,或者我們可以為配置聲明@FeignClient客戶端名稱:

feign:

 client:

 config:

 jplaceholder:

如果我們同時具有@Configuration bean和配置屬性,則配置屬性將覆蓋@Configuration值。

5.攔截器

Feign提供的另一個有用的功能是攔截器。

攔截器可以為每個HTTP請求/響應執行從身份驗證到日誌記錄的各種隱式任務。

在本節中,我們將實現自己的攔截器,並使用現成的Spring Cloud OpenFeign提供的攔截器。兩者都將向每個請求添加基本身份驗證標頭

5.1。實現RequestInterceptor

因此,在下面的代碼段中,讓我們實現自定義請求攔截器:

@Bean

 public RequestInterceptor requestInterceptor() {

 return requestTemplate -> {

 requestTemplate.header("user", username);

 requestTemplate.header("password", password);

 requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());

 };

 }

另外,要將攔截器添加到請求鏈中,我們只需要將此bean添加到我們的@Configuration類中即可,或者如我們先前所見,在屬性文件中對其進行聲明:

feign:

 client:

 config:

 default:

 requestInterceptors:

 com.baeldung.cloud.openfeign.JSONPlaceHolderInterceptor

5.2。使用BasicAuthRequestInterceptor

另外,我們可以使用Spring Cloud OpenFeign提供的BasicAuthRequestInterceptor類:

@Bean

 public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {

 return new BasicAuthRequestInterceptor("username", "password");

 }

就這麼簡單!現在,所有請求都將包含基本身份驗證標頭。

6. Hystrix支持

Feign支持Hystrix,因此,如果啟用它,我們可以實現後備模式。

使用後備模式,當遠程服務調用失敗而不是生成異常時,服務使用者將執行備用代碼路徑,以嘗試通過其他方式執行操作。

為了實現該目標,我們需要啟用Hystrix,並在屬性文件中添加feign.hystrix.enabled=true

這使我們可以實現服務失敗時調用的後備方法:

@Component

 public class JSONPlaceHolderFallback implements JSONPlaceHolderClient {



 @Override

 public List<Post> getPosts() {

 return Collections.emptyList();

 }



 @Override

 public Post getPostById(Long postId) {

 return null;

 }

 }

為了讓Feign知道已經提供了fallback方法,我們還需要在@FeignClient批註中設置我們的fallback類:

@FeignClient(value = "jplaceholder",

 url = "https://jsonplaceholder.typicode.com/",

 fallback = JSONPlaceHolderFallback.class)

 public interface JSONPlaceHolderClient {

 // APIs

 }

7. 日誌

對於每個Feign客戶端,默認情況下都會創建一個記錄器。

要啟用日誌記錄,我們應該使用客戶端接口的包名稱在application.propertie的文件中聲明它:

logging.level.com.baeldung.cloud.openfeign.client: DEBUG

或者,如果我們只想為包中的一個特定客戶端啟用日誌記錄,則可以使用完整的類名:

logging.level.com.baeldung.cloud.openfeign.client.JSONPlaceHolderClient: DEBUG

請注意,偽記錄僅響應DEBUG級別。

我們可以為每個客戶端配置的Logger.Level指示要記錄的數量:

@Configuration

 public class ClientConfiguration {



 @Bean

 Logger.Level feignLoggerLevel() {

 return Logger.Level.BASIC;

 }

 }

有四個日誌記錄級別可供選擇:

  • NONE –不記錄,這是默認設置
  • BASIC –僅記錄請求方法,URL和響應狀態
  • HEADERS -記錄與請求和響應頭的基本信息一起
  • FULL –記錄請求和響應的正文,標頭和元數據

8.錯誤處理

Feign的默認錯誤處理程序ErrorDecoder.default始終拋出FeignException

現在,這種行為並不總是最有用的。因此,要自定義拋出的異常,我們可以使用CustomErrorDecoder

public class CustomErrorDecoder implements ErrorDecoder {

 @Override

 public Exception decode(String methodKey, Response response) {



 switch (response.status()){

 case 400:

 return new BadRequestException();

 case 404:

 return new NotFoundException();

 default:

 return new Exception("Generic error");

 }

 }

 }

然後,就像我們之前所做的那樣,我們必須通過將一個bean添加到@Configuration類來替換默認的ErrorDecoder

@Configuration

 public class ClientConfiguration {



 @Bean

 public ErrorDecoder errorDecoder() {

 return new CustomErrorDecoder();

 }

 }

9.結論

在本文中,我們討論了Spring Cloud OpenFeign及其在簡單示例應用程序中的實現。

此外,我們已經了解瞭如何配置客戶端,如何在請求中添加攔截器以及如何使用HystrixErrorDecoder.處理錯誤ErrorDecoder.

像往常一樣,本教程中顯示的所有代碼示例均可在GitHub上獲得。