MyBatis-plus:dynamic-datasource :手动注入多数据源

4,033 阅读2分钟

公司有个需求:通过数据库配置和前端请求,在数据库中执行一段脚本。这个需求的核心是配置动态数据源,而且需要在程序运行中配置多数据源。我这里用到了dynamic-datasource 的数据源扩展点实现此功能。

maven 坐标

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.4.0</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.22</version>
</dependency>

实现代码

//使用Spring Boot的扩展点,在容器启动成功后执行多数据源配置
@Configuration
public class DynamicDataSourceConfig implements ApplicationListener<ContextRefreshedEvent> {
    //读取yml 文件里面主数据源名称,用于获取主数据源
    @Value("${spring.datasource.dynamic.primary}")
    private String dynamicPrimary;
    
    //这个是我自己的数据源配置service
    @Autowired
    private IDbManageService dbManageService;
    
    //核心动态数据源组件
    @Autowired
    private DynamicRoutingDataSource dynamicRoutingDataSource;
    //Druid数据源创建器
    @Autowired
    private DruidDataSourceCreator dataSourceCreator;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        List<DbManage> dbManageList = dbManageService.list();
        if (CollectionUtils.isEmpty(dbManageList)) {
            return;
        }

        dbManageList.forEach(item -> {
            //获取主数据源对象
            DataSource masterDs = dynamicRoutingDataSource.getDataSource(dynamicPrimary);
            DataSourceProperty dsProperty = new DataSourceProperty();
            //copy 主数据源属性
            BeanUtils.copyProperties(masterDs, dsProperty);
            //修改数据库连接
            dsProperty.setDriverClassName(item.getDriverClassName());
            dsProperty.setUrl(item.getUrl());
            dsProperty.setUsername(item.getUsername());
            dsProperty.setPassword(item.getPassword());
            //创建数据源
            DataSource dataSource = dataSourceCreator.createDataSource(dsProperty);
            //加入到数据源容器内
            dynamicRoutingDataSource.addDataSource(item.getDsName(), dataSource);
        });
    }
}

yaml 配置(备用)

spring:
  # 多数据源配置,需要移除默认的Druid 配置
  autoconfigure:
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  # 数据源配置
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    # 配置Druid监控
    druid:
      stat-view-servlet:
        enabled: true
        login-username: admin
        login-password: 123456
    dynamic:
      # 配置Druid 的各项参数
      druid:
        # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,wall用于防火墙
        filters: stat
        # 初始化大小、最小或最大
        initial-size: 5
        min-idle: 5
        max-active: 20
        # 获取连接等待超时的时间,单位毫秒
        max-wait: 60000
        # 配置间隔多久进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        time-between-eviction-runs-millis: 60000
        # 配置一个连接在连接池中的最小生存时间,单位是毫秒
        min-evictable-idle-time-millis: 300000
        validation-query: SELECT 'x'
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
        # 打开PSCache,并且制定每个连接上PSCache的大小
        pool-prepared-statements: true
        max-pool-prepared-statement-per-connection-size: 20
        stat:
          merge-sql: true
          log-slow-sql: true
          slow-sql-millis: 3000
      # 配置数据库参数
      primary: master
      strict: true
      datasource:
        master:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://192.168.110.232:3306/project_development_test?serverTimezone=GMT%2B8&characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true
          username: projectDevelopment
          password: projectDevelopment
          poolPingQuery: SELECT NOW()
          poolPingEnabled: true