4.0.6

該專案透過自動配置和繫結到 Spring 環境及其他 Spring 程式設計模型慣用語,為 Spring Boot 應用提供 OpenFeign 整合。

1. 宣告式 REST 客戶端:Feign

Feign 是一個宣告式的 Web 服務客戶端。它使編寫 Web 服務客戶端變得更加容易。要使用 Feign,建立一個介面並進行註解。它支援可插拔的註解,包括 Feign 註解和 JAX-RS 註解。Feign 還支援可插拔的編碼器和解碼器。Spring Cloud 添加了對 Spring MVC 註解的支援,以及使用 Spring Web 中預設使用的相同 HttpMessageConverters。Spring Cloud 集成了 Eureka、Spring Cloud CircuitBreaker 以及 Spring Cloud LoadBalancer,在使用 Feign 時提供一個負載均衡的 HTTP 客戶端。

1.1. 如何包含 Feign

要在您的專案中包含 Feign,請使用群組為 org.springframework.cloud,artifact id 為 spring-cloud-starter-openfeign 的 starter。有關使用當前 Spring Cloud 釋出列車設定構建系統的詳細資訊,請參閱Spring Cloud 專案頁面

Spring Boot 應用程式示例

@SpringBootApplication
@EnableFeignClients
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
StoreClient.java
@FeignClient("stores")
public interface StoreClient {
    @RequestMapping(method = RequestMethod.GET, value = "/stores")
    List<Store> getStores();

    @RequestMapping(method = RequestMethod.GET, value = "/stores")
    Page<Store> getStores(Pageable pageable);

    @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
    Store update(@PathVariable("storeId") Long storeId, Store store);

    @RequestMapping(method = RequestMethod.DELETE, value = "/stores/{storeId:\\d+}")
    void delete(@PathVariable Long storeId);
}

@FeignClient 註解中,字串值(上面是 "stores")是一個任意客戶端名稱,用於建立 Spring Cloud LoadBalancer 客戶端。您還可以使用 url 屬性(絕對值或僅主機名)指定 URL。應用程式上下文中的 bean 名稱是介面的完全限定名。要指定您自己的別名值,您可以使用 @FeignClient 註解的 qualifiers 值。

上面的負載均衡器客戶端將希望發現 "stores" 服務的物理地址。如果您的應用程式是 Eureka 客戶端,它將在 Eureka 服務登錄檔中解析該服務。如果您不想使用 Eureka,您可以使用 SimpleDiscoveryClient 在您的外部配置中配置伺服器列表。

Spring Cloud OpenFeign 支援 Spring Cloud LoadBalancer 阻塞模式的所有可用功能。您可以在專案文件中瞭解更多資訊。

要在 @Configuration 註解的類上使用 @EnableFeignClients 註解,請務必指定客戶端所在的位置,例如:@EnableFeignClients(basePackages = "com.example.clients") 或顯式列出它們:@EnableFeignClients(clients = InventoryServiceFeignClient.class)

1.1.1. 屬性解析模式

在建立 Feign 客戶端 bean 時,我們解析透過 @FeignClient 註解傳遞的值。從 4.x 開始,這些值正在被急切地解析。對於大多數用例來說,這是一個很好的解決方案,它還支援 AOT。

如果您需要延遲解析屬性,請將 spring.cloud.openfeign.lazy-attributes-resolution 屬性值設定為 true

對於 Spring Cloud Contract 測試整合,應該使用延遲屬性解析。

1.2. 覆蓋 Feign 預設值

Spring Cloud 的 Feign 支援中的一個核心概念是命名客戶端。每個 Feign 客戶端都是元件集合的一部分,這些元件協同工作以按需聯絡遠端伺服器,並且該集合有一個名稱,您作為應用程式開發人員使用 @FeignClient 註解給它。Spring Cloud 為每個命名客戶端使用 FeignClientsConfiguration 按需建立一個新的 ApplicationContext 集合。這(除其他外)包含一個 feign.Decoder、一個 feign.Encoder 和一個 feign.Contract。可以透過使用 @FeignClient 註解的 contextId 屬性來覆蓋該集合的名稱。

Spring Cloud 允許您透過使用 @FeignClient 宣告額外配置(在 FeignClientsConfiguration 之上)來完全控制 Feign 客戶端。例如

@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
    //..
}

在這種情況下,客戶端由 FeignClientsConfiguration 中已有的元件以及 FooConfiguration 中的任何元件組成(後者將覆蓋前者)。

