1. 声明式 REST 客户端: Feign

Feign 是一个声明式的 web 服务客户端。它使编写 web 服务客户端变得更加容易。要使用 Feign,请创建一个接口并添加注解。它具有可插拔的注释支持,包括 Feign 注释和 JAX-RS 注释。Feign 还支持可插拔编码器和解码器。Spring Cloud 为 Spring MVC 注解以及默认情况下与 Spring Web 兼容的同一 HttpMessageConverters 添加了对 Feign 的支持。Spring Cloud 集成了 Eureka、Spring Cloud CircuitBreaker、以及 Spring Cloud LoadBalancer,当使用 Feign 时,可以提供一个负载均衡的 http 客户端。spring-doc.cadn.net.cn

1.1. 如何包含 Feign

要将 Feign 包含在您的项目中,请使用组为 org.springframework.cloud 且工件 ID 为 spring-cloud-starter-openfeign 的Starters。有关使用当前 Spring Cloud 发布列车设置构建系统的详细信息,请参阅 Spring Cloud 项目页面spring-doc.cadn.net.cn

示例 spring boot 应用spring-doc.cadn.net.cn

@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);
}

在注解中,上面的String值(“stores”)是一个任意的客户端名称,它用于创建一个Spring Cloud LoadBalancer客户端。您还可以使用url属性指定URL(绝对值或仅主机名)。应用程序上下文中的bean的名称是接口的完全限定名。要指定自己的别名值,可以使用@FeignClient注解的qualifiers值。spring-doc.cadn.net.cn

负载均衡器客户端上面想要发现“商店”服务的物理地址。如果您的应用程序是Eureka客户端,那么它将在Eureka服务注册表中解析该服务。如果您不想使用Eureka,您可以在外部配置中为服务器列表配置一个列表,如SimpleDiscoveryClient所示。spring-doc.cadn.net.cn

Spring Cloud OpenFeign 支持 Spring Cloud LoadBalancer 阻塞模式下所有可用的功能。有关更多信息,请参阅 项目文档spring-doc.cadn.net.cn

要使用 @EnableFeignClients 注解在 @Configuration 注解的类上,请确保指定客户端的位置,例如:@EnableFeignClients(basePackages = "com.example.clients"), 或者明确列出它们:@EnableFeignClients(clients = InventoryServiceFeignClient.class)

1.2. 覆盖Feign默认值

一个概念在Spring Cloud的Feign支持中是命名的客户端。每个Feign 客户端是一组组件的一部分,这些组件一起工作来按需接触远程服务器,并且这组组件有一个名称,您可以使用0 注解作为应用程序开发人员给它。每当需要创建一个新的命名集时,Spring Cloud都会使用2 创建一个新的1 。其中包括(但不限于)一个3 、一个4 和一个5 。 可以使用6 注解的7 属性来覆盖该集合的名称。spring-doc.cadn.net.cn

Spring Cloud 让您通过声明附加配置(在 0 的基础上)来完全控制 Feign 客户端,使用 1。例如:spring-doc.cadn.net.cn

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

在这种情况下,客户机由 0 中已经存在的组件与 1 中的任何组件(后者将覆盖前者)组成。spring-doc.cadn.net.cn

FooConfiguration 不需要使用 @Configuration 注解。然而,如果使用了,则要确保从任何会包含此配置的 @ComponentScan 中排除,否则当指定时,它将成为 feign.Decoderfeign.Encoderfeign.Contract 等的默认来源。可以通过将其放在与任何 @ComponentScan@SpringBootApplication 不重叠的包中,或在 @ComponentScan 中显式排除来避免此问题。
使用注解的contextId属性,以及更改@FeignClient集合中ApplicationContext的名称,它将覆盖客户端名称的别名,并将其用作创建该客户端配置 bean 名称的一部分。
之前,使用 url 属性,并不需要 name 属性。现在,使用 name 是必须的。

占位符支持在属性中使用 nameurlspring-doc.cadn.net.cn

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

