dynamic多数据源整合springboot以及遇到的问题

1:引入依赖

        <!--多数据源-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>2.5.4</version>
        </dependency>

2:编写配置文件

  datasource:
    dynamic:
      #默认数据源
      primary:db1
      #严格模式
      strict: true
      datasource:
        db1:
          url: jdbc:mysql......
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
        db2:
          url: jdbc:mysql......
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
  #连接池 type: com.alibaba.druid.pool.DruidDataSource

3:使用:

在需要使用db2的controller上 直接增加这个注解,下面就会在使用过程中,改变链接 指向db2的链接

当然,再次过程中,尽量不要同时使用其他datasource注入相关的配置文件,比如自己实现的aop多数据源配置等

@DS("db2")public class TestController extends BaseController {}

注意事项:

由于是使用线程变量来做的数据源指向,所以在多线程情况下,它会出现找不到数据源,然后就会使用默认数据源的情况。

解决方案之一:

比较简单的处理方案是,给当前线程设置一个指定的数据源

/**
     * 切换数据源的显示指定
     *
     * @param run 运行的函数
     * @param ds  数据源名称
     */
    public static void run(TaskRun run, String ds) {
        try {
            if (StringUtils.isNotEmpty(ds)) {
                DynamicDataSourceContextHolder.push(ds);
                log.warn(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>切换当前数据源为:{}", ds);
                run.exec();
            } else {
                log.error("数据源不能为空!不使用默认数据源执行!");
            }
        } finally {
            DynamicDataSourceContextHolder.clear();
            log.warn(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>清除当前数据源:{}", ds);
        }
    }

    public static void main(String[] args) {
        new Thread(()->{
            run(()->{
                System.out.println("使用db1的数据源");
            },"db1");
        }).start();

        new Thread(()->{
            run(()->{
                System.out.println("使用db2的数据源");
            },"db2");
        }).start();

        new Thread(()->{
            run(()->{
                System.out.println("使用db3的数据源");
            },"db3");
        }).start();
    }

上面方法的接口函数

public interface TaskRun {

    /**
     * 执行方法
     */
    void exec();
}

 

当然上面的main方法里面三个函数都只是打印了一下并没有真正链接那些库,实际测试时,只要链接不同的库,就能实现不同的功能,上面方法执行后的日志如下

11:05:19.580 [Thread-0] WARN com.demo.utils.DataSourceUtils - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>切换当前数据源为:db1
        11:05:19.580 [Thread-1] WARN com.demo.utils.DataSourceUtils - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>切换当前数据源为:db2
        使用db2的数据源
        11:05:19.580 [Thread-2] WARN com.demo.utils.DataSourceUtils - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>切换当前数据源为:db3
        使用db3的数据源
        使用db1的数据源
        11:05:19.584 [Thread-1] WARN com.demo.utils.DataSourceUtils - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>清除当前数据源:db2
        11:05:19.584 [Thread-2] WARN com.demo.utils.DataSourceUtils - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>清除当前数据源:db3
        11:05:19.585 [Thread-0] WARN com.demo.utils.DataSourceUtils - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>清除当前数据源:db1

可以看出,数据源的变量已经改变

posted @ 2022-08-23 16:09  鸭猪是的念来过倒  阅读(606)  评论(0编辑  收藏  举报