Spring Cloud OpenFeign 全教程
1. 声明式 REST 客户端: Feign
Feign 是一个声明式的 Web Service 客户端。它使编写 Web Service 客户端更容易。要使用 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,请使用 group 为 org.springframework.cloud 和 artifact id 为 spring-cloud-starter-openfeign 的 starter。请参阅 Spring Cloud 项目页面,了解关于使用当前 Spring Cloud Release Train 设置构建系统的详细信息。
例子: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 client.。你也可以使用 url 属性指定一个 URL(绝对值或只是一个hostname)。application context 中的 bean 名称是接口的完全限定名称。要指定你自己的别名值,你可以使用 @FeignClient 注解的 qualifiers 值。
上面的负载均衡器客户端将想发现 "stores" service 的物理地址。如果你的应用程序是一个 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 {//..
}
在这种情况下,client 由 FeignClientsConfiguration 中已有的组件和 FooConfiguration 中的任何组件组成(后者将覆盖前者)。
FooConfiguration 不需要用 @Configuration 来注解。然而,如果它是,那么请注意将它从任何 @ComponentScan 中排除,否则会包括这个配置,因为它将成为 feign.Decoder、feign.Encoder、feign.Contract 等的默认来源。这可以通过把它放在与任何 @ComponentScan 或 @SpringBootApplication 单独的、不重叠的包中来避免,或者在 @ComponentScan 中明确排除它。 |
使用 @FeignClient 注解的 contextId 属性,除了改变 ApplicationContext 集合的名称外,它还将覆盖客户端名称的别名,它将被用作为该客户端创建的配置Bean名称的一部分。 |
以前,使用 url 属性,不需要使用 name 属性。现在,使用 name 是必须的。 |
在 name 和 url 属性中支持占位符。
@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 在 classpath 并且 ObservationRegistry 是可用的
- MicrometerCapability micrometerCapability: 如果 feign-micrometer 在 classpath, MeterRegistry 可用,并且 ObservationRegistry 不可用
- CachingCapability cachingCapability: 如果使用了 @EnableCaching 注解,可以通过 spring.cloud.openfeign.cache.enabled 来禁用。
- Contract feignContract: SpringMvcContract
- Feign.Builder feignBuilder: FeignCircuitBreaker.Builder
- Client feignClient: 如果 Spring Cloud LoadBalancer 在 classpath 上,就会使用 FeignBlockingLoadBalancerClient。如果它们都不在 classpath 上,则使用默认的 feign 客户端。
spring-cloud-starter-openfeign 支持 spring-cloud-starter-loadbalancer。然而,由于它是一个可选的依赖项,如果你想使用它,你需要确保它已经被添加到你的项目中。 |
通过将 spring.cloud.openfeign.okhttp.enabled 或 spring.cloud.openfeign.httpclient.hc5.enabled 分别设置为 true 并将其放在 classpath 上,就可以使用 OkHttpClient 和 Apache HttpClient 5 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,但仍然从 application context 查找这些类型的 Bean 来创建 feign 客户端:
- Logger.Level
- Retryer
- ErrorDecoder
- Request.Options
- Collection<RequestInterceptor>
- SetterFactory
- QueryMapEncoder
- Capability (MicrometerObservationCapability 和 CachingCapability 默认提供) 默认情况下,会创建一个 Retryer.NEVER_RETRY 类型的 Retryer bean,它将禁用重试。注意这个重试行为与 Feign 的默认行为不同,它将自动重试 IOExceptions,将其视为瞬时网络相关的异常,以及从 ErrorDecoder 抛出的任何 RetryableException。
创建这些类型中的一个bean,并将其放置在 @FeignClient 配置中(如上面的 FooConfiguration),允许你覆盖所述的每一个 bean。例子:
@Configuration
public class FooConfiguration {@Beanpublic Contract feignContract() {return new feign.Contract.Default();}@Beanpublic BasicAuthRequestInterceptor basicAuthRequestInterceptor() {return new BasicAuthRequestInterceptor("user", "password");}
}
这就用 feign.Contract.Default 替换了 SpringMvcContract,并在 RequestInterceptor 的集合中添加了一个 RequestInterceptor。
@FeignClient 也可以使用配置属性进行配置。
application.yml
spring:cloud:openfeign:client:config:feignName:url: http://remote-service.comconnectTimeout: 5000readTimeout: 5000loggerLevel: fullerrorDecoder: com.example.SimpleErrorDecoderretryer: com.example.SimpleRetryerdefaultQueryParameters:query: queryValuedefaultRequestHeaders:header: headerValuerequestInterceptors:- com.example.FooRequestInterceptor- com.example.BarRequestInterceptorresponseInterceptor: com.example.BazResponseInterceptordismiss404: falseencoder: com.example.SimpleEncoderdecoder: com.example.SimpleDecodercontract: com.example.SimpleContractcapabilities:- com.example.FooCapability- com.example.BarCapabilityqueryMapEncoder: com.example.SimpleQueryMapEncodermicrometer.enabled: false
本例中的 feignName 指的是 @FeignClient value,它也被别名为 @FeignClient name 和 @FeignClient contextId。在负载均衡的情况下,它也对应于将被用来检索实例的服务器应用程序的 serviceId。
默认配置可以在 @EnableFeignClients 属性 defaultConfiguration 中指定,其方式与上面描述的类似。不同的是,这个配置将适用于所有 feign 客户端。
如果你喜欢用配置属性来配置所有的 @FeignClient,你可以用 default feign name 创建配置属性。
你可以使用 spring.cloud.openfeign.client.config.feignName.defaultQueryParameters 和 spring.cloud.openfeign.client.config.feignName.defaultRequestHeaders 来指定查询参数和 header 信息,它们将与名为 feignName 的客户端的每个请求一起发送。
application.yml
spring:cloud:openfeign:client:config:default:connectTimeout: 5000readTimeout: 5000loggerLevel: basic
如果我们同时创建 @Configuration bean和配置属性,配置属性将获胜。它将覆盖 @Configuration 的值。但如果你想改变 @Configuration 的优先级,你可以将 spring.cloud.openfeign.client.default-to-properties 改为 false。
如果我们想创建多个具有相同名称或网址的feign客户端,使它们指向同一台服务器,但每个都有不同的自定义配置,那么我们必须使用 @FeignClient 的 contextId 属性,以避免这些配置 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() {@Overridepublic 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 从连接建立时开始应用,当返回响应的时间过长时就会被触发。
如果服务器没有运行或可用,则数据包会导致连接被拒绝。通信以错误信息或 fallback 的方式结束。如果 connectTimeout 设置得很低,这可能在它之前发生。执行查找和接收这种数据包所需的时间导致了这一延迟的重要部分。它可能根据涉及DNS查询的远程主机而改变。 |
1.4. 手动创建 Feign Client
在某些情况下,可能需要对你的 Feign 客户进行定制,而使用上述方法是不可能的。在这种情况下,你可以使用 Feign Builder API 来创建客户端。下面是一个例子,它创建了两个具有相同接口的 Feign 客户端,但每个客户端都配置了一个单独的请求拦截器(request interceptor)。
@Import(FeignClientsConfiguration.class)
class FooController {private FooClient fooClient;private FooClient adminClient;@Autowiredpublic 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 在 classpath 上,并且 spring.cloud.openfeign.circuitbreaker.enabled=true,Feign 将用 circuit breaker 来包装所有方法。
为了在每个客户端的基础上禁用 Spring Cloud CircuitBreaker 的支持,创建一个具有 "prototype" scope 的 vanilla Feign.Builder,例如:
@Configuration
public class FooConfiguration {@Bean@Scope("prototype")public Feign.Builder feignBuilder() {return Feign.builder();}
}
circuit breaker 的名称遵循这种模式 <feignClientClassName>#<calledMethod>(<parameterTypes>)。当调用一个带有 FooClient 接口的 @FeignClient,并且被调用的接口方法 bar 没有参数,那么 circuit breaker 的名称将是 FooClient#bar()。
从2020.0.2开始,circuit breaker 名称模式已经从 <feignClientName>_<calledMethod> 改变。使用2020.0.4中引入的 CircuitBreakerNameResolver,circuit breaker 名称可以保留旧模式。 |
提供一个 CircuitBreakerNameResolver 的bean,你可以改变 circuit breaker 名称模式。
@Configuration
public class FooConfiguration {@Beanpublic CircuitBreakerNameResolver circuitBreakerNameResolver() {return (String feignClientName, Target<?> target, Method method) -> feignClientName + "_" + method.getName();}
}
要启用 Spring Cloud CircuitBreaker group,请将 spring.cloud.openfeign.circuitbreaker.group.enabled 属性设置为 true(默认为 false)。
1.6. 使用配置属性配置 CircuitBreaker
你可以通过配置属性来配置 CircuitBreaker。
例如,如果你有这个 Feign 客户端
@FeignClient(url = "http://localhost:8080")
public interface DemoClient {@GetMapping("demo")String getDemo();
}
你可以通过以下方式使用配置属性来配置它
spring:cloud:openfeign:circuitbreaker:enabled: truealphanumeric-ids:enabled: true
resilience4j:circuitbreaker:instances:DemoClientgetDemo:minimumNumberOfCalls: 69timelimiter:instances:DemoClientgetDemo:timeoutDuration: 10s
如果你想切换回 Spring Cloud 2022.0.0 之前使用的 circuit breaker name,你可以将 spring.cloud.openfeign.circuitbreaker.alphanumeric-ids.enabled 设置为 false。 |
1.7. Feign Spring Cloud CircuitBreaker Fallback
Spring Cloud CircuitBreaker 支持 fallback 的概念:一个默认的代码路径,在 circuit 打开或出现错误时执行。要为一个给定的 @FeignClient 启用 fallback,将 fallback 属性设置为实现 fallback 的类名。你还需要将你的实现声明为一个 Spring Bean。
@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();}@Componentstatic class Fallback implements TestClient {@Overridepublic Hello getHello() {throw new NoFallbackAvailableException("Boom!", new RuntimeException());}@Overridepublic String getException() {return "Fixed response";}}
如果需要访问使 fallback 触发的原因,可以使用 @FeignClient 里面的 fallbackFactory 属性。
@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();}@Componentstatic class TestFallbackFactory implements FallbackFactory<FallbackWithFactory> {@Overridepublic FallbackWithFactory create(Throwable cause) {return new FallbackWithFactory();}}static class FallbackWithFactory implements TestClientWithFactory {@Overridepublic Hello getHello() {throw new NoFallbackAvailableException("Boom!", new RuntimeException());}@Overridepublic String getException() {return "Fixed response";}}
1.8. Feign 和@Primary
当使用 Feign 与 Spring Cloud CircuitBreaker fallback 时,ApplicationContext 中存在多个相同类型的Bean。这将导致 @Autowired 不起作用,因为没有确切的一个 bean,或一个被标记为 primary 的 bean。为了解决这个问题,Spring Cloud OpenFeign 将所有Feign实例标记为 @Primary,因此 Spring Framework 将知道要注入哪个Bean。在某些情况下,这可能是不可取的。要关闭这种行为,请将 @FeignClient 的 primary 属性设置为 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 request/response 压缩
你可以考虑为你的 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 使用 "transparent"(透明) 压缩,即在存在 content-encoding 或 accept-encoding 头的情况下禁用,所以当 feign.okhttp.OkHttpClient 出现在 classpath 上并且 spring.cloud.openfeign.okhttp.enabled 被设置为 true 时,我们不会启用压缩。 |
1.11. Feign 日志
每个创建的 Feign 客户端都会创建一个logger。默认情况下,logger 的名字是用于创建Feign客户端的接口的全类名称。Feign 的日志只响应 DEBUG 级别。
application.yml
logging.level.project.user.UserClient: DEBUG
你可以为每个客户端配置 Logger.Level 对象,告诉 Feign 要记录多少内容。选择是:
- NONE, 没日志(默认)。
- BASIC, 只记录请求方法和URL以及响应状态代码和执行时间。
- HEADERS, 记录基本信息以及请求和响应头。
- FULL, 记录请求和响应的header、正文和元数据。
例如,下面将设置 Logger.Level 为 FULL:
@Configuration
public class FooConfiguration {@BeanLogger.Level feignLoggerLevel() {return Logger.Level.FULL;}
}
1.12. Feign Capability 的支持
Feign Capability 暴露了Feign的核心组件,因此这些组件可以被修改。例如,这些功能可以接受客户端,对其进行装饰,并将装饰后的实例反馈给 Feign。对 Micrometer 的支持就是一个很好的现实生活中的例子。参见 [micrometer-support]。
创建一个或多个 Capability Bean并将其置于 @FeignClient 配置中,可以让你注册它们并修改相关客户端的行为。
@Configuration
public class FooConfiguration {@BeanCapability customCapability() {return new CustomCapability();}
}
1.13. Micrometer 的支持
如果以下所有条件为 true,就会创建并注册一个 MicrometerObservationCapability Bean,这样你的 Feign 客户端就可以被 Micrometer 观察到:
- feign-micrometer 在 classpath 上。
- ObservationRegistry bean 可用。
- feign micrometer 属性设置为 true (默认)
- spring.cloud.openfeign.micrometer.enabled=true (针对所有客户)
- spring.cloud.openfeign.client.config.feignName.micrometer.enabled=true (针对单个客户端)
如果你的应用程序已经使用了 Micrometer,启用这个功能就像把 feign-micrometer 放到你的classpath上一样简单。 |
你也可以通过以下两种方式禁用该功能:
- 从你的 classpath 中排除 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 {@Beanpublic MicrometerObservationCapability micrometerObservationCapability(ObservationRegistry registry) {return new MicrometerObservationCapability(registry);}
}
仍然可以在 Feign 中使用 MicrometerCapability(仅支持指标),你需要禁用 Micrometer 支持(spring.cloud.openfeign.micrometer.enabled=false)并创建一个 MicrometerCapability Bean:
@Configuration
public class FooConfiguration {@Beanpublic 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参数注解为查询参数map。
例如,Params 类定义了参数 param1 和 param2:
// 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);
}
如果你需要对生成的查询参数 Map 有更多控制,你可以实现一个自定义的 QueryMapEncoder Bean。
1.16. HATEOAS 的支持
Spring提供了一些API来创建遵循 HATEOAS 原则的REST表示, Spring Hateoas 和 Spring Data REST。
如果你的项目使用 org.springframework.boot:spring-boot-starter-hateoas starter 或 org.springframework.boot:spring-boot-starter-data-rest starter,Feign HATEOAS 支持被默认启用。
当HATEOAS支持被启用时,Feign 客户端被允许序列化和反序列化 HATEOAS 表示模型: EntityModel、 CollectionModel 和 PagedModel.。
@FeignClient("demo")
public interface DemoTemplate {@GetMapping(path = "/stores")CollectionModel<Store> getStores();
}
1.17. Spring @MatrixVariable 的支持
Spring Cloud OpenFeign提供对Spring @MatrixVariable 注解的支持。
如果一个 map 被作为方法参数传递,@MatrixVariable path 段是通过用 = 连接 map 中的键值对而创建的。
如果传递了一个不同的对象,那么在 @MatrixVariable 注解中提供的 name(如果定义了的话)或者注解的变量名称将使用 = 与提供的方法参数结合起来。
IMPORTANT
尽管在服务器端,Spring 并不要求用户将路径段占位符的名称与 matrix variable 的名称相同,因为这在客户端太模糊了,Spring Cloud OpenFeign要求你添加一个路径段占位符,其名称要与 @MatrixVariable 注解(如果定义了)中提供的 name 或注解的变量名称相符。
例如:
@GetMapping("/objects/links/{matrixVars}")
Map<String, List<String>> getObjects(@MatrixVariable Map<String, List<String>> matrixVars);
注意,变量名和 path 段占位符都被称为 matrixVars。
@FeignClient("demo")
public interface DemoTemplate {@GetMapping(path = "/stores")CollectionModel<Store> getStores();
}
1.18. FeignCollectionFormat的支持
我们通过提供 @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 客户端的方式,你可能会在启动你的应用程序时看到初始化错误。为了解决这个问题,你可以在自动连接客户端时使用一个 ObjectProvider。
@Autowired
ObjectProvider<TestFeignClient> testFeignClient;
1.20. Spring Data 的支持
如果 Jackson Databind 和 Spring Data Commons 在classpath上,org.springframework.data.domain.Page 和 org.springframework.data.domain.Sort 的 converter 将被自动添加。
要禁用这种行为,请设置:
spring.cloud.openfeign.autoconfiguration.jackson.enabled=false
详见 org.springframework.cloud.openfeign.FeignAutoConfiguration.FeignJacksonConfiguration。
1.21. Spring@RefreshScope的支持
如果启用了Feign客户端刷新,每个Feign客户端的创建都有:
- feign.Request.Options 作为一个 refresh scope 的bean。这意味着诸如 connectTimeout 和 readTimeout 等属性可以针对任何Feign客户端实例进行刷新。
- 在 org.springframework.cloud.openfeign.RefreshableUrl 下包装的url。这意味着如果用 spring.cloud.openfeign.client.config.{feignName}.url 属性定义 Feign 客户端的URL,可以针对任何 Feign 客户端实例进行刷新。
你可以通过 POST /actuator/refresh 刷新这些属性。
默认情况下,Feign 客户端的刷新行为是禁用的。使用以下属性来启用刷新行为:
spring.cloud.openfeign.client.refresh-enabled=true
不要用 @RefreshScope 注解来注解 @FeignClient 接口。 |
1.22. OAuth2 的支持
可以通过设置以下标志启用OAuth2支持:
spring.cloud.openfeign.oauth2.enabled=true
当该标志被设置为 "true",且oauth2客户端 context resource detail 存在时,就会创建一个 OAuth2AccessTokenInterceptor 类的 bean。在每次请求之前,拦截器都会解析所需的访问令牌,并将其作为一个header。OAuth2AccessTokenInterceptor 使用 OAuth2AuthorizedClientManager 来获取持有 OAuth2AccessToken 的 OAuth2AuthorizedClient。如果用户使用 spring.cloud.openfeign.oauth2.clientRegistrationId 属性指定了一个 OAuth2 clientRegistrationId,它将被用来检索令牌。如果没有检索到令牌或没有指定 clientRegistrationId,将使用从 url host 段检索的 serviceId。
TIP
使用 serviceId 作为 OAuth2 客户端的 registrationId 对于负载均衡的Feign客户端是很方便的。对于非负载均衡的客户端,基于属性的 clientRegistrationId 是一个合适的方法。
TIP
如果你不想使用 OAuth2AuthorizedClientManager 的默认设置,你可以直接在你的配置中实例化一个这种类型的bean。
1.23. 转换负载均衡的HTTP请求
你可以使用选定的 ServiceInstance 来转换负载均衡的HTTP请求。
对于 Request,你需要实现和定义 LoadBalancerFeignRequestTransformer,如下所示:
@Bean
public LoadBalancerFeignRequestTransformer transformer() {return new LoadBalancerFeignRequestTransformer() {@Overridepublic 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-Host 和 X-Forwarded-Proto 支持可以通过设置以下标志启用:
spring.cloud.loadbalancer.x-forwarded.enabled=true
1.25. 支持向 Feign 客户端提供URL的方法
你可以通过以下任何一种方式向Feign客户端提供一个URL:
场景 | 例子 | 细节 |
URL是在 @FeignClient 注解中提供的。 | @FeignClient(name="testClient", url="http://localhost:8081") | URL是从注解的 url 属性中解析出来的,没有负载均衡。 |
URL是在 @FeignClient 注解和配置属性中提供的。 | @FeignClient(name="testClient", url="http://localhost:8081") 和定义在 application.yml 中的属性 spring.cloud.openfeign.client.config.testClient.url=http://localhost:8081 | URL是从注解的 url 属性中解析出来的,没有负载均衡。在配置属性中提供的URL仍未使用。 |
URL没有在 @FeignClient 注解中提供,而是在配置属性中提供。 | @FeignClient(name="testClient") 和定义在 application.yml 中的属性 spring.cloud.openfeign.client.config.testClient.url=http://localhost:8081 | URL 从配置属性中解析,没有负载均衡。如果 spring.cloud.openfeign.client.refresh-enabled=true,那么配置属性中定义的 URL 可以被刷新,如 Spring RefreshScope 的支持 中所述。 |
在 @FeignClient 注解中和配置属性中都没有提供这个URL。 | @FeignClient(name="testClient") | URL是从注解的 name 属性中解析出来的,具有负载均衡性。 |
1.26. AOT 和原生镜像的支持
Spring Cloud OpenFeign 支持 Spring AOT 转换和原生镜像,但是,只有在禁用刷新模式、禁用Feign客户端刷新(默认设置)和禁用 延迟的 @FeignClient 属性解析(默认设置)的情况下,才能支持。
如果你想在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 值,那么通过运行带有 -Dspring.cloud.openfeign.client.config.[clientId].url=[url] 标志的镜像,就有可能覆盖 @FeignClient 的 url 值。为了实现覆盖,在构建时也必须通过属性而不是 @FeignClient 属性来设置一个 url 值。 |
2. 配置属性
各种属性可以在 application.properties
文件、application.yml
文件中指定,也可以作为命令行开关。本附录提供了一个常见的 Spring Cloud OpenFeign 属性列表,以及对消费这些属性的底层类的引用。
属性贡献可以来自你classpath上的其他jar文件,所以你不应该认为这是一个详尽的列表。另外,你可以定义你自己的属性。 |
Name | Default | Description |
---|---|---|
spring.cloud.openfeign.autoconfiguration.jackson.enabled |
| If true, PageJacksonModule and SortJacksonModule bean will be provided for Jackson page decoding. |
spring.cloud.openfeign.circuitbreaker.enabled |
| If true, an OpenFeign client will be wrapped with a Spring Cloud CircuitBreaker circuit breaker. |
spring.cloud.openfeign.circuitbreaker.group.enabled |
| If true, an OpenFeign client will be wrapped with a Spring Cloud CircuitBreaker circuit breaker with with group. |
spring.cloud.openfeign.client.config | ||
spring.cloud.openfeign.client.decode-slash |
| Feign clients do not encode slash |
spring.cloud.openfeign.client.default-config |
| |
spring.cloud.openfeign.client.default-to-properties |
| |
spring.cloud.openfeign.client.refresh-enabled |
| Enables options value refresh capability for Feign. |
spring.cloud.openfeign.compression.request.enabled |
| Enables the request sent by Feign to be compressed. |
spring.cloud.openfeign.compression.request.mime-types |
| The list of supported mime types. |
spring.cloud.openfeign.compression.request.min-request-size |
| The minimum threshold content size. |
spring.cloud.openfeign.compression.response.enabled |
| Enables the response from Feign to be compressed. |
spring.cloud.openfeign.encoder.charset-from-content-type |
| Indicates whether the charset should be derived from the {@code Content-Type} header. |
spring.cloud.openfeign.httpclient.connection-timeout |
| |
spring.cloud.openfeign.httpclient.connection-timer-repeat |
| |
spring.cloud.openfeign.httpclient.disable-ssl-validation |
| |
spring.cloud.openfeign.httpclient.enabled |
| Enables the use of the Apache HTTP Client by Feign. |
spring.cloud.openfeign.httpclient.follow-redirects |
| |
spring.cloud.openfeign.httpclient.hc5.enabled |
| Enables the use of the Apache HTTP Client 5 by Feign. |
spring.cloud.openfeign.httpclient.hc5.pool-concurrency-policy | Pool concurrency policies. | |
spring.cloud.openfeign.httpclient.hc5.pool-reuse-policy | Pool connection re-use policies. | |
spring.cloud.openfeign.httpclient.hc5.socket-timeout |
| Default value for socket timeout. |
spring.cloud.openfeign.httpclient.hc5.socket-timeout-unit | Default value for socket timeout unit. | |
spring.cloud.openfeign.httpclient.max-connections |
| |
spring.cloud.openfeign.httpclient.max-connections-per-route |
| |
spring.cloud.openfeign.httpclient.ok-http.read-timeout |
| {@link OkHttpClient} read timeout; defaults to 60 seconds. |
spring.cloud.openfeign.httpclient.time-to-live |
| |
spring.cloud.openfeign.httpclient.time-to-live-unit | ||
spring.cloud.openfeign.micrometer.enabled |
| Enables Micrometer capabilities for Feign. |
spring.cloud.openfeign.oauth2.enabled |
| Enables feign interceptor for managing oauth2 access token. |
spring.cloud.openfeign.oauth2.load-balanced |
| Enables load balancing for oauth2 access token provider. |
spring.cloud.openfeign.okhttp.enabled |
| Enables the use of the OK HTTP Client by Feign. |
相关文章:
Spring Cloud OpenFeign 全教程
1. 声明式 REST 客户端: Feign Feign 是一个声明式的 Web Service 客户端。它使编写 Web Service 客户端更容易。要使用 Feign,需要创建一个接口并对其进行注解。它有可插拔的注解支持,包括 Feign 注解和 JAX-RS 注解。Feign 还支持可插拔的…...

LLaMA模型论文《LLaMA: Open and Efficient Foundation Language Models》阅读笔记
文章目录 1. 简介2.方法2.1 预训练数据2.2 网络架构2.3 优化器2.4 高效的实现 3.论文其余部分4. 参考资料 1. 简介 LLaMA是meta在2023年2月开源的大模型,在这之后,很多开源模型都是基于LLaMA的,比如斯坦福大学的羊驼模型。 LLaMA的重点是比…...

了解Unity编辑器 之组件篇Effects(十一)
一、Halo:是一个可用于游戏对象的特效组件,它可以在对象周围添加一个光晕效果 Color属性: 用于设置Halo的颜色。你可以通过选择颜色面板中的颜色来指定光晕的外观。选择适当的颜色可以使光晕与游戏场景中的其他元素相匹配或突出显示。 Size属性: 用于设…...
笔记整理-SpringBoot中的扩展点
SpringBoot有哪些扩展点 aware 感知类接口 aware系列的扩展接口,允许spring应用感知/获取特定的上下文环境或对象。bean生命周期控制类接口 bean生命周期类的接口,可以控制spring容器对bean的处理。app生命周期控制类接口 app生命周期控制类接口…...
各系统的目录信息路径
Windows系统: 查看系统版本——C:\boot.ini IIS配置文件——C:\windows\system32\inetsrv\MetaBase.xml 存储Windows系统初次安装的密码——C:\windows\repair\sam Mysql配置——C:\ProgramFiles\mysql\my.ini MySQL root密码——C:\P…...
Asp.Net 使用Log4Net (封装帮助类)
Asp.Net 使用Log4Net (封装帮助类) 1. 创建Log4Net帮助类 首先,在你的项目中创建一个Log4Net帮助类,用于封装Log4Net的配置和日志记录逻辑。 using log4net; using log4net.Config;public class LogHelper {private static readonly ILog log LogMan…...

全志F1C200S嵌入式驱动开发(lcd屏幕驱动)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 lcd RGB屏幕作为比较经济、实用的显示工具,在实际场景中使用较多。它的信号来说,一般也比较简单,除了常规的数据信号,剩下来就是行同步、场同步、数据使能和时钟信号了。数据信…...

dubbo原理框架设计
dubbo原理框架设计 (1)config 配置层:对外配置接口,以 ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类。 (2)proxy 服务代理…...

【数据挖掘】使用 LSTM 进行时间和序列预测
一、说明 每天,人类在执行诸如过马路之类的任务时都会做出被动预测,他们估计汽车的速度和与汽车的距离,或者通过猜测球的速度并相应地定位手来接球。这些技能是通过经验和实践获得的。然而,由于涉及众多变量,预测天气或…...
Typescript第四章 函数(声明和调用,注解参数类型,多态,类型别名,泛型)
第四章 函数 ts中声明和调用函数的不同方式签名重载多态函数多态类型声明 4.1 声明和调用函数 在js中函数是一等对象,我们可以像对象那样使用函数,可以复制给变量,可以作为参数传递,返回值,赋值给对象的原型&#x…...

大数据-Spark批处理实用广播Broadcast构建一个全局缓存Cache
1、broadcast广播 在Spark中,broadcast是一种优化技术,它可以将一个只读变量缓存到每个节点上,以便在执行任务时使用。这样可以避免在每个任务中重复传输数据。 2、构建缓存 import org.apache.spark.sql.SparkSession import org.apache.s…...
Android Service的生命周期,两种启动方法,有什么区别
Android Service的生命周期,两种启动方法,有什么区别 Android Service是一种后台组件,用于在后台执行长时间运行的任务,而无需与用户界面进行交互。Service具有自己的生命周期,其主要包含以下几个状态:创建…...

测试开源C#人脸识别模块ViewFaceCore(5:质量检测和眼睛状态检测)
ViewFaceCore模块中的FaceQuality支持预测人脸质量,最初以为是预测人体体重,实际测试过程中才发现是评估人脸图片质量,主要调用Detect函数执行图片质量检测操作,其函数原型如下所示: //// 摘要:// 人脸质量评估///…...
Go语言网络库net/http
Go语言网络库net/http Http 协议(Hyper Text Transfer Protocol,超文本传输协议)是一个简单的请求-响应协议,它通常运行在 TCP 之 上。超文本传输协议是互联网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。 Http 协…...

Acwing.91 最短Hamilton路径(动态规划)
题目 给定一张n个点的带权无向图,点从0~n-1标号,求起点0到终点n-1的最短Hamilton路径。Hamilton路径的定义是从0到n-1不重不漏地经过每个点恰好一次。 输入格式 第—行输入整数n。 接下来n行每行n个整数,其中第i行第j个整数表示点i到j的距…...
[hfut] [important] v4l2 vedio使用总结/opevx/ffpeg/v4l2/opencv/cuda
(158条消息) linux驱动camera//test ok_感知算法工程师的博客-CSDN博客 (158条消息) linux V4L2子系统——v4l2架构(1)之整体架构_感知算法工程师的博客-CSDN博客 (158条消息) linux V4L2子系统——v4l2的结构体(2)之video_devi…...

2023年深圳杯数学建模A题影响城市居民身体健康的因素分析
2023年深圳杯数学建模 A题 影响城市居民身体健康的因素分析 原题再现: 以心脑血管疾病、糖尿病、恶性肿瘤以及慢性阻塞性肺病为代表的慢性非传染性疾病(以下简称慢性病)已经成为影响我国居民身体健康的重要问题。随着人们生活方式的改变&am…...

指令调度(Instruction Scheduling)
指令调度(Instruction Scheduling) 指令调度的约束基本机器模型基本块调度全局调度 指令调度是为了提高指令级并行(ILP),对于超长指令字(VLIW, Very Long Instruction Word)和多发射系统&#x…...
【运维】Linux 跨服务器复制文件文件夹
【运维】Linux 跨服务器复制文件文件夹 如果是云服务 建议用内网ip scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。可能会稍微影…...
k8s apiserver如何支持http访问?
原本是可以通过设置api-server的--insecure-port来实现,但是这个参数已经被废弃了,更好的方法则是使用proxy来实现: 在集群任意一个节点上起一个proxy服务,并设置允许所有host访问: kubectl proxy --address0.0.0.0 …...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...

Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
WEB3全栈开发——面试专业技能点P4数据库
一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库,基于 mysql 库改进而来,具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点: 支持 Promise / async-await…...

C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。
2024 年,高端封装市场规模为 80 亿美元,预计到 2030 年将超过 280 亿美元,2024-2030 年复合年增长率为 23%。 细分到各个终端市场,最大的高端性能封装市场是“电信和基础设施”,2024 年该市场创造了超过 67% 的收入。…...