Spring Cloud OpenFeign 默认为 feign (BeanType beanName: ClassName):spring-doc.cadn.net.cn

spring-cloud-starter-openfeign 支持 spring-cloud-starter-loadbalancer。然而,作为可选依赖,如果您想使用它,请确保将其添加到您的项目中。

可以通过将feign.okhttp.enabledfeign.httpclient.enabledfeign.httpclient.hc5.enabled分别设置为true,并在类路径中包含它们,来使用OkHttpClient、ApacheHttpClient和ApacheHC5的feign客户端。 您可以通过在使用Apache时提供org.apache.http.impl.client.CloseableHttpClient类型的bean,或者在使用OK HTTP时提供okhttp3.OkHttpClient类型的bean,或者在使用Apache HC5时提供org.apache.hc.client5.http.impl.classic.CloseableHttpClient类型的bean,来自定义所使用的HTTP客户端。spring-doc.cadn.net.cn

Spring Cloud OpenFeign 并不默认提供以下 beans,但仍会从应用程序上下文中查找这些类型的 beans 以创建 Feign 客户端:spring-doc.cadn.net.cn

默认情况下,会创建一个类型为 RetryerRetryer.NEVER_RETRY bean,这将会禁用重试。 请注意,这种重试行为与 Feign 的默认行为不同,Feign 会自动重试 IOExceptions, 将其视为短暂的网络相关异常,以及任何由 ErrorDecoder 抛出的 RetryableException。spring-doc.cadn.net.cn

创建那些类型之一的 bean 并将其放在 @FeignClient 配置(如上例中的 FooConfiguration)中,允许您重写每个所述 bean。例如:spring-doc.cadn.net.cn

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

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

This replaces the SpringMvcContract with feign.Contract.Default and adds a RequestInterceptor to the collection of RequestInterceptor.spring-doc.cadn.net.cn

@FeignClient 还可以使用配置属性进行配置。spring-doc.cadn.net.cn

application.ymlspring-doc.cadn.net.cn

feign:
    client:
        config:
            feignName:
                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
                decode404: false
                encoder: com.example.SimpleEncoder
                decoder: com.example.SimpleDecoder
                contract: com.example.SimpleContract
                capabilities:
                    - com.example.FooCapability
                    - com.example.BarCapability
                queryMapEncoder: com.example.SimpleQueryMapEncoder
                metrics.enabled: false

在此示例中,代码 0 对应代码 1 代码 2,它还与代码 3 代码 4 和代码 5 代码 6 别名。在负载平衡方案中,它还对应用于检索实例的应用服务器的代码 7。指定的解码器、重试程序和其他类必须在 Spring 上下文中有一个 bean 或有一个默认构造函数。spring-doc.cadn.net.cn

默认配置可以在属性@EnableFeignClients中指定,方法与上文所述类似。其区别在于,此配置将应用于所有Feign客户端。spring-doc.cadn.net.cn

如果您更喜欢使用配置属性来配置所有@FeignClient,您可以创建带有default feign 名称的配置属性。spring-doc.cadn.net.cn

你可以使用 feign.client.config.feignName.defaultQueryParametersfeign.client.config.feignName.defaultRequestHeaders 来指定客户端名为 feignName 的每个请求将发送的查询参数和头信息。spring-doc.cadn.net.cn

application.ymlspring-doc.cadn.net.cn

feign:
    client:
        config:
            default:
                connectTimeout: 5000
                readTimeout: 5000
                loggerLevel: basic

如果我们在 0 中创建了 Bean 和配置属性,配置属性将获胜。它会覆盖 1 值。但如果你想改变优先级为 2 ,您可以将 3 更改为 4 spring-doc.cadn.net.cn

如果我们想要创建多个 Feign 客户端,它们具有相同的名称或 URL 以便指向同一台服务器,但每个都有不同的自定义配置 那么就需要使用 contextId 属性 of @FeignClient,以避免这些配置 Bean 的名称冲突。spring-doc.cadn.net.cn

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