FooConfiguration 不需要用 @Configuration 註解。但是,如果它被註解了,那麼請注意將其從任何 @ComponentScan 中排除,否則該 @ComponentScan 將包含此配置,因為它將成為 feign.Decoderfeign.Encoderfeign.Contract 等的預設源(如果指定)。這可以透過將其放在與任何 @ComponentScan@SpringBootApplication 不重疊的單獨包中來避免,或者可以在 @ComponentScan 中顯式排除它。
除了更改 ApplicationContext 集合的名稱之外,使用 @FeignClient 註解的 contextId 屬性還將覆蓋客戶端名稱的別名,並將其用作為該客戶端建立的配置 bean 名稱的一部分。
以前,使用 url 屬性不需要 name 屬性。現在必須使用 name

nameurl 屬性支援佔位符。

@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface StoreClient {
    //..
}

Spring Cloud OpenFeign 預設提供以下 Feign bean(BeanType beanName: ClassName

  • Decoder feignDecoder: ResponseEntityDecoder(包裝了一個 SpringDecoder

  • Encoder feignEncoder: SpringEncoder

  • Logger feignLogger: Slf4jLogger

  • MicrometerObservationCapability micrometerObservationCapability: 如果類路徑上有 feign-micrometer 並且 ObservationRegistry 可用

  • MicrometerCapability micrometerCapability: 如果類路徑上有 feign-micrometerMeterRegistry 可用且 ObservationRegistry 不可用

  • CachingCapability cachingCapability: 如果使用 @EnableCaching 註解。可以透過 spring.cloud.openfeign.cache.enabled 停用。

  • Contract feignContract: SpringMvcContract

  • Feign.Builder feignBuilder: FeignCircuitBreaker.Builder

  • Client feignClient: 如果類路徑上有 Spring Cloud LoadBalancer,則使用 FeignBlockingLoadBalancerClient。如果兩者都沒有,則使用預設的 Feign 客戶端。

spring-cloud-starter-openfeign 支援 spring-cloud-starter-loadbalancer。但是,由於它是一個可選依賴項,如果您想使用它,需要確保已將其新增到您的專案中。

要使用 OkHttpClient 支援的 Feign 客戶端,請確保 OKHttpClient 在您的類路徑上,並將 spring.cloud.openfeign.okhttp.enabled 設定為 true

對於 Apache HttpClient 5 支援的 Feign 客戶端,只需確保 HttpClient 5 在類路徑上即可,但您仍然可以透過將 spring.cloud.openfeign.httpclient.hc5.enabled 設定為 false 來停用 Feign 客戶端使用它。您可以透過在使用 Apache HC5 時提供 org.apache.hc.client5.http.impl.classic.CloseableHttpClient 型別的 bean 來定製使用的 HTTP 客戶端。

您可以透過在 spring.cloud.openfeign.httpclient.xxx 屬性中設定值來進一步定製 HTTP 客戶端。以 httpclient 開頭的屬性將適用於所有客戶端,以 httpclient.hc5 開頭的適用於 Apache HttpClient 5,以 httpclient.okhttp 開頭的適用於 OkHttpClient。您可以在附錄中找到可自定義的屬性的完整列表。

從 Spring Cloud OpenFeign 4 開始,不再支援 Feign Apache HttpClient 4。我們建議改用 Apache HttpClient 5。

Spring Cloud OpenFeign 預設提供以下 Feign bean,但仍從應用程式上下文中查詢這些型別的 bean 以建立 Feign 客戶端

  • Logger.Level

  • Retryer

  • ErrorDecoder

  • Request.Options

  • Collection<RequestInterceptor>

  • SetterFactory

  • QueryMapEncoder

  • CapabilityMicrometerObservationCapabilityCachingCapability 預設提供)

預設情況下會建立一個型別為 RetryerRetryer.NEVER_RETRY bean,這將停用重試。請注意,這種重試行為與 Feign 預設行為不同,在 Feign 預設行為中,它會自動重試 IOException,將其視為瞬時網路相關異常,以及從 ErrorDecoder 丟擲的任何 RetryableException。

建立其中一種型別的 bean 並將其放在 @FeignClient 配置中(例如上面的 FooConfiguration)允許您覆蓋所描述的每個 bean。示例

@Configuration
public class FooConfiguration {
    @Bean
    public Contract feignContract() {
        return new feign.Contract.Default();
    }

    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("user", "password");
    }
}

這會將 SpringMvcContract 替換為 feign.Contract.Default,並向 RequestInterceptor 集合新增一個 RequestInterceptor

@FeignClient 也可以使用配置屬性進行配置。

