当前位置: 首页 > article >正文

springBoot设置多数据源

1.数据库配置

spring:
  datasource:
    # 默认数据源
    default:
      url: jdbc:mysql://localhost:3306/maindb
      username: default
      password: depassword
      driver-class-name: com.mysql.cj.jdbc.Driver

    # 第二个数据源
    second:
      url: jdbc:mysql://localhost:3306/seconddb
      username: second
      password: secondpassword
      driver-class-name: com.mysql.cj.jdbc.Driver

2.创建数据源Bean

@Configuration
@EnableTransactionManagement
public class MultipleDataSourceConfig {
   @Bean(name ="default")
   @ConfigurationProperties(prefix = "spring.datasource.default")
   public DataSource default(){
      return DataSourceBuilder.create.build():
   }

   @Bean(name ="second")
   @ConfigurationProperties(prefix = "spring.datasource.second")
   public DataSource second(){
      return DataSourceBuilder.create.build():
   }

}
//上下文数据源设置
public class DynamicDataSourceContext(){
  
  private static ThreadLocal<String> contextHolder = null;
  synchronized public static ThreadLocal<String> getInstance() {
     if (contextHolder == null) {
        contextHolder = new ThreadLocal<>();
     }
     return contextHolder;
  }
 public static void setDataSource(String dataSource) {
      getInstance().set(dataSource);
 }
 
 public static String getDataSource(){
     return Objects.isNull(getInstance().get()) ? "default": getDataSource().get();
 }

 public static void clearDataSource(){
    getInstance().remove();
 }
}
//AbstractRoutingDataSource 是 Spring 提供的一个抽象类,用于支持在运行时动态切换数据源。它允许根据特定的标识符来选择要使用的数据源,这样您可以根据需要在不同的情况下选择不同的数据源。

//AbstractRoutingDataSource 中的 determineCurrentLookupKey() 方法是一个抽象方法,您需要在自定义的数据源路由类中覆盖此方法。它的作用是确定当前要使用的数据源的标识符,通常用来从一些上下文信息中获取数据源的标识。

public class DynamicDataSource extends AbstractRoutingDataSource {

   @Override
   protected Object determineCurrentLookupKey(){
        return DynamicDataSourceContext.getDataSource();
   }
}
@Configuration
public class DynamicDataSourceConfig {
   
   @Bean
   @Primary
   public DataSource dataSOurce(@Qualifier("default") DataSource defeult,@Qualifier("second") DataSource second){
      Map<Object,Object> datasource = new HashMap();
      datasource.put("default",defeult);
      datasource.put("second",second);
      DynamicDataSource dynamicDataSource = new DynamicDataSource();
      dynamicDataSource.setTargetDataSources(datasource);
      dynamicDataSource.setDefaultTargetDataSource(default);
      return dynamicDataSource;
   } 
}

3.定义注解,设置具体数据源

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicDataSourceSwitch {
    String value() default "default"; 
}

//切面,略微有些问题,根据自己需要修改

@Aspect
@Component
public class DataSourceAspect {

    @Pointcut("@annotation(xx.xx.xxx.DynamicDataSourceSwitch)")
    public void myCustomAnnotationPointcut() {
    }

    @Before("myCustomAnnotationPointcut()")
    public void beforeMyCustomAnnotation( JoinPoint point) {
       Signature signature = point.getSignature();
       DynamicDataSourceSwitch switercher;
       if(signature instanceof MethodSignature ms){// java 17写法
           //方法上的注解
           switercher = ms.getMethod().getAnnotation(DynamicDataSourceSwitch.class);
           if(Objects.isNull(switercher)){
             //class上的注解
             switercher = (DynamicDataSourceSwitch)signature.getDeclaringType().getAnnotation(DynamicDataSourceSwitch.class);
           }
           if(Objects.nonNull(switercher)) {
           //设置数据源
             DynamicDataSourceContext.setDataSource(switercher.value);
           }
       }
    }

    @After("myCustomAnnotationPointcut()")
    public void afterMyCustomAnnotation(JoinPoint point) {
        DynamicDataSourceContext.clearDataSource();
    }

    @AfterThrowing(pointcut = "myCustomAnnotationPointcut()")
    public void afterThrowingMyCustomAnnotation(JoinPoint point) {
        DynamicDataSourceContext.clearDataSource();
    }
}

4.使用

@Service
@DynamicDataSourceSwitch("second")
public class TestService {
  public void test(){
  //你的逻辑
  }
}
  • 备注:若不想显示指定,还可以在拦截器中拦截,根据路径或者header里的信息来指定数据源

http://www.kler.cn/news/148701.html

相关文章:

  • uniapp地图基本使用及解决添加markers不生效问题?
  • Linux shell编程学习笔记31:alias 和 unalias 操作 命令别名
  • 力扣 39. 组合总和 递归解法
  • Linux处理系统常见命令
  • [个人笔记] vCenter6.7使用自建SSL证书
  • UE5 范围内随机生成
  • 1. TiDB-Operator 备份到 Minio
  • RK3566RK3568 安卓11 在framework层进行串口通信
  • 【LeetCode】70. 爬楼梯
  • 服务器运行train.py报错解决
  • 成功的蓝图:实现长期成长与卓越表现的 6 项策略
  • 如何使用ArcGIS实现生态廊道模拟
  • 针对MySql知识的回顾
  • nodejs 如何将 Buffer 数据转为 String
  • 条形码格式
  • 位运算算法【1】
  • UI自动化的基本知识
  • Hive进阶函数:SPACE() 一行炸裂指定行
  • 【栈和队列(1)(逆波兰表达式)】
  • Ps:子路径的上下排列以及对齐与分布
  • 【开发实践】使用POI实现导出带有复杂表头的的excel文件
  • 璞华大数据产品入选中国信通院“铸基计划”
  • 【开源】基于Vue+SpringBoot的学校热点新闻推送系统
  • 梦极光(ez_re???)
  • MYSQL基础知识之【LIKE子句的使用 ,NULL值的处理,空值的处理】
  • ArrayList和顺序表
  • 服务器中深度学习环境的配置
  • 使用OSS搭建私有云内网yum仓库的方法
  • 盖茨表示GPT-5不会比GPT-4有太大改进;Intro to Large Language Models
  • 羽隔已就之图像处理之BP神经网络入门