也有可能配置 FeignClient 不继承父上下文中的 beans。 可以通过在 1 中重写 0 来返回 2 spring-doc.cadn.net.cn

@Configuration
public class CustomConfiguration {
    @Bean
    public FeignClientConfigurer feignClientConfigurer() {
        return new FeignClientConfigurer() {
            @Override
            public boolean inheritParentConfiguration() {
                 return false;
            }
        };
    }
}
默认情况下,Feign 客户端不会编码斜线 / 字符。您可以通过将 feign.client.decodeSlash 设置为 false 来更改此行为。

1.2.1. SpringEncoder 配置

在我们提供的SpringEncoder中,我们为二进制内容类型设置null字符集,为所有其他内容类型设置2。
spring-doc.cadn.net.cn

您可以修改此行为,通过设置值feign.encoder.charset-from-content-typetrue,从Content-Type标头charset派生字符集。spring-doc.cadn.net.cn

1.3. 超时处理

我们可以在默认的和命名的客户端上都配置超时。OpenFeign 与两个超时参数一起工作:spring-doc.cadn.net.cn

In case the server is not running or available a packet results in connection refused. The communication ends either with an error message or in a fallback. This can happen before the connectTimeout if it is set very low. The time taken to perform a lookup and to receive such a packet causes a significant part of this delay. It is subject to change based on the remote host that involves a DNS lookup.

1.4. 手动创建 Feign 客户端

In some cases it might be necessary to customize your Feign Clients in a way that is not possible using the methods above. In this case you can create Clients using the Feign Builder API. Below is an example which creates two Feign Clients with the same interface but configures each one with a separate request interceptor.spring-doc.cadn.net.cn

@Import(FeignClientsConfiguration.class)
class FooController {

    private FooClient fooClient;

    private FooClient adminClient;

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

        this.adminClient = Feign.builder().client(client)
                .encoder(encoder)
                .decoder(decoder)
                .contract(contract)
                .addCapability(micrometerCapability)
                .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
                .target(FooClient.class, "https://PROD-SVC");
    }
}
In the above example FeignClientsConfiguration.class is the default configuration provided by Spring Cloud OpenFeign.
PROD-SVC 是客户端将要发出请求的服务的名称。
Feign Contract 对象定义了在接口上有效的注解和值。自动装配的 Contract Bean 提供了对 SpringMVC 注解的支持,而不是默认的 Feign 原生注解。

你也可以在 Builder 上使用 Builder`to configure FeignClient not to inherit beans from the parent context. You can do this by overriding calling `inheritParentContext(false)spring-doc.cadn.net.cn

1.5. Feign Spring Cloud 断路器支持

如果Spring Cloud CircuitBreaker在类路径上且值为feign.circuitbreaker.enabled=true,Feign将使用断路器包装所有方法。spring-doc.cadn.net.cn

要按客户端禁用Spring Cloud CircuitBreaker支持,请使用“prototype”范围创建一个vanilla Feign.Builder,例如:spring-doc.cadn.net.cn

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

遵循此模式命名断路器名称<feignClientClassName>#<calledMethod>(<parameterTypes>)。调用带有FooClient接口的@FeignClient时,具有无参数的被调用接口方法是bar,则断路器名称将为FooClient#bar()spring-doc.cadn.net.cn

从2020.0.2开始,电路断路器名称模式已更改为<feignClientName>_<calledMethod>。使用在2020.0.4中引入的CircuitBreakerNameResolver,电路断路器名称可以保留旧模式。

提供值为CircuitBreakerNameResolver的bean,你可以改变熔断器名称模式。spring-doc.cadn.net.cn

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

要启用Spring Cloud CircuitBreaker组,请将feign.circuitbreaker.group.enabled属性设置为true(默认情况下false)。spring-doc.cadn.net.cn

1.6. 使用配置属性配置断路器