application.yml

spring:
    cloud:
        openfeign:
            client:
                config:
                    feignName:
                        url: http://remote-service.com
                        connectTimeout: 5000
                        readTimeout: 5000
                        loggerLevel: full
                        errorDecoder: com.example.SimpleErrorDecoder
                        retryer: com.example.SimpleRetryer
                        defaultQueryParameters:
                            query: queryValue
                        defaultRequestHeaders:
                            header: headerValue
                        requestInterceptors:
                            - com.example.FooRequestInterceptor
                            - com.example.BarRequestInterceptor
                        responseInterceptor: com.example.BazResponseInterceptor
                        dismiss404: false
                        encoder: com.example.SimpleEncoder
                        decoder: com.example.SimpleDecoder
                        contract: com.example.SimpleContract
                        capabilities:
                            - com.example.FooCapability
                            - com.example.BarCapability
                        queryMapEncoder: com.example.SimpleQueryMapEncoder
                        micrometer.enabled: false

此示例中的 feignName 指的是 @FeignClientvalue,它也與 @FeignClientname@FeignClientcontextId 別名。在負載均衡場景中,它也對應於將用於檢索例項的伺服器應用程式的 serviceId。解碼器、重試器和其他指定的類必須在 Spring 上下文中有一個 bean 或有一個預設建構函式。

預設配置可以透過 @EnableFeignClients 屬性 defaultConfiguration 以與上述類似的方式指定。區別在於此配置將應用於 所有 Feign 客戶端。

如果您更喜歡使用配置屬性來配置所有 @FeignClient,您可以使用 default Feign 名稱建立配置屬性。

您可以使用 spring.cloud.openfeign.client.config.feignName.defaultQueryParametersspring.cloud.openfeign.client.config.feignName.defaultRequestHeaders 來指定將隨名為 feignName 的客戶端的每個請求一起傳送的查詢引數和頭。

application.yml

spring:
    cloud:
        openfeign:
            client:
                config:
                    default:
                        connectTimeout: 5000
                        readTimeout: 5000
                        loggerLevel: basic

如果同時建立 @Configuration bean 和配置屬性,配置屬性將勝出。它將覆蓋 @Configuration 值。但如果您想將優先順序更改為 @Configuration,可以將 spring.cloud.openfeign.client.default-to-properties 更改為 false

如果我們想建立多個具有相同名稱或 URL 的 Feign 客戶端,以便它們指向同一伺服器但每個都具有不同的自定義配置,那麼我們必須使用 @FeignClientcontextId 屬性,以避免這些配置 bean 的名稱衝突。

@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
public interface FooClient {
    //..
}
@FeignClient(contextId = "barClient", name = "stores", configuration = BarConfiguration.class)
public interface BarClient {
    //..
}

還可以配置 FeignClient 不從父上下文繼承 bean。您可以透過覆蓋 FeignClientConfigurer bean 中的 inheritParentConfiguration() 返回 false 來實現

@Configuration
public class CustomConfiguration {
    @Bean
    public FeignClientConfigurer feignClientConfigurer() {
        return new FeignClientConfigurer() {
            @Override
            public boolean inheritParentConfiguration() {
                 return false;
            }
        };
    }
}
預設情況下,Feign 客戶端不編碼斜槓 / 字元。您可以透過將 spring.cloud.openfeign.client.decodeSlash 的值設定為 false 來更改此行為。

1.2.1. SpringEncoder 配置

在我們提供的 SpringEncoder 中,我們將二進位制內容型別設定為 null 字元集,將所有其他內容型別設定為 UTF-8

您可以透過將 spring.cloud.openfeign.encoder.charset-from-content-type 的值設定為 true 來修改此行為,從而從 Content-Type 頭字元集中派生字元集。

1.3. 超時處理

我們可以為預設客戶端和命名客戶端配置超時。OpenFeign 使用兩個超時引數

  • connectTimeout 防止因伺服器處理時間過長而阻塞呼叫者。

  • readTimeout 從連線建立時開始應用,當返回響應時間過長時觸發。

如果伺服器未執行或不可用,資料包會導致 連線被拒絕。通訊要麼以錯誤訊息結束,要麼以回退結束。如果 connectTimeout 設定得很低,這可能發生在 之前。執行查詢和接收此類資料包所需的時間構成了此延遲的很大一部分。它會根據涉及 DNS 查詢的遠端主機而改變。

1.4. 手動建立 Feign 客戶端

