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里的信息来指定数据源
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值