大数跨境
0
0

从静态到动态!Spring Boot 动态创建配置Feign Client

从静态到动态!Spring Boot 动态创建配置Feign Client Spring全家桶实战案例
2025-09-03
1
导读:从静态到动态!Spring Boot 动态创建配置Feign Client
Spring Boot 3实战案例锦集PDF电子书已更新至130篇!
图片

🎉🎉《Spring Boot实战案例合集》目前已更新164个案例,我们将持续不断的更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务

💌💌如何获取
订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

→ 现在就订阅合集

环境:SpringBoot3.4.2



1. 简介

在微服务架构中,Feign堪称开发者的得力助手——它是一款声明式的HTTP客户端,能让调用其他服务变得像编写接口一样简单。然而,如果你的Feign客户端配置(如基础URL、超时时间或认证信息)需要动态化,那该怎么办呢?

将这类值硬编码在application.yml文件中,对于静态环境而言尚可接受,但在实际场景中,我们往往需要运行时灵活性:

  • 多租户应用中,每个客户的API端点可能各不相同

  • 从数据库或配置服务器获取的环境特定配置

  • 根据业务逻辑动态路由到不同的微服务

本篇文章我们将通过数据库动态配置Feign客户端。

2.实战案例

2.1 定义Feign基本配置实体

@Entity@Table(name = "t_feign_config")public class FeignConfig {  @Id  @GeneratedValue(strategy = GenerationType.IDENTITY)  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<FeignConfigLong> {  /**根据clientName查询Feign配置*/  Optional<FeignConfig> findByClientName(String clientName) ;}

2.3 定义Service

@Servicepublic 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客户端创建工厂

@Componentpublic 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 测试

@RestController@RequestMapping("/test")public class TestController {  private final FeignClientFactory factory;  public TestController(FeignClientFactory factory) {    this.factory = factory;  }  @GetMapping("/user/query")  public UserDTO query() {    return this.factory        .getClient(UserClient.class"user-client")        .query() ;  }}

调用的接口

@RestController@RequestMapping("/users")public class UserController {  @GetMapping("/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 动态配置请求超时时间

首先,准备三方接口(模拟耗时)

@GetMapping("/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")      ) ;  // 模拟耗时4s  TimeUnit.SECONDS.sleep(4) ;  return ResponseEntity.ok(users) ;}

其次,定义Feign接口

@FeignClient(name = "user-client", url = "http://localhost:8080")public interface UserDefaultClient {
  @GetMapping("/users/list")  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 ;}@GetMapping("/user/list2")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: /ac      exposure:        include:        - refresh

我们再次启动服务;启动服务后,我们直接修改配置如下:

spring:  cloud:    openfeign:      client:        config:          user-client:            read-timeout: 5000

接着调用 /ac/refresh 接口

发现了配置的变化,再次访问接口

动态刷新配置成功。

2.7 动态刷新请求URL

首先,修改Feign定义接口如下:

@FeignClient(name = "user-client")public interface UserDefaultClient {
  @GetMapping("/users/list")  List<UserDTO> list() ;}

注意:这里我们并没有定义url属性,我们会在配置文件中定义。

其次,配置文件中定义user-client客户端请求的url

spring:  cloud:    openfeign:      client:        config:          user-client:            urlhttp://localhost:8080

最后,我们还是访问上面的接口

成功;修改请求的url如下:

spring:  cloud:    openfeign:      client:        config:          user-client:            urlhttp://localhost:8081

将端口改错;接下来,调用/ac/refresh接口

再次访问接口

连接错误了,请求的端口变为8081。



以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

优雅!Spring Boot 动态任务调度,灵活又强大

一个接口,N 种实现?Spring Boot 中的10种切换方式

别再错过!Spring Boot 12个高级开发技巧,助你成为大神

拒绝重复造轮子!Spring Boot 六大核心AOP切面,开发必备

性能优化!3种方案优化Controller接口调用,性能提升N倍

Controller 接口竟有这些 "神操作"?

Spring Boot 记录Controller接口请求日志7种方式,第六种性能极高

高级开发!Spring Boot 一个注解实现远程接口调用

太强了!Spring Boot 百万级Excel读写仅需5秒,这波操作封神!

太强了!动态脚本引擎QLExpress,实现各种复杂的业务规则

Spring Boot 内置多版本API接口控制

强大!Spring Boot 一个注解导出任意Excel

图片
图片
图片
图片
图片
图片
图片
图片
图片

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读285
粉丝0
内容832