|
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Cloud OpenFeign 4.2.1! |
Spring Cloud OpenFeign 功能
声明式 REST 客户端:Feign
Feign 是一个声明性 Web 服务客户端。
它使编写 Web 服务客户端变得更加容易。
要使用 Feign,请创建一个接口并对其进行注释。
它具有可插拔的注释支持,包括 Feign 注释和 JAX-RS 注释。
Feign 还支持可插拔编码器和解码器。
Spring Cloud 增加了对 Spring MVC 注释和使用相同的HttpMessageConverters在 Spring Web 中默认使用。
Spring Cloud 集成了 Eureka、Spring Cloud CircuitBreaker 以及 Spring Cloud LoadBalancer,以便在使用 Feign 时提供负载均衡的 http 客户端。
如何包含 Feign
要将 Feign 包含在您的项目中,请使用 starter with grouporg.springframework.cloud和工件 IDspring-cloud-starter-openfeign.有关使用当前 Spring Cloud Release Train 设置构建系统的详细信息,请参阅 Spring Cloud 项目页面。
Spring Boot 应用程序示例
@SpringBootApplication
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@FeignClient("stores")
public interface StoreClient {
@RequestMapping(method = RequestMethod.GET, value = "/stores")
List<Store> getStores();
@GetMapping("/stores")
Page<Store> getStores(Pageable pageable);
@PostMapping(value = "/stores/{storeId}", consumes = "application/json",
params = "mode=upsert")
Store update(@PathVariable("storeId") Long storeId, Store store);
@DeleteMapping("/stores/{storeId:\\d+}")
void delete(@PathVariable Long storeId);
}
在@FeignClientannotation String 值(上面的 “stores”)是任意的客户端名称,用于创建 Spring Cloud LoadBalancer 客户端。
您还可以使用url属性
(绝对值或只是一个主机名)。Bean 在
Application Context 是接口的完全限定名称。
要指定您自己的别名值,您可以使用qualifiers价值
的@FeignClient注解。
上面的负载均衡器客户端将需要发现物理地址
对于 “stores” 服务。如果您的应用程序是 Eureka 客户端,则
它将解析 Eureka 服务注册表中的服务。如果你
不想使用 Eureka,可以配置服务器列表
在外部配置中使用SimpleDiscoveryClient.
Spring Cloud OpenFeign 支持 Spring Cloud LoadBalancer 的阻塞模式可用的所有功能。您可以在项目文档中阅读有关它们的更多信息。
要使用@EnableFeignClients注释开启@Configuration-annotated-classes 中,请确保指定客户端所在的位置,例如:@EnableFeignClients(basePackages = "com.example.clients")或明确列出它们:@EnableFeignClients(clients = InventoryServiceFeignClient.class). |
为了在多模块设置中加载 Spring Feign 客户端 bean,你需要直接指定包。
因为FactoryBean对象可以在初始上下文刷新之前被实例化,并且 Spring Cloud OpenFeign 客户端的实例化会触发上下文刷新,则不应在FactoryBean类。 |
覆盖 Feign Defaults
Spring Cloud 的 Feign 支持中的一个中心概念是命名客户端的概念。每个 Feign 客户端都是组件集合的一部分,这些组件协同工作以按需联系远程服务器,并且集合具有一个名称,您可以作为应用程序开发人员使用@FeignClient注解。Spring Cloud 创建一个新的 ensemble 作为ApplicationContext按需为每个指定客户端使用FeignClientsConfiguration.这包含(除其他外)一个feign.Decoder一个feign.Encoder和feign.Contract.
可以使用contextId属性的@FeignClient注解。
Spring Cloud 允许您通过声明额外的配置(在FeignClientsConfiguration) 使用@FeignClient.例:
@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
//..
}
在这种情况下,客户端由已有的FeignClientsConfiguration与任何 IN 一起FooConfiguration(其中后者将覆盖前者)。
FooConfiguration不需要使用@Configuration.但是,如果是,请注意将其从任何@ComponentScan否则将包含此配置,因为它将成为feign.Decoder,feign.Encoder,feign.Contract等。这可以通过将其放在一个单独的、不重叠的包中来避免@ComponentScan或@SpringBootApplication,或者可以在@ComponentScan. |
用contextId属性的@FeignClient注解,以及更改
这ApplicationContextensemble 的 API 中,它将覆盖客户端名称的别名
它将用作为该客户端创建的配置 Bean 名称的一部分。 |
以前,使用url属性,不需要name属性。用name现在是必需的。 |
占位符在name和url属性。
@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface StoreClient {
//..
}
Spring Cloud OpenFeign 默认为 feign (BeanTypebeanName 的 Bean 名称:ClassName):
-
DecoderfeignDecoder 的ResponseEntityDecoder(它将SpringDecoder) -
EncoderfeignEncoder 的SpringEncoder -
LoggerfeignLogger 中:Slf4jLogger -
MicrometerObservationCapabilitymicrometerObservationCapability:如果feign-micrometer位于 Classpath 上,并且ObservationRegistry可用 -
MicrometerCapabilitymicrometerCapability:如果feign-micrometer位于 Classpath 上,MeterRegistry可用且ObservationRegistry不可用 -
CachingCapabilitycachingCapability:如果@EnableCachingannotation 的 intent 中。可以通过以下方式禁用spring.cloud.openfeign.cache.enabled. -
ContractfeignContract 的SpringMvcContract -
Feign.BuilderfeignBuilder 中:FeignCircuitBreaker.Builder -
ClientfeignClient:如果 Spring Cloud LoadBalancer 在 Classpath 上,则FeignBlockingLoadBalancerClient被使用。 如果它们都不在 Classpath 上,则使用默认的 Feign 客户端。
spring-cloud-starter-openfeign支持spring-cloud-starter-loadbalancer.但是,与可选依赖项一样,如果要使用它,则需要确保已将其添加到项目中。 |
要使用 OkHttpClient 支持的假客户端和 Http2Client 假客户端,请确保您要使用的客户端位于 Classpath 上,并将spring.cloud.openfeign.okhttp.enabled或spring.cloud.openfeign.http2client.enabled自true分别。
对于 Apache HttpClient 5 支持的假客户端,确保 HttpClient 5 在 Classpath 上就足够了,但您仍然可以通过设置spring.cloud.openfeign.httpclient.hc5.enabled自false.
您可以通过提供以下任一 bean 来自定义使用的 HTTP 客户端org.apache.hc.client5.http.impl.classic.CloseableHttpClient使用 Apache HC5 时。
您可以通过在spring.cloud.openfeign.httpclient.xxx性能。那些只以httpclient将适用于所有客户端,前缀为httpclient.hc5到 Apache HttpClient 5 中,前缀为httpclient.okhttp到 OkHttpClient 和前缀为httpclient.http2发送到 Http2Client。您可以在附录中找到可自定义的属性的完整列表。
如果无法使用属性配置 Apache HttpClient 5,则会出现HttpClient5FeignConfiguration.HttpClientBuilderCustomizer用于编程配置的接口。
Apache HTTP 组件5.4更改了 HttpClient 中与 HTTP/1.1 TLS 升级相关的默认值。大多数代理服务器可以毫无问题地处理升级,但是,您可能会遇到 Envoy 或 Istio 的问题。如果您需要恢复以前的行为,您可以使用HttpClient5FeignConfiguration.HttpClientBuilderCustomizer来执行此作,如下例所示。 |
@Configuration
public class FooConfiguration {
@Bean
public HttpClient5FeignConfiguration.HttpClientBuilderCustomizer httpClientBuilder() {
return (httpClientBuilder) -> {
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
requestConfigBuilder.setProtocolUpgradeEnabled(false);
httpClientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
};
}
}
| 从 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 -
Capability(MicrometerObservationCapability和CachingCapability默认提供)
一个 beanRetryer.NEVER_RETRY将Retryer,这将禁用重试。
请注意,此重试行为与 Feign 默认行为不同,后者将自动重试 IOExceptions。
将它们视为与网络相关的暂时性异常,以及从 ErrorDecoder 引发的任何 RetryableException。
创建其中一种类型的 Bean 并将其放置在@FeignClient配置(例如FooConfigurationabove) 允许您覆盖所描述的每个 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也可以使用 Configuration Properties 进行配置。
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在此示例中,指的是@FeignClient value,该 ID 也与@FeignClient name和@FeignClient contextId.在负载均衡方案中,它还对应于serviceId的 Server 应用程序。为 decoders、retryer 和其他类指定的类必须在 Spring 上下文中具有 bean 或具有默认构造函数。
默认配置可以在@EnableFeignClients属性defaultConfiguration以与上述类似的方式。区别在于此配置将应用于所有 Feign 客户端。
如果您更喜欢使用配置属性来配置所有@FeignClient中,您可以使用default假名。
您可以使用spring.cloud.openfeign.client.config.feignName.defaultQueryParameters和spring.cloud.openfeign.client.config.feignName.defaultRequestHeaders指定将随名为feignName.
application.yml
spring:
cloud:
openfeign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic
如果我们同时创建@Configurationbean 和 configuration 属性,则 configuration 属性将胜出。
它将覆盖@Configuration值。但是,如果您想将优先级更改为@Configuration,
您可以更改spring.cloud.openfeign.client.default-to-properties自false.
如果我们想创建多个具有相同名称或 url 的 Feign 客户端
这样它们就会指向同一个服务器,但每个服务器都有不同的自定义配置
我们必须使用contextId属性的@FeignClient为了避免姓名
这些配置 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。
您可以通过覆盖inheritParentConfiguration()在FeignClientConfigurer要返回的 beanfalse:
@Configuration
public class CustomConfiguration {
@Bean
public FeignClientConfigurer feignClientConfigurer() {
return new FeignClientConfigurer() {
@Override
public boolean inheritParentConfiguration() {
return false;
}
};
}
}
默认情况下,Feign 客户端不对斜杠字符进行编码。您可以通过设置/spring.cloud.openfeign.client.decode-slash自false. |
默认情况下,Feign 客户端不会从请求路径中删除尾部斜杠字符。
您可以通过设置/spring.cloud.openfeign.client.remove-trailing-slash自true.
从请求路径中删除尾部斜杠将成为下一个主要版本的默认行为。 |
超时处理
我们可以在默认客户端和命名客户端上配置超时。OpenFeign 使用两个超时参数:
-
connectTimeout防止由于服务器处理时间长而阻止调用方。 -
readTimeout从建立连接时开始应用,并在返回响应时间过长时触发。
如果服务器未运行或不可用,则数据包会导致连接被拒绝。通信以错误消息或回退结束。这可能发生在connectTimeout如果设置得非常低。执行查找和接收此类数据包所花费的时间会导致此延迟的很大一部分。它可能会根据涉及 DNS 查找的远程主机而更改。 |
手动创建假客户端
在某些情况下,可能需要以一种不是 可以使用上述方法。在这种情况下,您可以使用 Feign Builder API 创建客户端。下面是一个示例 这会创建两个具有相同接口的假客户端,但为每个客户端配置 一个单独的请求拦截器。
@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是 Client 将向其发出请求的服务的名称。 |
假动作Contractobject 定义哪些 annotation 和 values 在接口上有效。这
自动接线Contractbean 支持 SpringMVC 注解,而不是
默认的 Feign 本机注释。不建议将 Spring MVC 注释和本机 Feign 注释混合在一起。 |
您还可以使用Builder`to configure FeignClient not to inherit beans from the parent context.
You can do this by overriding calling `inheritParentContext(false)在Builder.
Feign Spring Cloud CircuitBreaker 支持
如果 Spring Cloud CircuitBreaker在 Classpath 上,并且spring.cloud.openfeign.circuitbreaker.enabled=true,Feign 将用断路器包装所有方法。
要在每个客户端上禁用 Spring Cloud CircuitBreaker 支持,请创建一个 vanillaFeign.Builder使用 “prototype” 范围,例如:
@Configuration
public class FooConfiguration {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}
断路器名称遵循此模式<feignClientClassName>#<calledMethod>(<parameterTypes>).调用@FeignClient跟FooClientinterface 和被调用的 interface 方法没有参数bar则断路器名称将为FooClient#bar().
自 2020.0.2 起,熔断器名称模式已从<feignClientName>_<calledMethod>.
用CircuitBreakerNameResolver在 2020.0.4 中引入,断路器名称可以保留旧模式。 |
提供 beanCircuitBreakerNameResolver中,您可以更改断路器名称模式。
@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.enabledproperty 设置为true(默认情况下false).
使用配置属性配置 CircuitBreaker
您可以通过配置属性配置 CircuitBreaker。
例如,如果您有这个 Feign 客户端
@FeignClient(url = "http://localhost: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. |
Feign Spring Cloud CircuitBreaker 回退
Spring Cloud CircuitBreaker 支持回退的概念:当电路打开或出现错误时执行的默认代码路径。要为给定的@FeignClient将fallback属性设置为实现回退的类名。您还需要将实现声明为 Spring Bean。
@FeignClient(name = "test", url = "http://localhost:${server.port}/", fallback = Fallback.class)
protected interface TestClient {
@GetMapping("/hello")
Hello getHello();
@GetMapping("/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属性@FeignClient.
@FeignClient(name = "testClientWithFactory", url = "http://localhost:${server.port}/",
fallbackFactory = TestFallbackFactory.class)
protected interface TestClientWithFactory {
@GetMapping("/hello")
Hello getHello();
@GetMapping("/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";
}
}
Feign 和@Primary
当将 Feign 与 Spring Cloud CircuitBreaker 回退一起使用时,其中ApplicationContext相同类型。这将导致@Autowired不起作用,因为没有一个 bean,或者一个标记为 primary。为了解决这个问题,Spring Cloud OpenFeign 将所有 Feign 实例标记为@Primary,因此 Spring Framework 将知道要注入哪个 bean。在某些情况下,这可能并不可取。要关闭此行为,请将primary属性@FeignClient设置为 false。
@FeignClient(name = "hello", primary = false)
public interface HelloClient {
// methods here
}
Feign Inheritance 支持
Feign 通过单继承接口支持样板 API。 这允许将常见作分组到方便的 base interfaces 中。
public interface UserService {
@GetMapping("/users/{id}")
User getUser(@PathVariable("id") long id);
}
@RestController
public class UserResource implements UserService {
}
@FeignClient("users")
public interface UserClient extends UserService {
}
@FeignClient不应在服务器和客户端之间共享接口,并添加@FeignClient接口与@RequestMapping不再支持 on class 级别。 |
假请求/响应压缩
您可以考虑为您的 假装请求。您可以通过启用以下属性之一来执行此作:
spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.response.enabled=true
假请求压缩为您提供的设置类似于您为 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
这些属性允许您选择压缩媒体类型和最小请求阈值长度。
当请求与spring.cloud.openfeign.compression.request.mime-types和spring.cloud.openfeign.compression.request.min-request-size,spring.cloud.openfeign.compression.request.enabled=true导致将 Compression 标头添加到请求中。
标头的功能是向服务器发出信号,表明客户端需要压缩的正文。服务器端应用程序负责根据客户端提供的标头提供压缩的正文。
由于 OkHttpClient 使用“透明”压缩,因此如果content-encoding或accept-encodingheader 存在,则当feign.okhttp.OkHttpClient存在于 Classpath 中,并且spring.cloud.openfeign.okhttp.enabled设置为true. |
Feign logging (假日志记录)
为创建的每个 Feign 客户端创建一个 Logger。默认情况下,Logger 的名称是用于创建 Feign Client 端的接口的完整类名。假日志记录仅响应DEBUG水平。
logging.level.project.user.UserClient: DEBUG
这Logger.Level对象,告诉 Feign 要记录多少。选项包括:
-
NONE、无日志记录 (DEFAULT)。 -
BASIC,仅记录请求方法和 URL 以及响应状态代码和执行时间。 -
HEADERS,记录基本信息以及请求和响应标头。 -
FULL,记录请求和响应的标头、正文和元数据。
例如,以下代码会将Logger.Level自FULL:
@Configuration
public class FooConfiguration {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
Feign Capability 支持
Feign 功能公开核心 Feign 组件,以便可以修改这些组件。例如,功能可以采用Client,装饰它,并将装饰的实例返回给 Feign。
对 Micrometer 的支持就是一个很好的真实示例。请参阅 Micrometer Support (千分尺支持)。
创建一个或多个Capabilitybean 并将它们放在@FeignClientconfiguration 允许您注册它们并修改相关客户端的行为。
@Configuration
public class FooConfiguration {
@Bean
Capability customCapability() {
return new CustomCapability();
}
}
千分尺支持
如果满足以下所有条件,则MicrometerObservationCapabilitybean 被创建并注册,以便 Micrometer 可以观察到你的 Feign 客户端:
-
feign-micrometer位于 Classpath 上 -
一个
ObservationRegistryBean 可用 -
Feign Micrometer 属性设置为
true(默认情况下)-
spring.cloud.openfeign.micrometer.enabled=true(适用于所有客户) -
spring.cloud.openfeign.client.config.feignName.micrometer.enabled=true(对于单个客户)
-
如果您的应用程序已经使用 Micrometer,启用此功能就像将feign-micrometer添加到您的 Classpath 中。 |
您还可以通过以下任一方式禁用该功能:
-
以外
feign-micrometer从 Classpath 中 -
将 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 支持,而不管 client-level 标志的值是多少:spring.cloud.openfeign.client.config.feignName.micrometer.enabled.
如果要启用或禁用每个客户端的 Micrometer 支持,请不要设置spring.cloud.openfeign.micrometer.enabled并使用spring.cloud.openfeign.client.config.feignName.micrometer.enabled. |
您还可以自定义MicrometerObservationCapability通过注册您自己的 Bean:
@Configuration
public class FooConfiguration {
@Bean
public MicrometerObservationCapability micrometerObservationCapability(ObservationRegistry registry) {
return new MicrometerObservationCapability(registry);
}
}
仍然可以使用MicrometerCapability使用 Feign (仅度量支持) 时,您需要禁用 Micrometer 支持 (spring.cloud.openfeign.micrometer.enabled=false) 并创建一个MicrometerCapability豆:
@Configuration
public class FooConfiguration {
@Bean
public MicrometerCapability micrometerCapability(MeterRegistry meterRegistry) {
return new MicrometerCapability(meterRegistry);
}
}
假装缓存
如果@EnableCachingannotation 时,使用CachingCapability创建并注册 bean,以便您的 Feign 客户端识别@Cache*其接口上的注释:
public interface DemoClient {
@GetMapping("/demo/{filterParam}")
@Cacheable(cacheNames = "demo-cache", key = "#keyParam")
String demoEndpoint(String keyParam, @PathVariable String filterParam);
}
您还可以通过 property 禁用该功能spring.cloud.openfeign.cache.enabled=false.
Spring @RequestMapping 支持
Spring Cloud OpenFeign 为 Spring 提供支持@RequestMappingannotation 及其派生的 annotations(例如@GetMapping,@PostMapping等)支持。
的@RequestMapping注解(包括value,method,params,headers,consumes和produces) 由SpringMvcContract作为请求的内容。
请考虑以下示例:
使用params属性。
@FeignClient("demo")
public interface DemoTemplate {
@PostMapping(value = "/stores/{storeId}", params = "mode=upsert")
Store update(@PathVariable("storeId") Long storeId, Store store);
}
在上面的示例中,请求 url 解析为/stores/storeId?mode=upsert.
params 属性还支持使用多个key=value或只有一个key:
-
什么时候
params = { "key1=v1", "key2=v2" },则请求 URL 解析为/stores/storeId?key1=v1&key2=v2. -
什么时候
params = "key",则请求 URL 解析为/stores/storeId?key.
假装@QueryMap支持
Spring Cloud OpenFeign 提供了一个等效的@SpringQueryMap注解,其中
用于将 POJO 或 Map 参数注释为查询参数 map。
例如,Paramsclass 定义参数param1和param2:
// Params.java
public class Params {
private String param1;
private String param2;
// [Getters and setters omitted for brevity]
}
以下 Feign 客户端使用Params类@SpringQueryMap注解:
@FeignClient("demo")
public interface DemoTemplate {
@GetMapping(path = "/demo")
String demoEndpoint(@SpringQueryMap Params params);
}
如果您需要对生成的查询参数 map 进行更多控制,可以实现自定义的QueryMapEncoder豆。
HATEOAS 支持
Spring 提供了一些 API 来创建遵循 HATEOAS 原则、Spring Hateoas 和 Spring Data REST 的 REST 表示。
如果您的项目使用org.springframework.boot:spring-boot-starter-hateoas起动机
或org.springframework.boot:spring-boot-starter-data-reststarter 中,默认情况下会启用 Feign HATEOAS 支持。
启用 HATEOAS 支持后,允许 Feign 客户端进行序列化 并反序列化 HATEOAS 表示模型:EntityModel、CollectionModel 和 PagedModel。
@FeignClient("demo")
public interface DemoTemplate {
@GetMapping(path = "/stores")
CollectionModel<Store> getStores();
}
Spring @MatrixVariable 支持
Spring Cloud OpenFeign 为 Spring 提供支持@MatrixVariable注解。
如果将 map 作为方法参数传递,则@MatrixVariable路径段是通过将映射中的键值对与 .=
如果传递了不同的对象,则name在@MatrixVariableannotation (如果已定义) 或带注释的变量名称为
使用 .=
- 重要
-
尽管在服务器端, Spring 不要求用户将路径段占位符命名为与矩阵变量名称相同的名称,但由于在客户端太模糊,Spring Cloud OpenFeign 要求您添加一个名称与
name在@MatrixVariableannotation (如果已定义) 或带注释的变量名称。
例如:
@GetMapping("/objects/links/{matrixVars}")
Map<String, List<String>> getObjects(@MatrixVariable Map<String, List<String>> matrixVars);
请注意,变量 name 和 path segment placeholder 都称为matrixVars.
@FeignClient("demo")
public interface DemoTemplate {
@GetMapping(path = "/stores")
CollectionModel<Store> getStores();
}
装CollectionFormat支持
我们支持feign.CollectionFormat通过提供@CollectionFormat注解。
你可以通过传递所需的feign.CollectionFormat作为注释值。
在以下示例中,CSVformat 而不是默认的EXPLODED以处理该方法。
@FeignClient(name = "demo")
protected interface DemoFeignClient {
@CollectionFormat(feign.CollectionFormat.CSV)
@GetMapping(path = "/test")
ResponseEntity performRequest(String test);
}
响应式支持
由于在 Spring Cloud OpenFeign 积极开发时,OpenFeign 项目不支持响应式客户端,例如 Spring WebClient,因此也无法将此类支持添加到 Spring Cloud OpenFeign 中。
由于 Spring Cloud OpenFeign 项目现在被认为功能完整,因此即使它在上游项目中可用,我们也不打算添加支持。我们建议迁移到 Spring Interface Clients。那里支持阻塞和反应堆栈。
Spring Data 支持
如果 Jackson Databind 和 Spring Data Commons 位于类路径上,则org.springframework.data.domain.Page和org.springframework.data.domain.Sort将自动添加。
要禁用此行为,请将
spring.cloud.openfeign.autoconfiguration.jackson.enabled=false
看org.springframework.cloud.openfeign.FeignAutoConfiguration.FeignJacksonConfiguration了解详情。
Spring@RefreshScope支持
如果启用了 Feign 客户端刷新,则每个 Feign 客户端都将使用以下方式创建:
-
feign.Request.Options作为刷新范围的 Bean。这意味着connectTimeout和readTimeout可以针对任何 Feign 客户端实例进行刷新。 -
包裹在
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
请勿注释@FeignClient与@RefreshScope注解。 |
OAuth2 支持
OAuth2 支持可以通过添加spring-boot-starter-oauth2-client依赖项并设置以下标志:
spring.cloud.openfeign.oauth2.enabled=true
当该标志设置为 true,并且存在 oauth2 客户端上下文资源详细信息时,类OAuth2AccessTokenInterceptor已创建。在每个请求之前,侦听器会解析所需的访问Tokens并将其作为标头包含在内。OAuth2AccessTokenInterceptor使用OAuth2AuthorizedClientManager获取OAuth2AuthorizedClient,它持有OAuth2AccessToken.如果用户指定了 OAuth2clientRegistrationId使用spring.cloud.openfeign.oauth2.clientRegistrationId属性,它将用于检索Tokens。如果未检索到Tokens,或者clientRegistrationId未指定,则serviceId从 中检索url将使用 host segment。
- 提示
-
使用
serviceId作为 OAuth2 客户端 registrationId 对于负载均衡的 Feign 客户端来说很方便。对于非负载均衡的 API,基于 property 的clientRegistrationId是一种合适的方法。 - 提示
-
如果您不想使用
OAuth2AuthorizedClientManager,则只需在配置中实例化此类型的 bean。
转换负载均衡的 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以指定顺序。
X-Forwarded 标头支持
X-Forwarded-Host和X-Forwarded-Proto可以通过设置以下标志来启用支持:
spring.cloud.loadbalancer.x-forwarded.enabled=true
向假客户端提供 URL 的支持方法
您可以通过以下任一方式提供 Feign 客户端的 URL:
| 箱 | 示例 | 详 |
|---|---|---|
URL 在 |
|
URL 从 |
URL 在 |
|
URL 从 |
URL 未在 |
|
URL 是从配置属性解析的,无需负载均衡。如果 |
URL 未在 |
|
URL 是从 |
AOT 和本机映像支持
Spring Cloud OpenFeign 支持 Spring AOT 转换和本机映像,但是,仅在禁用刷新模式的情况下,Feign 客户端刷新处于禁用状态(默认设置)和懒惰@FeignClient属性解析disabled (默认设置)。
如果要以 AOT 或原生镜像模式运行 Spring Cloud OpenFeign 客户端,请确保将spring.cloud.refresh.enabled自false. |
如果要以 AOT 或本机映像模式运行 Spring Cloud OpenFeign 客户端,请确保spring.cloud.openfeign.client.refresh-enabled未设置为true. |
如果要以 AOT 或本机映像模式运行 Spring Cloud OpenFeign 客户端,请确保spring.cloud.openfeign.lazy-attributes-resolution未设置为true. |
但是,如果您将url值,则可以覆盖@FeignClient url值,方法是使用-Dspring.cloud.openfeign.client.config.[clientId].url=[url]旗。为了启用覆盖,一个urlvalue 也必须通过 properties 而不是@FeignClient属性。 |
配置属性
要查看所有 Spring Cloud OpenFeign 相关配置属性的列表,请查看附录页面。