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

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里的信息来指定数据源

相关文章:

  • css实现水波纹效果
  • 2024年天津艺术职业学院专升本报名工作的通知
  • python读取PDF文件中的指定页码的范围并存储到指定的文件名
  • Java中的Integer.bitCount浅析
  • 初识JVM(简单易懂),解开JVM神秘的面纱
  • C语言面试之旅:掌握基础,探索深度(面试实战之c语言关键词中篇)
  • 04_Flutter自定义Slider滑块
  • filebeat(远程收集日志工具)
  • 大模型训练为什么用A100不用4090
  • Anaconda离线下载torch与安装包
  • QT配合CSS隐藏按钮
  • 建筑红模板尺寸规格
  • Python web自动化测试 —— 文件上传
  • 18、Android 组件化
  • 搭个网页应用,让ChatGPT帮我写SQL
  • 【传送点】上千漏洞复现复现集合 exp poc 持续更新
  • 微信小程序记住密码,让登录解放双手
  • Redis key的类型以及命令
  • 你要的fiddler快捷键全部在这里了,学最全的快捷键,做最快的IT程序员
  • mysql中数据是如何被用B+树查询到的
  • 上报集团社长李芸:发挥媒体优势,让中非民心在数字时代更深层互联互通
  • 中国词学研究会原会长、华东师大教授马兴荣逝世,享年101岁
  • 公安部部署“昆仑2025”专项工作,严打环食药等领域突出犯罪
  • 美联储主席:不打算先发制人地降息,将继续观望
  • 马上评|不再提“智驾”,新能源车企回归理性
  • 公积金利率降至历史最低!多项房地产利好政策落地,购房者置业成本又降了