在某些情況下,可能需要以無法使用上述方法的方式自定義您的 Feign 客戶端。在這種情況下,您可以使用 Feign Builder API 建立客戶端。下面是一個示例,它建立了兩個具有相同介面的 Feign 客戶端,但為每個客戶端配置了單獨的請求攔截器。

@Import(FeignClientsConfiguration.class)
class FooController {

    private FooClient fooClient;

    private FooClient adminClient;

    @Autowired
    public FooController(Client client, Encoder encoder, Decoder decoder, Contract contract, MicrometerObservationCapability micrometerObservationCapability) {
        this.fooClient = Feign.builder().client(client)
                .encoder(encoder)
                .decoder(decoder)
                .contract(contract)
                .addCapability(micrometerObservationCapability)
                .requestInterceptor(new BasicAuthRequestInterceptor("user", "user"))
                .target(FooClient.class, "https://PROD-SVC");

        this.adminClient = Feign.builder().client(client)
                .encoder(encoder)
                .decoder(decoder)
                .contract(contract)
                .addCapability(micrometerObservationCapability)
                .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
                .target(FooClient.class, "https://PROD-SVC");
    }
}
在上面的示例中,FeignClientsConfiguration.class 是 Spring Cloud OpenFeign 提供的預設配置。
PROD-SVC 是客戶端將向其發出請求的服務的名稱。
Feign Contract 物件定義了介面上哪些註解和值是有效的。自動裝配的 Contract bean 支援 SpringMVC 註解,而不是預設的 Feign 原生註解。

您還可以使用 Builder 來配置 FeignClient 不從父上下文繼承 bean。您可以透過在 Builder 上呼叫 inheritParentContext(false) 來實現。

1.5. Feign Spring Cloud CircuitBreaker 支援

如果類路徑上有 Spring Cloud CircuitBreaker 並且 spring.cloud.openfeign.circuitbreaker.enabled=true,Feign 將使用斷路器包裝所有方法。

要停用每個客戶端的 Spring Cloud CircuitBreaker 支援,請建立一個具有 "prototype" 範圍的普通 Feign.Builder,例如

@Configuration
public class FooConfiguration {
    @Bean
    @Scope("prototype")
    public Feign.Builder feignBuilder() {
        return Feign.builder();
    }
}

斷路器名稱遵循此模式 <feignClientClassName>#<calledMethod>(<parameterTypes>)。當呼叫具有 FooClient 介面的 @FeignClient 並且被呼叫的介面方法沒有引數是 bar 時,斷路器名稱將是 FooClient#bar()

從 2020.0.2 開始,斷路器名稱模式已從 <feignClientName>_<calledMethod> 更改。使用 2020.0.4 中引入的 CircuitBreakerNameResolver,斷路器名稱可以保留舊模式。

透過提供 CircuitBreakerNameResolver 的 bean,您可以更改斷路器名稱模式。

@Configuration
public class FooConfiguration {
    @Bean
    public CircuitBreakerNameResolver circuitBreakerNameResolver() {
        return (String feignClientName, Target<?> target, Method method) -> feignClientName + "_" + method.getName();
    }
}

要啟用 Spring Cloud CircuitBreaker 組,請將 spring.cloud.openfeign.circuitbreaker.group.enabled 屬性設定為 true(預設為 false)。

1.6. 使用配置屬性配置 CircuitBreaker

您可以透過配置屬性配置 CircuitBreaker。

例如,如果您有這個 Feign 客戶端

@FeignClient(url = "https://:8080")
public interface DemoClient {

    @GetMapping("demo")
    String getDemo();
}

您可以透過以下方式使用配置屬性配置它

spring:
  cloud:
    openfeign:
      circuitbreaker:
        enabled: true
        alphanumeric-ids:
          enabled: true
resilience4j:
  circuitbreaker:
    instances:
      DemoClientgetDemo:
        minimumNumberOfCalls: 69
  timelimiter:
    instances:
      DemoClientgetDemo:
        timeoutDuration: 10s
如果您想切換回 Spring Cloud 2022.0.0 之前使用的斷路器名稱,可以將 spring.cloud.openfeign.circuitbreaker.alphanumeric-ids.enabled 設定為 false

1.7. Feign Spring Cloud CircuitBreaker 回退

Spring Cloud CircuitBreaker 支援回退概念:當斷路器開啟或出現錯誤時執行的預設程式碼路徑。要為給定的 @FeignClient 啟用回退,請將 fallback 屬性設定為實現回退的類名。您還需要將您的實現宣告為 Spring bean。

@FeignClient(name = "test", url = "https://:${server.port}/", fallback = Fallback.class)
protected interface TestClient {

