10 06 2025


新建 application.yml 文件


里面配置信息如下:


server:
  port: 8005
spring:
  datasource:
    mysql-db:
      jdbc-url: jdbc:mysql://xxx:3306/xxx_db?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
      username: xxxx
      password: xxx
      # 使用druid数据源
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver

    mssql-db:
      jdbc-url: jdbc:sqlserver://xxx:1433;DatabaseName=xxx
      username: xxx
      password: xxx
      # 使用druid数据源
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver

    mssql-db-tj:
      jdbc-url: jdbc:sqlserver://xxx:1433;DatabaseName=xxx
      username: xxx
      password: xxx
      # 使用druid数据源
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
  jpa:
    show-sql: true

mybatis:
  mapper-locations: classpath*:mapper/*.xml
  type-aliases-package: rich.job.richjob.entity


pom.xml 必要包 配置如下:


<dependencies>
    <!-- alibaba的druid数据库连接池 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.4</version>
    </dependency>
</dependencies>


1:DataSourceConfig.java


@Configuration
public class DataSourceConfig {
    @Bean(name = "mysqlDb")
    @ConfigurationProperties(prefix = "spring.datasource.mysql-db")
    public DataSource mysqlDb() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = "mssqlDb")
    @ConfigurationProperties(prefix = "spring.datasource.mssql-db")
    public DataSource mssqlDb() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "mssqlDb_Tj")
    @ConfigurationProperties(prefix = "spring.datasource.mssql-db-tj")
    public DataSource mssqlDb_Tj() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 动态数据源: 通过AOP在不同数据源之间动态切换
     * @return
     */
    @Primary
    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(mysqlDb());
        // 配置多数据源
        Map<Object, Object> dsMap = new HashMap<Object, Object>();
        dsMap.put("mysqlDb", mysqlDb());
        dsMap.put("mssqlDb", mssqlDb());
        dsMap.put("mssqlDb_Tj", mssqlDb_Tj());

        dynamicDataSource.setTargetDataSources(dsMap);
        return dynamicDataSource;
    }

    /**
     * 配置@Transactional注解事物
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}


2:DataSourceContextHolder.java


public class DataSourceContextHolder {
    /**
     * 默认数据源
     */
    public static final String DEFAULT_DS = "mysqlDb";

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    // 设置数据源名
    public static void setDB(String dbType) {
        System.out.println("切换到{"+dbType+"}数据源");
        contextHolder.set(dbType);
    }

    // 获取数据源名
    public static String getDB() {
        return (contextHolder.get());
    }

    // 清除数据源名
    public static void clearDB() {
        contextHolder.remove();
    }
}


3:DS.java


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface DS {
    String value() default "mysqlDb";
}


4:DynamicDataSource.java


public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        System.out.println("数据源为"+DataSourceContextHolder.getDB());
        return DataSourceContextHolder.getDB();
    }
}


5:DynamicDataSourceAspect.java


@Aspect
@Component
public class DynamicDataSourceAspect {
    @Before("@annotation(DS)")
    @SuppressWarnings("rawtypes")
    public void beforeSwitchDS(JoinPoint point){
        //获得当前访问的class
        Class<?> className = point.getTarget().getClass();
        //获得访问的方法名
        String methodName = point.getSignature().getName();
        //得到方法的参数的类型
        Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
        String dataSource = DataSourceContextHolder.DEFAULT_DS;
        try {
            // 得到访问的方法对象
            Method method = className.getMethod(methodName, argClass);
            // 判断是否存在@DS注解
            if (method.isAnnotationPresent(DS.class)) {
                DS annotation = ((Method) method).getAnnotation(DS.class);
                // 取出注解中的数据源名
                dataSource = annotation.value();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 切换数据源
        DataSourceContextHolder.setDB(dataSource);
    }

    @After("@annotation(DS)")
    public void afterSwitchDS(JoinPoint point){
        DataSourceContextHolder.clearDB();
    }
}


6:CostDbService.java (调用方式)


@DS("mysqlDb")
public int  insertCostDb(CostDbObj costDbObj) throws Exception {
    return costDbMapper.insertCostDb(costDbObj);
}


7:JobApplication.java (项目启动配置)


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@MapperScan("com.rich.job.mapper")
@SpringBootApplication(exclude = {
        DataSourceAutoConfiguration.class
})
public class JobApplication {

    public static void main(String[] args) {
        SpringApplication.run(JobApplication.class, args);
    }
}