一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

怎么通过环境变量动态切换容器内数据源实现一键变环境

时间:2026-07-10 09:49:03 编辑:袖梨 来源:一聚教程网

核心思路是利用Spring Boot的profile机制结合AbstractRoutingDataSource,在启动时读取环境变量(如spring.profiles.active),通过ApplicationContext动态注册数据源,并在运行时基于ThreadLocal与AOP实现方法级数据源路由,无需改代码、不重启即可完成环境切换。

核心思路是让 spring boot 启动时读取环境变量(如 spring.profiles.active),结合 applicationcontextabstractroutingdatasource,在容器初始化阶段或运行时动态注册/路由到对应数据源,无需改代码、不重启服务即可完成环境切换。

一、用 profile + 多配置文件定义环境差异

这是最轻量、最标准的起点。Spring Boot 会自动加载 application-{profile}.yml 文件,并根据激活的 profile 决定使用哪套配置。

  • 在 application.yml 中统一声明激活策略:
    spring:
      profiles:
        active: @spring.profiles.active@(Maven 构建时注入)或直接设为 dev
  • 创建独立配置文件:
    application-dev.yml → H2 内存库
    application-test.yml → 测试 MySQL 实例
    application-prod.yml → 生产集群地址+连接池参数
  • 启动时指定:
    java -jar app.jar --spring.profiles.active=prod
    或通过系统环境变量:
    export SPRING_PROFILES_ACTIVE=prod

二、用 ApplicationContextAware 动态注册数据源 Bean

适用于需要在容器启动后、Bean 创建前就完成数据源绑定的场景(比如某些依赖 DataSource 的组件必须早于数据源初始化)。

  • 实现 ApplicationContextAwareEnvironmentAware,拿到容器和当前 profile
  • @PostConstruct 或自定义初始化方法中,调用 applicationContext.getBeanFactory().registerSingleton() 注册对应数据源实例
  • 关键点:注册的 Bean 名必须与后续 @PrimarySqlSessionFactory 引用的名称一致,否则注入失败

三、用 AbstractRoutingDataSource 实现运行时路由

这是最灵活、最常用的动态切换方式,支持方法级、事务级甚至请求级的数据源选择。

  • 继承 AbstractRoutingDataSource,重写 determineCurrentLookupKey()
  • 配合 ThreadLocal<String> 存储当前线程要使用的数据源标识(如 "master""slave""history"
  • 通过 AOP 切面或自定义注解(如 @DS("test"))在方法执行前设置 ThreadLocal 值,执行后清理
  • 所有数据库操作最终都经过这个 RoutingDataSource,它根据 ThreadLocal 返回的 key 查找预注册的目标数据源

四、Docker/K8s 环境下对接外部环境变量

生产部署时,环境变量通常由运维侧注入,应用只需“读取并响应”。

  • Docker 启动:
    docker run -e SPRING_PROFILES_ACTIVE=prod -e DB_URL=jdbc:mysql://db-prod:3306/mydb ...
  • Kubernetes ConfigMap/Secret 挂载:
    application-prod.yml 内容以键值对形式存入 ConfigMap,挂载为 volume 或 envFrom
  • 注意:Spring Boot 默认只从 SPRING_PROFILES_ACTIVEspring.profiles.active 读取 profile,其他变量需在配置中显式引用,例如:
    spring.datasource.url=${DB_URL:jdbc:h2:mem:test}

热门栏目