    @RequestMapping(method = RequestMethod.GET, value = "/hello")
    Hello getHello();

    @RequestMapping(method = RequestMethod.GET, value = "/hellonotfound")
    String getException();

}

@Component
static class Fallback implements TestClient {

    @Override
    public Hello getHello() {
        throw new NoFallbackAvailableException("Boom!", new RuntimeException());
    }

    @Override
    public String getException() {
        return "Fixed response";
    }

}

如果需要訪問導致回退觸發的原因,可以使用 @FeignClient 中的 fallbackFactory 屬性。

@FeignClient(name = "testClientWithFactory", url = "https://:${server.port}/",
            fallbackFactory = TestFallbackFactory.class)
protected interface TestClientWithFactory {

    @RequestMapping(method = RequestMethod.GET, value = "/hello")
    Hello getHello();

    @RequestMapping(method = RequestMethod.GET, value = "/hellonotfound")
    String getException();

}

@Component
static class TestFallbackFactory implements FallbackFactory<FallbackWithFactory> {

    @Override
    public FallbackWithFactory create(Throwable cause) {
        return new FallbackWithFactory();
    }

}

static class FallbackWithFactory implements TestClientWithFactory {

    @Override
    public Hello getHello() {
        throw new NoFallbackAvailableException("Boom!", new RuntimeException());
    }

    @Override
    public String getException() {
        return "Fixed response";
    }

}

1.8. Feign 和 @Primary

當將 Feign 與 Spring Cloud CircuitBreaker 回退一起使用時,ApplicationContext 中存在多個相同型別的 bean。這將導致 @Autowired 無法工作,因為沒有恰好一個 bean,或者沒有一個被標記為 primary。為了解決這個問題,Spring Cloud OpenFeign 將所有 Feign 例項標記為 @Primary,這樣 Spring Framework 就會知道要注入哪個 bean。在某些情況下,這可能不合需要。要關閉此行為,請將 @FeignClientprimary 屬性設定為 false。

@FeignClient(name = "hello", primary = false)
public interface HelloClient {
    // methods here
}

1.9. Feign 繼承支援

Feign 透過單繼承介面支援樣板 API。這允許將常見操作分組到方便的基介面中。

UserService.java
public interface UserService {

    @RequestMapping(method = RequestMethod.GET, value ="/users/{id}")
    User getUser(@PathVariable("id") long id);
}
UserResource.java
@RestController
public class UserResource implements UserService {

}
UserClient.java
package project.user;

@FeignClient("users")
public interface UserClient extends UserService {

}
@FeignClient 介面不應在伺服器和客戶端之間共享,並且不再支援在類級別使用 @RequestMapping 註解 @FeignClient 介面。

1.10. Feign 請求/響應壓縮

您可以考慮為 Feign 請求啟用請求或響應 GZIP 壓縮。您可以透過啟用其中一個屬性來實現這一點

spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.response.enabled=true

Feign 請求壓縮為您提供了類似於您可以為 Web 伺服器設定的設定

spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.request.mime-types=text/xml,application/xml,application/json
spring.cloud.openfeign.compression.request.min-request-size=2048

這些屬性允許您對壓縮媒體型別和最小請求閾值長度進行選擇性設定。

由於 OkHttpClient 使用“透明”壓縮,如果在類路徑上存在 feign.okhttp.OkHttpClient 並且 spring.cloud.openfeign.okhttp.enabled 設定為 true,則會停用此壓縮,因為存在 content-encodingaccept-encoding 頭部。

1.11. Feign 日誌

為每個建立的 Feign 客戶端建立一個日誌記錄器。預設情況下,日誌記錄器的名稱是用於建立 Feign 客戶端的介面的完整類名。Feign 日誌記錄僅響應 DEBUG 級別。

application.yml
logging.level.project.user.UserClient: DEBUG

您可以為每個客戶端配置的 Logger.Level 物件,它告訴 Feign 要記錄多少資訊。選項有

  • NONE,不記錄任何資訊(預設)。

  • BASIC,僅記錄請求方法和 URL,以及響應狀態碼和執行時間。

  • HEADERS,記錄基本資訊以及請求和響應頭。

  • FULL,記錄請求和響應的頭、正文和元資料。

例如,以下將 Logger.Level 設定為 FULL

@Configuration
public class FooConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

1.12. Feign Capability 支援

Feign 能力公開了核心 Feign 元件,以便可以修改這些元件。例如,這些能力可以獲取 Client,對其進行 裝飾,然後將裝飾後的例項返回給 Feign。對 Micrometer 的支援就是一個很好的實際示例。參見 Micrometer 支援

