springboot运行时指定数据源切换 动态多数据源切换,mysql与h2数据库

springboot运行时指定数据源切换 动态多数据源切换,mysql与h2数据库

springboot运行时指定数据源切换 动态多数据源切换



前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、背景

需要在运行的时候从前端接受数据库参数来切换数据源,类似自己实现一个配置中心

二、使用步骤

1.引入maven

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
```<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
 <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
 <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
            <version>1.4.199</version><!--低版本,支持访问内存数据库-->
        </dependency>
## 2.读入数据

核心代码如下(示例):

```xml

```java
@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.druid")
    public DataSource defaultDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    @DependsOn({"springUtils", "defaultDataSource"})
    public DynamicDataSource dataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(DynamicDataSource.dataSourcesMap);
        return dynamicDataSource;
    }

```public class DynamicDataSource extends AbstractRoutingDataSource {
    private static  String dataSourceKey =  "defaultDataSource";

    public static Map<Object, Object> dataSourcesMap = new ConcurrentHashMap<>(10);

    static {
        dataSourcesMap.put("defaultDataSource", SpringUtils.getBean("getDefaultDataSource"));
        //dataSourcesMap.put("defaultDataSource", DataSourceBuilder.create().driverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
        //    .url("jdbc:sqlserver://127.0.0.1:1433;DatabaseName=test")
        //    .username("sa")
        //    .password("root")
        //    .build());
        dataSourcesMap.put("dbkey", DataSourceBuilder.create().driverClassName("org.h2.Driver")
            .url("jdbc:h2:~/test")
            .username("sa")
            .password("root")
            .build());
    }

    @Override
    protected Object determineCurrentLookupKey() {

        return DynamicDataSource.dataSourceKey;
    }

    public static void setDataSource(String dataSource) {
        DynamicDataSource.dataSourceKey=dataSource;
        DynamicDataSource dynamicDataSource = (DynamicDataSource) SpringUtils.getBean("dataSource");
        dynamicDataSource.afterPropertiesSet();
    }


    public static void setH2DataSource(){
        DynamicDataSource.setDataSource("dbkey");
    }

    public static void setDefaultDataSource(){
        DynamicDataSource.setDataSource("defaultDataSource");

    }

    public static String getDataSource() {
        return DynamicDataSource.dataSourceKey;
    }

    //public static void clear() {
    //    DynamicDataSource.dataSourceKey.remove();
    //}
}
//初始化时指定一个默认数据源
```@Bean
    public DataSource getDefaultDataSource(){
        Props props = new Props(propertiesUrl+"dataSourceConfig.properties");

        DataSource build = DataSourceBuilder.create().driverClassName(props.getStr("driverClassName"))
            .url(props.getStr("url"))
            .username(props.getStr("username"))
            .password(props.getStr("password"))
            .build();
        props.clear();
        return build;

    }

通过接口来实现数据源的变更
@PostMapping("/setDataSource")
    public ResultDTO<Boolean> changeDataSource(DataSourceDTO dataSourceDTO) {
        DataSource dataSource = DataSourceBuilder.create().driverClassName(dataSourceDTO.getDriverClassName())
            .url(dataSourceDTO.getJdbcUrl())
            .username(dataSourceDTO.getUsername())
            .password(dataSourceDTO.getPassword())
            .build();

        DynamicDataSource.dataSourcesMap.put("defaultDataSource", dataSource);
        DynamicDataSource.setDataSource("defaultDataSource");
        //持久化写入
        Props props = new Props();
        props.setProperty("driverClassName",dataSourceDTO.getDriverClassName());
        props.setProperty("url",dataSourceDTO.getJdbcUrl());
        props.setProperty("username",dataSourceDTO.getUsername());
        props.setProperty("password",dataSourceDTO.getPassword());
        props.store(propertiesUrl+"dataSourceConfig.properties");
        props.clear();
        return ResultDTO.success();
    }
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyDataSource {
 
  String value();
 
}
//通过注解和aop来扫描mapper层接口来实现数据源切换
@Aspect
@Order(1)  //设置AOP执行顺序(需要在事务之前,否则事务只发生在默认库中)
@Component
@Slf4j
public class DataSourceAspect {
 
  //切点
  @Pointcut("execution(* com.cainiao.test.puhang.mapper.*.*(..))")
  public void aspect() { }
 
  @Before("aspect()")
  private void before(JoinPoint point) throws Throwable {

    try {
      Class<?> aClass = point.getTarget().getClass();
      MyDataSource parent = AnnotationUtils.findAnnotation(aClass, MyDataSource.class);
      if (parent!=null){
        DynamicDataSource.setH2DataSource();
      }

    } catch (Exception e) {
      log.error("get datasource error ",e);
      //默认选择master
      DynamicDataSource.setDefaultDataSource();
    }
  }
 
  @AfterReturning("aspect()")
  public void after() {
    DynamicDataSource.setDefaultDataSource();

  }
}

总结

提示:这里对文章进行总结:

适合特定的场景,但是要做到变更数据库的时候字段和类型是统一的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值