SpringBoot+Druid配置多数据源(注解切换)

禁止掉DataSourceAutoConfiguration:

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DatahubApplication implements CommandLineRunner {

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

 

yml配置文件:

(注:每个数据源都需完整配置好参数)

spring:
  datasource:
    druid:
      mysql:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://10.0.0.10:3306/xxxx?useUnicode=true&useSSL=false&zeroDateTimeBehavior=convertToNull&characterEncoding=utf8&serverTimezone=GMT%2B8
        username: xx
        password: xx
        driver-class-name: com.mysql.cj.jdbc.Driver
        initial-size: 10
        max-active: 100
        min-idle: 10
        max-wait: 60000
        pool-prepared-statements: true
        max-pool-prepared-statement-per-connection-size: 20
        time-between-eviction-runs-millis: 60000
        min-evictable-idle-time-millis: 300000
        #Oracle需要打开注释
        #validation-query: SELECT 1 FROM DUAL
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
        stat-view-servlet:
          enabled: true
          url-pattern: /druid/*
          #login-username: admin
          #login-password: admin
        filter:
          stat:
            log-slow-sql: true
            slow-sql-millis: 1000
            merge-sql: false
          wall:
            config:
              multi-statement-allow: true
      db2:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:db2://10.3.2.5:50000/micszhc
        username: xx
        password: xx
        driver-class-name: com.ibm.db2.jcc.DB2Driver
        initial-size: 10
        max-active: 100
        min-idle: 10
        max-wait: 60000
        pool-prepared-statements: true
        max-pool-prepared-statement-per-connection-size: 20
        time-between-eviction-runs-millis: 60000
        min-evictable-idle-time-millis: 300000
        #Oracle需要打开注释
        #validation-query: SELECT 1 FROM DUAL
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
        stat-view-servlet:
          enabled: true
          url-pattern: /druid/*
          #login-username: admin
          #login-password: admin
        filter:
          stat:
            log-slow-sql: true
            slow-sql-millis: 1000
            merge-sql: false
          wall:
            config:
              multi-statement-allow: true

 

生成@DataSource注解,在Mapper层中使用(防止在service出现调用其他service层的方法,防止同时用到两种数据源存在冲突)

 

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    String name() default "";
}

 

 自定义数据源常量:

public class DataSourceConstants {

    public static final String MYSQL = "mysql";

    public static final String DB2 = "db2";

}

自定义DynamicDataSourceConfig:注入数据源

import javax.sql.DataSource;
@Configuration
public class DynamicDataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.druid.mysql")
    public DataSource mysqlDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.db2")
    public DataSource db2lDataSource() {
        return DruidDataSourceBuilder.create().build();
    }


    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource mysqlDataSource, DataSource db2lDataSource) {
        Map<Object, Object> targetDataSource = new HashMap<>();
        targetDataSource.put(DataSourceConstants.MYSQL, mysqlDataSource);
        targetDataSource.put(DataSourceConstants.DB2, db2lDataSource);
        return new DynamicDataSource(mysqlDataSource, targetDataSource);
    }
}

 自定义DynamicDataSource:

public class DynamicDataSource extends AbstractRoutingDataSource {

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

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }

    public static void setDataSource(String dataSource){
        contextHolder.set(dataSource);
    }

    public static String getDataSource(){
        return  contextHolder.get();
    }

    public static void clearDataSource(){
        contextHolder.remove();
    }
}

 自定义DataSourceAspect:

@Aspect
@Component
public class DataSourceAspect implements Ordered {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Pointcut("@annotation(com.pci.imc.datahub.common.constants.DataSource)")
    public void dataSourcePointCut(){

    }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point)throws  Throwable{
        MethodSignature signature = (MethodSignature)point.getSignature();
        Method method = signature.getMethod();
        DataSource ds = method.getAnnotation(DataSource.class);
        if(ds == null){
            DynamicDataSource.setDataSource(DataSourceConstants.MYSQL);
            logger.info("set mysql");
        }else{
            DynamicDataSource.setDataSource(ds.name());
            logger.info("set datasource");
        }

        try{
           return point.proceed();
        }finally {
            DynamicDataSource.clearDataSource();
            logger.info("clear datasource");
        }
    }
    @Override
    public int getOrder() {
        return 1;
    }
}

 Mapper层只需在方法上添加注解@DataSource(name = DB2) 就行了,不添加默认使用第一个数据源mysql

   @DataSource(name = DB2)
    List<Map<String, Object>> getLevel5Devices(@Param("name") String name, @Param("locationId") Integer locationId);

 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,你的问题是关于如何在Spring Boot应用中实现多数据动态切换,使用的技术包括Spring Boot、MyBatis、MySQL、Oracle、Druid数据连接池、自定义注解和切面,并且配置文件使用application.yml格式。 首先,需要在pom.xml文件中添加相应的依赖: ```xml <!--Spring Boot--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--MyBatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> <!--MySQL--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> <!--Oracle--> <dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc8</artifactId> <version>19.3.0.0</version> </dependency> <!--Druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.6</version> </dependency> ``` 接下来,需要在application.yml文件中配置数据和MyBatis相关的属性,例如: ```yaml spring: datasource: druid: # 数据1 db1: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/db1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: root # 数据2 db2: driver-class-name: oracle.jdbc.OracleDriver url: jdbc:oracle:thin:@localhost:1521:ORCL username: scott password: tiger # 默认数据 url: jdbc:mysql://localhost:3306/db1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: root mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.demo.entity ``` 然后,需要定义一个自定义注解,用于标识哪些方法需要使用哪个数据: ```java @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataSource { String value() default "db1"; } ``` 在数据切换的时候,我们需要获取注解上指定的数据名称,因此需要定义一个切面: ```java @Aspect @Component public class DataSourceAspect { @Around("@annotation(ds)") public Object around(ProceedingJoinPoint point, DataSource ds) throws Throwable { String dataSourceName = ds.value(); DynamicDataSource.setDataSource(dataSourceName); try { return point.proceed(); } finally { DynamicDataSource.clearDataSource(); } } } ``` 最后,需要定义一个动态数据,用于实现数据切换: ```java public class DynamicDataSource extends AbstractRoutingDataSource { private static final ThreadLocal<String> dataSourceHolder = new ThreadLocal<>(); @Override protected Object determineCurrentLookupKey() { return dataSourceHolder.get(); } public static void setDataSource(String dataSourceName) { dataSourceHolder.set(dataSourceName); } public static void clearDataSource() { dataSourceHolder.remove(); } } ``` 至此,多数据动态切换配置就完成了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值