建立或多個 Capability bean 並將其放在 @FeignClient 配置中,您可以註冊它們並修改相關客戶端的行為。

@Configuration
public class FooConfiguration {
    @Bean
    Capability customCapability() {
        return new CustomCapability();
    }
}

1.13. Micrometer 支援

如果滿足以下所有條件,將建立並註冊一個 MicrometerObservationCapability bean,以便您的 Feign 客戶端可以透過 Micrometer 進行觀察

  • 類路徑上有 feign-micrometer

  • ObservationRegistry bean 可用

  • feign micrometer 屬性設定為 true(預設)

    • spring.cloud.openfeign.micrometer.enabled=true(適用於所有客戶端)

    • spring.cloud.openfeign.client.config.feignName.micrometer.enabled=true(適用於單個客戶端)

如果您的應用程式已經使用 Micrometer,啟用此功能就像將 feign-micrometer 放在類路徑上一樣簡單。

您還可以透過以下方式停用該功能

  • feign-micrometer 從類路徑中排除

  • 將其中一個 feign micrometer 屬性設定為 false

    • spring.cloud.openfeign.micrometer.enabled=false

    • spring.cloud.openfeign.client.config.feignName.micrometer.enabled=false

spring.cloud.openfeign.micrometer.enabled=false 會停用 所有 Feign 客戶端的 Micrometer 支援,無論客戶端級別標誌 spring.cloud.openfeign.client.config.feignName.micrometer.enabled 的值如何。如果您想為每個客戶端啟用或停用 Micrometer 支援,請不要設定 spring.cloud.openfeign.micrometer.enabled,而是使用 spring.cloud.openfeign.client.config.feignName.micrometer.enabled

您還可以透過註冊自己的 bean 來定製 MicrometerObservationCapability

@Configuration
public class FooConfiguration {
    @Bean
    public MicrometerObservationCapability micrometerObservationCapability(ObservationRegistry registry) {
        return new MicrometerObservationCapability(registry);
    }
}

仍然可以使用 MicrometerCapability 與 Feign(僅度量支援),您需要停用 Micrometer 支援(spring.cloud.openfeign.micrometer.enabled=false)並建立一個 MicrometerCapability bean

@Configuration
public class FooConfiguration {
    @Bean
    public MicrometerCapability micrometerCapability(MeterRegistry meterRegistry) {
        return new MicrometerCapability(meterRegistry);
    }
}

1.14. Feign 快取

如果使用 @EnableCaching 註解,將建立並註冊一個 CachingCapability bean,以便您的 Feign 客戶端識別其介面上的 @Cache* 註解

public interface DemoClient {

    @GetMapping("/demo/{filterParam}")
    @Cacheable(cacheNames = "demo-cache", key = "#keyParam")
    String demoEndpoint(String keyParam, @PathVariable String filterParam);
}

您也可以透過屬性 spring.cloud.openfeign.cache.enabled=false 停用此功能。

1.15. Feign @QueryMap 支援

Spring Cloud OpenFeign 提供了一個等效的 @SpringQueryMap 註解,用於將 POJO 或 Map 引數註解為查詢引數對映。

例如,Params 類定義了引數 param1param2

// Params.java
public class Params {
    private String param1;
    private String param2;

    // [Getters and setters omitted for brevity]
}

以下 feign 客戶端使用 @SpringQueryMap 註解使用 Params

@FeignClient("demo")
public interface DemoTemplate {

    @GetMapping(path = "/demo")
    String demoEndpoint(@SpringQueryMap Params params);
}

如果您需要對生成的查詢引數對映進行更多控制,您可以實現自定義的 QueryMapEncoder bean。

1.16. HATEOAS 支援

Spring 提供了一些 API 來建立遵循 HATEOAS 原則的 REST 表示,即 Spring HateoasSpring Data REST

如果您的專案使用 org.springframework.boot:spring-boot-starter-hateoas starter 或 org.springframework.boot:spring-boot-starter-data-rest starter,則預設啟用 Feign HATEOAS 支援。

啟用 HATEOAS 支援後,Feign 客戶端可以序列化和反序列化 HATEOAS 表示模型:EntityModelCollectionModelPagedModel

@FeignClient("demo")
public interface DemoTemplate {

    @GetMapping(path = "/stores")
    CollectionModel<Store> getStores();
}

1.17. Spring @MatrixVariable 支援

Spring Cloud OpenFeign 提供對 Spring @MatrixVariable 註解的支援。

