栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Springboot整合多数据源代码示例详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Springboot整合多数据源代码示例详解

最近有个老项目想逐步将新业务的数据放到新的数据库,以前的业务还得连接以前的数据库,于是需要整合多数据源 。

多数据源实际上是继承了AbstractRoutingDataSource类,这个类最终实现了DataSource接口,DataSource里只有一个getConnection方法,数据库每次访问的时候都要先通过这个方法获取连接,所有多数据源就是每次访问数据库之前动态的改变数据源。

在请求前改变数据源当然需要用到SpringAOP,自定义注解操作

项目结构

下面上代码:

首先是依赖:


    
      mysql
      mysql-connector-java
      runtime
    
    
      org.springframework.boot
      spring-boot-starter-jdbc
    
    
    
      com.microsoft.sqlserver
      mssql-jdbc
      runtime
    
    
    
      com.baomidou
      mybatis-plus-boot-starter
      3.1.2
    
    
    
      com.alibaba
      druid
      1.1.8
          
    
      org.springframework.boot
      spring-boot-starter-aop
    

yml配置数据源

server:
 port: 8888

spring:
 jackson:
  time-zone: GMT+8
  date-format: yyyy-MM-dd HH:mm:ss
 datasource:
  druid:
   first:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    jdbc-url: jdbc:mysql://rm-uf6265pj340sc9447oo.mysql.rds.54565.com:3306/dm?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=utf-8
    username: username
    password: password
   second:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    jdbc-url: jdbc:sqlserver://39.104.203.222:1433;DatabaseName=TestTLcom
    username: root
    password: 123456

mybatis-plus:
 mapper-locations: classpath*:/mapper
public interface DataSourceNames {

  String FIRST = "first";
  String SECOND = "second";
}

动态数据源

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;


public class DynamicDataSource extends AbstractRoutingDataSource {

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

  public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) {

    super.setDefaultTargetDataSource(defaultTargetDataSource);
    super.setTargetDataSources(new HashMap<>(targetDataSources));
    super.afterPropertiesSet();
  }

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

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

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

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

配置多数据源

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.zdyl.dynamicdatasourcedemo.dynamicdatasource.DataSourceNames;
import com.zdyl.dynamicdatasourcedemo.dynamicdatasource.DynamicDataSource;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;


@Configuration
@MapperScan("com.zdyl.dynamicdatasourcedemo.**.mapper*")
public class MybatisPluConfig {

  
  @Bean
  @ConfigurationProperties(prefix="spring.datasource.druid.first")
  public DataSource firstDataSource() {
    return DataSourceBuilder.create().build();
  }

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

  @Bean
  @Primary
  public DynamicDataSource dataSource(DataSource firstDataSource, DataSource secondDataSource){
    Map targetDataSources = new HashMap<>();
    targetDataSources.put(DataSourceNames.FIRST, firstDataSource);
    targetDataSources.put(DataSourceNames.SECOND, secondDataSource);
    return new DynamicDataSource(firstDataSource, targetDataSources);
  }

  
  @Bean
  public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
  }

}

下面就是自定义注解

import java.lang.annotation.*;



@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface CurDataSource {

  String name() default "";
}

AOP

import com.zdyl.dynamicdatasourcedemo.dynamicdatasource.DataSourceNames;
import com.zdyl.dynamicdatasourcedemo.dynamicdatasource.DynamicDataSource;
import com.zdyl.dynamicdatasourcedemo.dynamicdatasource.annotation.CurDataSource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;




@Slf4j
@Aspect
@Component
public class DataSourceAspect implements Ordered {


  
  @Pointcut("@annotation(com.zdyl.dynamicdatasourcedemo.dynamicdatasource.annotation.CurDataSource)")
  public void dataSourcePointCut() {

  }

  @Around("dataSourcePointCut()")
  public Object around(ProceedingJoinPoint point) throws Throwable {
    MethodSignature signature = (MethodSignature) point.getSignature();
    Method method = signature.getMethod();
    CurDataSource curDataSource = method.getAnnotation(CurDataSource.class);
    if (curDataSource == null) {
      DynamicDataSource.setDataSource(DataSourceNames.FIRST);
      log.info("set datasource is " + DataSourceNames.FIRST);
    } else {
      DynamicDataSource.setDataSource(curDataSource.name());
      log.info("set datasource is " + curDataSource.name());
    }
    try {
      return point.proceed();
    } finally {
      DynamicDataSource.clearDataSource();
      log.info("clean datasource");
    }
  }

  @Override
  public int getOrder() {
    return 1;
  }
}

最后主启动了去掉数据源自动加载

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

最后我们来跑起来请求一下,测试一下是否正确

@RestController
public class CfgDeviceController {
  @Resource
  CfgDeviceService cfgDeviceService;
  @Resource
  CfgChargeStartInfoService cfgChargeStartInfoService;
  
  @CurDataSource(name = DataSourceNames.FIRST)
  @GetMapping("/test")
  public void getUser() {
    CfgDevice byId = cfgDeviceService.getById(19);
    System.out.println(byId.toString());
  }

  @CurDataSource(name = DataSourceNames.SECOND)
  @GetMapping("/test1")
  public void getUser1() {
    CfgChargeStartInfo byId = cfgChargeStartInfoService.getById(1);
    System.out.println(byId.toString());
  }
}

**如果不加注解,使用默认数据源

至此就整合完了

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/132734.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号