🎉🎉《Spring Boot实战案例合集》目前已更新164个案例,我们将持续不断的更新。文末有电子书目录。
💪💪永久更新承诺
我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务。
💌💌如何获取
订阅我们的合集《点我订阅》,并通过私信联系我们,我们将第一时间将电子书发送给您。
环境:SpringBoot3.4.2
1. 简介
在微服务架构中,Feign堪称开发者的得力助手——它是一款声明式的HTTP客户端,能让调用其他服务变得像编写接口一样简单。然而,如果你的Feign客户端配置(如基础URL、超时时间或认证信息)需要动态化,那该怎么办呢?
将这类值硬编码在application.yml文件中,对于静态环境而言尚可接受,但在实际场景中,我们往往需要运行时灵活性:
多租户应用中,每个客户的API端点可能各不相同
从数据库或配置服务器获取的环境特定配置
根据业务逻辑动态路由到不同的微服务
本篇文章我们将通过数据库动态配置Feign客户端。
2.1 定义Feign基本配置实体
public class FeignConfig {private Long id ;/**客户端名称*/private String clientName ;/**该客户端的baseUrl*/private String baseUrl ;/**请求超时配置*/private Long connectTimeout ;private Long readTimeout ;private String apiKey ;// getters, setters}
该实体对象中我们定义了Feign客户端所需要的基本信息。准备如下数据:
2.2 定义Repository接口
在该Repository中,我们仅提供了一个方法,通过clientName查询对应的配置详细。
public interface FeignConfigRepository extends JpaRepository<FeignConfig, Long> {/**根据clientName查询Feign配置*/Optional<FeignConfig> findByClientName(String clientName) ;}
2.3 定义Service
public class FeignConfigService {private final FeignConfigRepository configRepository ;public FeignConfigService(FeignConfigRepository configRepository) {this.configRepository = configRepository;}public FeignConfig getClientConfig(String clientName) {return configRepository.findByClientName(clientName).orElseThrow(() -> new RuntimeException("Feign 配置不存在: " + clientName));}}
2.4 Feign客户端创建工厂
public class FeignClientFactory {private final FeignConfigService configService;private final ObjectFactory<HttpMessageConverters> messageConverters ;public FeignClientFactory(FeignConfigService configService,ObjectFactory<HttpMessageConverters> messageConverters) {this.configService = configService;this.messageConverters = messageConverters ;}public <T> T getClient(Class<T> clientType, String clientName) {FeignConfig config = configService.getClientConfig(clientName) ;Request.Options options = new Request.Options(config.getConnectTimeout(), TimeUnit.MILLISECONDS,config.getReadTimeout(), TimeUnit.MILLISECONDS, false);return Feign.builder().encoder(new SpringEncoder(this.messageConverters)).decoder(new SpringDecoder(messageConverters)).contract(new SpringMvcContract()).retryer(Retryer.NEVER_RETRY).requestInterceptor(template -> template.header("Authorization", "Bearer " + config.getApiKey())).options(options).target(clientType, config.getBaseUrl()) ;}}
每次在调用时都从数据库中获取最新的配置创建对象。
2.5 测试
public class TestController {private final FeignClientFactory factory;public TestController(FeignClientFactory factory) {this.factory = factory;}public UserDTO query() {return this.factory.getClient(UserClient.class, "user-client").query() ;}}
调用的接口
("/users")public class UserController {("/query")public ResponseEntity<?> query() {return ResponseEntity.ok(new User("pack", "123123", new Date(), "xxgg@qq.com")) ;}}
执行结果
以上我们就完成了基于数据库的Feign的动态配置。
默认情况下,spring-cloud-openfeign 已经提供了一定程度的动态配置支持,尤其在以下两个关键场景中表现尤为突出:
动态配置请求超时时间
动态刷新请求的url
接下来,我们将通过具体代码示例,演示如何利用 spring-cloud-openfeign 的现有能力实现上述两种动态配置功能,帮助你快速掌握这一核心特性。
2.6 动态配置请求超时时间
首先,准备三方接口(模拟耗时)
("/list")public ResponseEntity<?> list() throws Exception {List<User> users = List.of(new User("张三", "111111", new Date(), "zs@gmail.com"),new User("李四", "222222", new Date(), "ls@gmail.com"),new User("王五", "333333", new Date(), "ww@gmail.com"),new User("赵六", "444444", new Date(), "zl@gmail.com")) ;// 模拟耗时4sTimeUnit.SECONDS.sleep(4) ;return ResponseEntity.ok(users) ;}
其次,定义Feign接口
public interface UserDefaultClient {List<UserDTO> list() ;}
最后,为user-client配置超时时间
spring:cloud:openfeign:client:config:user-client:read-timeout: 3000
设置读数据超时时间为3s(我们上面接口模拟了4s才会输出内容)。
测试接口
private final UserDefaultClient defaultClient ;public TestController(UserDefaultClient defaultClient) {this.defaultClient = defaultClient ;}public List<UserDTO> list2() {return this.defaultClient.list() ;}
抛出了超时异常。
接下来,我们引入actuator
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
配置actuator
management:endpoints:web:base-path: /acexposure:include:- refresh
我们再次启动服务;启动服务后,我们直接修改配置如下:
spring:cloud:openfeign:client:config:user-client:read-timeout: 5000
接着调用 /ac/refresh 接口
发现了配置的变化,再次访问接口
动态刷新配置成功。
2.7 动态刷新请求URL
首先,修改Feign定义接口如下:
public interface UserDefaultClient {List<UserDTO> list() ;}
注意:这里我们并没有定义url属性,我们会在配置文件中定义。
其次,配置文件中定义user-client客户端请求的url
spring:cloud:openfeign:client:config:user-client:url: http://localhost:8080
最后,我们还是访问上面的接口
成功;修改请求的url如下:
spring:cloud:openfeign:client:config:user-client:url: http://localhost:8081
将端口改错;接下来,调用/ac/refresh接口
再次访问接口
连接错误了,请求的端口变为8081。
推荐文章
一个接口,N 种实现?Spring Boot 中的10种切换方式
别再错过!Spring Boot 12个高级开发技巧,助你成为大神
拒绝重复造轮子!Spring Boot 六大核心AOP切面,开发必备
性能优化!3种方案优化Controller接口调用,性能提升N倍
Spring Boot 记录Controller接口请求日志7种方式,第六种性能极高
太强了!Spring Boot 百万级Excel读写仅需5秒,这波操作封神!
太强了!动态脚本引擎QLExpress,实现各种复杂的业务规则