您可以使用配置属性来配置断路器。要设置,请将feign.circuitbreaker.alphanumeric-ids.enabled更改为true。由于您不能在配置属性名称中使用像#(),这样的字符,因此我们需要更改由OpenFeign生成的断路器ID的命名约定。上述属性会为您完成此操作。spring-doc.cadn.net.cn

例如,如果您有此 Feign 客户端spring-doc.cadn.net.cn

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

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

你也可以通过执行以下操作使用配置属性对其进行配置spring-doc.cadn.net.cn

feign:
  circuitbreaker:
    enabled: true
    alphanumeric-ids:
      enabled: true
resilience4j:
  circuitbreaker:
    instances:
      DemoClientgetDemo:
        minimumNumberOfCalls: 69
  timelimiter:
    instances:
      DemoClientgetDemo:
        timeoutDuration: 10s

1.7. Feign Spring Cloud 断路器回退

Spring Cloud CircuitBreaker 支持回退的概念:当电路打开或出现错误时执行的默认代码路径。要为某个@FeignClient启用回退,请将fallback属性设置为实现回退的类名。您还需要将其实现声明为 Spring bean。spring-doc.cadn.net.cn

@FeignClient(name = "test", url = "http://localhost:${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";
    }

}

如果需要访问导致回退触发的原因,可以使用 fallbackFactory 属性 inside @FeignClientspring-doc.cadn.net.cn