如果將 Map 作為方法引數傳遞,則透過將 Map 中的鍵值對與 = 連線來建立 @MatrixVariable 路徑段。

如果傳遞的是不同的物件,則 @MatrixVariable 註解中提供的 name(如果已定義)或被註解的變數名將與提供的方法引數使用 = 連線。

重要

儘管在伺服器端,Spring 不要求使用者將路徑段佔位符命名為與矩陣變數名相同,但由於在客戶端會過於模糊,Spring Cloud OpenFeign 要求您新增一個路徑段佔位符,其名稱與 @MatrixVariable 註解中提供的 name(如果已定義)或被註解的變數名匹配。

例如:

@GetMapping("/objects/links/{matrixVars}")
Map<String, List<String>> getObjects(@MatrixVariable Map<String, List<String>> matrixVars);

請注意,變數名和路徑段佔位符都稱為 matrixVars

@FeignClient("demo")
public interface DemoTemplate {

    @GetMapping(path = "/stores")
    CollectionModel<Store> getStores();
}

1.18. Feign CollectionFormat 支援

我們透過提供 @CollectionFormat 註解來支援 feign.CollectionFormat。您可以透過將所需的 feign.CollectionFormat 作為註解值傳遞來註解 Feign 客戶端方法(或整個類以影響所有方法)。

在以下示例中,使用 CSV 格式而不是預設的 EXPLODED 來處理方法。

@FeignClient(name = "demo")
protected interface DemoFeignClient {

    @CollectionFormat(feign.CollectionFormat.CSV)
    @GetMapping(path = "/test")
    ResponseEntity performRequest(String test);

}

1.19. 響應式支援

由於 OpenFeign 專案 目前不支援響應式客戶端,例如 Spring WebClient,Spring Cloud OpenFeign 也不支援。一旦核心專案中可用,我們將在此時新增支援。

在此之前,我們建議使用 feign-reactive 來支援 Spring WebClient。

1.19.1. 早期初始化錯誤

我們不鼓勵在應用程式生命週期的早期階段使用 Feign 客戶端,例如在處理配置和初始化 bean 時。在 bean 初始化期間使用客戶端是不受支援的。

同樣,根據您使用 Feign 客戶端的方式,您可能會在啟動應用程式時看到初始化錯誤。為了解決這個問題,您可以在自動裝配客戶端時使用 ObjectProvider

@Autowired
ObjectProvider<TestFeignClient> testFeignClient;

1.20. Spring Data 支援

如果類路徑上有 Jackson Databind 和 Spring Data Commons,則會自動新增 org.springframework.data.domain.Pageorg.springframework.data.domain.Sort 的轉換器。

要停用此行為,請設定

spring.cloud.openfeign.autoconfiguration.jackson.enabled=false

有關詳細資訊,請參閱 org.springframework.cloud.openfeign.FeignAutoConfiguration.FeignJacksonConfiguration

1.21. Spring @RefreshScope 支援

如果 Feign 客戶端重新整理已啟用,則每個 Feign 客戶端都使用以下方式建立

  • feign.Request.Options 作為重新整理範圍的 bean。這意味著 connectTimeoutreadTimeout 等屬性可以針對任何 Feign 客戶端例項進行重新整理。

  • URL 封裝在 org.springframework.cloud.openfeign.RefreshableUrl 下。這意味著 Feign 客戶端的 URL(如果使用 spring.cloud.openfeign.client.config.{feignName}.url 屬性定義)可以針對任何 Feign 客戶端例項進行重新整理。

您可以透過 POST /actuator/refresh 重新整理這些屬性。

預設情況下,Feign 客戶端中的重新整理行為是停用的。使用以下屬性啟用重新整理行為

spring.cloud.openfeign.client.refresh-enabled=true
請勿使用 @RefreshScope 註解 @FeignClient 介面。

1.22. OAuth2 支援

可以透過向專案新增 spring-boot-starter-oauth2-client 依賴項並設定以下標誌來啟用 OAuth2 支援

spring.cloud.openfeign.oauth2.enabled=true

當該標誌設定為 true 並且存在 OAuth2 客戶端上下文資源詳細資訊時,將建立一個 OAuth2AccessTokenInterceptor 類的 bean。在每個請求之前,攔截器解析所需的訪問令牌並將其作為請求頭包含。OAuth2AccessTokenInterceptor 使用 OAuth2AuthorizedClientManager 獲取包含 OAuth2AccessTokenOAuth2AuthorizedClient。如果使用者已使用 spring.cloud.openfeign.oauth2.clientRegistrationId 屬性指定了 OAuth2 clientRegistrationId,則將使用它來檢索令牌。如果未檢索到令牌或未指定 clientRegistrationId,則將使用從 url 主機段檢索到的 serviceId

提示

serviceId 用作 OAuth2 客戶端註冊 ID 對於負載均衡的 Feign 客戶端很方便。對於非負載均衡的客戶端,基於屬性的 clientRegistrationId 是一種合適的方法。

提示

如果您不想使用 OAuth2AuthorizedClientManager 的預設設定,您可以在配置中例項化此型別的 bean。

1.23. 轉換負載均衡的 HTTP 請求

您可以使用選定的 ServiceInstance 來轉換負載均衡的 HTTP 請求。

對於 Request,您需要實現並定義 LoadBalancerFeignRequestTransformer,如下所示

@Bean
public LoadBalancerFeignRequestTransformer transformer() {
    return new LoadBalancerFeignRequestTransformer() {

        @Override
        public Request transformRequest(Request request, ServiceInstance instance) {
            Map<String, Collection<String>> headers = new HashMap<>(request.headers());
            headers.put("X-ServiceId", Collections.singletonList(instance.getServiceId()));
            headers.put("X-InstanceId", Collections.singletonList(instance.getInstanceId()));
            return Request.create(request.httpMethod(), request.url(), headers, request.body(), request.charset(),
                    request.requestTemplate());
        }
    };
}

如果定義了多個轉換器,它們將按照 bean 定義的順序應用。或者,您可以使用 LoadBalancerFeignRequestTransformer.DEFAULT_ORDER 來指定順序。

1.24. X-Forwarded Headers 支援

可以透過設定以下標誌來啟用 X-Forwarded-HostX-Forwarded-Proto 支援

spring.cloud.loadbalancer.x-forwarded.enabled=true

1.25. 向 Feign 客戶端提供 URL 的支援方式

您可以透過以下任何一種方式向 Feign 客戶端提供 URL

情況 示例 詳細資訊

URL 在 @FeignClient 註解中提供。

@FeignClient(name="testClient", url="https://:8081")

URL 從註解的 url 屬性解析,不進行負載均衡。

URL 在 @FeignClient 註解和配置屬性中提供。

@FeignClient(name="testClient", url="https://:8081") 並且屬性在 application.yml 中定義為 spring.cloud.openfeign.client.config.testClient.url=https://:8081

URL 從註解的 url 屬性解析,不進行負載均衡。配置屬性中提供的 URL 未使用。

URL 未在 @FeignClient 註解中提供,但在配置屬性中提供。

@FeignClient(name="testClient") 並且屬性在 application.yml 中定義為 spring.cloud.openfeign.client.config.testClient.url=https://:8081

URL 從配置屬性解析,不進行負載均衡。如果 spring.cloud.openfeign.client.refresh-enabled=true,則配置屬性中定義的 URL 可以按照 Spring RefreshScope 支援 中所述進行重新整理。

URL 既未在 @FeignClient 註解中提供,也未在配置屬性中提供。

@FeignClient(name="testClient")

URL 從註解的 name 屬性解析,並進行負載均衡。

1.26. AOT 和 Native Image 支援

Spring Cloud OpenFeign 支援 Spring AOT 轉換和 native image,但僅限於停用重新整理模式、停用 Feign 客戶端重新整理(預設設定)和停用 延遲 @FeignClient 屬性解析(預設設定)的情況。

如果您想在 AOT 或 native image 模式下執行 Spring Cloud OpenFeign 客戶端,請務必將 spring.cloud.refresh.enabled 設定為 false
如果您想在 AOT 或 native image 模式下執行 Spring Cloud OpenFeign 客戶端,請確保 spring.cloud.openfeign.client.refresh-enabled 未設定為 true
如果您想在 AOT 或 native image 模式下執行 Spring Cloud OpenFeign 客戶端,請確保 spring.cloud.openfeign.lazy-attributes-resolution 未設定為 true
但是,如果您透過屬性設定 url 值,則可以透過使用 -Dspring.cloud.openfeign.client.config.[clientId].url=[url] 標誌執行映象來覆蓋 @FeignClienturl 值。為了啟用覆蓋,在構建時也必須透過屬性而不是 @FeignClient 屬性設定 url 值。

2. 配置屬性

要檢視所有 Spring Cloud OpenFeign 相關配置屬性的列表,請檢視附錄頁面

© . This site is unofficial and not affiliated with VMware.