@FeignClient(name = "testClientWithFactory", url = "http://localhost:${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 的 bean。为了解决这个问题,Spring Cloud OpenFeign 会将所有 Feign 实例标记为 @Primary,因此 Spring 框架会知道注入哪一个 bean。在某些情况下,这种行为可能并不 desirable。要关闭此行为,请将 @FeignClientprimary 属性设置为 false。spring-doc.cadn.net.cn

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

1.9. Feign 继承支持

Feign 通过单继承接口支持样板式 API。 这允许将常见的操作分组到方便的基接口中。spring-doc.cadn.net.cn

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 {

}
`0` 接口不应该在服务器端和客户端之间共享,而且在接口上标注 `1` 时不再支持在类级别上使用 `2` 。

1.10. Feign 请求/响应压缩

你可能需要为你的 Feign 请求启用请求或响应 GZIP 压缩。 你可以通过启用其中一个属性来实现:spring-doc.cadn.net.cn

feign.compression.request.enabled=true
feign.compression.response.enabled=true

Feign request compression gives you settings similar to what you may set for your web server:spring-doc.cadn.net.cn

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

这些属性允许您选择性地压缩媒体类型和最小请求数量。spring-doc.cadn.net.cn

从 OkHttp 使用“透明”压缩,如果存在content-encodingaccept-encoding标头,当类路径上存在feign.okhttp.OkHttpClientfeign.okhttp.enabled设置为true时,我们将禁用压缩。

1.11. Feign 日志记录

为每个创建的 Feign 客户端都创建了一个记录器。默认情况下,记录器的名称是用于创建 Feign 客户端的接口的完整类名。Feign 记录仅响应 DEBUG 级别。spring-doc.cadn.net.cn

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

Logger.Level对象,您可以为每个客户端进行配置,告诉Feign记录多少日志。选项包括:spring-doc.cadn.net.cn

例如,以下代码将设置为Logger.LevelFULLspring-doc.cadn.net.cn

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

1.12. Feign功能支持

Feign 的功能公开了核心 Feign 组件,以便可以修改这些组件。例如,该功能可以采用 Client装饰 它,并将装饰后的实例返回给 Feign。
对度量库的支持是此方法的一个很好的实际示例。请参阅 Feign 度量spring-doc.cadn.net.cn

创建一个或多个Capability个 bean 并将其放入@FeignClient配置,可以让您注册它们并修改涉及的客户端的行为。spring-doc.cadn.net.cn

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

1.13. Feign指标

如果满足以下所有条件,则会创建并注册一个 MicrometerCapability bean,以便您的 Feign 客户端将指标发布到 Micrometer:spring-doc.cadn.net.cn

\ 如果您的应用程序已经使用了 Micrometer,只需将 feign-micrometer 添加到类路径中即可启用指标功能。

您还可以通过以下方式禁用此功能:spring-doc.cadn.net.cn

feign.metrics.enabled=false 禁用所有 Feign 客户端的指标支持,无论客户端级别的标志值为多少:feign.client.config.feignName.metrics.enabled。如果您想按客户端启用或禁用指标,请不要设置 feign.metrics.enabled 并使用 feign.client.config.feignName.metrics.enabled

您还可以通过注册自己的bean来自定义MicrometerCapabilityspring-doc.cadn.net.cn

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

1.14. Feign 缓存

如果使用@EnableCaching注解,则会创建并注册一个CachingCapabilitybean,以便您的Feign客户端能够识别其接口上的@Cache*注解:spring-doc.cadn.net.cn

public interface DemoClient {

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

您也可以通过属性feign.cache.enabled=false禁用此功能。spring-doc.cadn.net.cn

1.15. Feign @QueryMap 支持

OpenFeign 的 @QueryMap 注解提供了支持,用于将 POJOs 用作 GET 参数映射。不幸的是,默认的 OpenFeign QueryMap 注解与 Spring 不兼容,因为它缺少一个 value 属性。spring-doc.cadn.net.cn

Spring Cloud OpenFeign 提供了一个等效的 @SpringQueryMap 注解,该注解用于将 POJO 或 Map 参数标记为查询参数映射。spring-doc.cadn.net.cn

例如,Params类定义了参数param1param2spring-doc.cadn.net.cn

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

    // [Getters and setters omitted for brevity]
}

以下 Feign 客户端通过使用 Params 类并利用 @SpringQueryMap 注解来实现:spring-doc.cadn.net.cn

@FeignClient("demo")
public interface DemoTemplate {

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

如果您需要对生成的查询参数映射进行更多控制,可以实现一个自定义的 QueryMapEncoder Bean。spring-doc.cadn.net.cn

1.16. HATEOAS 支持

Spring 提供了一些 API 来创建遵循 HATEOAS 原则的 REST 表示,Spring HateoasSpring Data RESTspring-doc.cadn.net.cn

如果您的项目使用org.springframework.boot:spring-boot-starter-hateoasStarters或org.springframework.boot:spring-boot-starter-data-restStarters,Feign HATEOAS 支持将默认启用。spring-doc.cadn.net.cn

当启用 HATEOAS 支持时,Feign 客户端被允许序列化和反序列化 HATEOAS 表示模型:EntityModelCollectionModelPagedModelspring-doc.cadn.net.cn

@FeignClient("demo")
public interface DemoTemplate {

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

1.17. Spring @MatrixVariable 支持

Spring Cloud OpenFeign 提供了对 Spring @MatrixVariable 注解的支持。spring-doc.cadn.net.cn

如果将映射传递为方法参数,则使用=连接映射中的键值对来创建@MatrixVariable路径段。spring-doc.cadn.net.cn

如果传递了不同的对象,则使用 = 将提供的 @MatrixVariable 注解中的 name(如果已定义)或带注解的变量名与提供的方法参数连接。spring-doc.cadn.net.cn

重要

即使在服务器端,Spring 不要求用户将路径段占位符的名称与矩阵变量名称相同(因为这在客户端会过于模糊),但 Spring Cloud OpenFeign 要求您添加一个路径段占位符,并且其名称必须匹配 name 注解中提供的名称(如果已定义)或标注的变量名。
spring-doc.cadn.net.cn

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

请注意,变量名称和路径段占位符都称为matrixVarsspring-doc.cadn.net.cn

@FeignClient("demo")
public interface DemoTemplate {

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

1.18. Feign CollectionFormat 支持

我们通过提供 feign.CollectionFormat 注解来支持 @CollectionFormat。 您可以通过传递所需的 feign.CollectionFormat 作为注解值,将该注解放在 Feign 客户端方法上(或整个类上以影响所有方法)。spring-doc.cadn.net.cn

在下面的例子中,使用了CSV格式而不是默认的EXPLODED来处理该方法。spring-doc.cadn.net.cn

@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也不支持。一旦核心项目中可用,我们将尽快在此处添加对其的支持。spring-doc.cadn.net.cn

在完成之前,我们建议使用feign-reactive来支持Spring WebClient。spring-doc.cadn.net.cn

1.19.1. 初始化早期错误

根据您使用Feign客户端的方式,启动应用程序时可能会看到初始化错误。
为了解决这个问题,可以在自动装配客户端时使用ObjectProviderspring-doc.cadn.net.cn

@Autowired
ObjectProvider<TestFeignClient> testFeignClient;

1.20. Spring 数据支持

您可能需要启用 Jackson 模块来支持 org.springframework.data.domain.Pageorg.springframework.data.domain.Sort 解码。spring-doc.cadn.net.cn

feign.autoconfiguration.jackson.enabled=true

1.21. Spring @RefreshScope 支持

如果启用了 Feign 客户端刷新,则每个 Feign 客户端都以 feign.Request.Options 作为刷新范围的 Bean 创建。这意味着可以通过 POST /actuator/refresh 对任何 Feign 客户端实例刷新诸如 connectTimeoutreadTimeout 等属性。spring-doc.cadn.net.cn

默认情况下,Feign 客户端中的刷新行为被禁用。使用以下属性启用刷新行为:spring-doc.cadn.net.cn

feign.client.refresh-enabled=true
不要使用@RefreshScope注解标记@FeignClient接口。

1.22. 支持OAuth2

可以通过设置以下标志来启用 OAuth2 支持:spring-doc.cadn.net.cn

feign.oauth2.enabled=true

编号1.22.1.不再做支持OAuth2支持

当标志设置为true时,如果spring-security-oauth2-autoconfigure存在于类路径中,并且存在oauth2客户端上下文资源详细信息以及OAuth2ClientContextOAuth2ProtectedResourceDetails的bean,则会创建OAuth2FeignRequestInterceptor类的bean。在每次请求之前,拦截器都会解析所需的访问Tokens并将其作为标头包含在内。

有时,在为Feign客户端启用负载均衡时,您可能希望也对获取访问Tokens使用负载均衡。为此,应确保负载均衡器位于类路径中(spring-cloud-starter-loadbalancer),并通过设置以下标志来显式启用OAuth2FeignRequestInterceptor的负载均衡:spring-doc.cadn.net.cn

feign.oauth2.load-balanced=true
警告

如上所述的OAuth2支持现在已弃用,因为spring-security-oauth2-autoconfigure已达到生命周期末期。请改用下面描述的模式。spring-doc.cadn.net.cn

1.22.2. 当前 OAuth2 支持

feign.client.refresh-enabled 标志设置为 true,并且 spring-security-oauth2-client 存在于类路径中时,将创建 OAuth2AccessTokenInterceptor 类型的 bean。在每次请求之前,拦截器会解析所需的访问Tokens并将其作为标题包含在内。OAuth2AccessTokenInterceptor 使用 OAuth2AuthorizedClientManager 来获取持有 OAuth2AccessTokenOAuth2AuthorizedClient。如果用户使用 feign.oauth2.clientRegistrationId 属性指定了 OAuth2 clientRegistrationId,则将使用它来检索Tokens。如果没有检索到Tokens或未指定 clientRegistrationId,则将使用从 url 主机段检索到的 serviceIdspring-doc.cadn.net.cn

TIP

使用serviceId作为OAuth2客户端注册ID对于负载均衡的Feign客户端来说非常方便。对于非负载均衡的情况,基于属性的clientRegistrationId是一种合适的方法。spring-doc.cadn.net.cn

TIP

如果您不想使用默认设置OAuth2AuthorizedClientManager,只需在配置中实例化此类型的bean即可。spring-doc.cadn.net.cn