spring boot多数据源动态切换代码实例

 更新时间:2020年01月15日 08:56:57   作者:炫舞风中  
这篇文章主要介绍了spring boot多数据源动态切换代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

这篇文章主要介绍了spring boot多数据源动态切换代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

当项目中存在多数据源时,就涉及到数据源的动态切换,通过研究,特此记录一下。

1、maven依赖

<!--数据库连接-->
<dependency>
      <groupId>com.oracle</groupId>
      <artifactId>ojdbc6</artifactId>
      <version>11.2.0.4</version>
      <scope>runtime</scope>
    </dependency>
<!--数据库连接池->
<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid-spring-boot-starter</artifactId>
      <version>1.1.10</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
<!--aop->
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

2、多数据源信息配置

#多数据源测试
spring:
 datasource:
  druid:
   master:
    driver-class-name: oracle.jdbc.driver.OracleDriver
    username: test
    password: test
    url: jdbc:oracle:thin:@//ip1:1521/orcl
   slave:
    driver-class-name: oracle.jdbc.driver.OracleDriver
    username: test
    password: test
    url: jdbc:oracle:thin:@//ip2:1521/orcl

3、数据源配置信息转换成实体类

@ConfigurationProperties(prefix = "spring.datasource.druid")
@Data
@Component
public class DataSourceProperties {
  private Map<String,String>master;
  private Map<String,String>slave;
}

4、动态数据源切换类

public class DynamicDataSource extends AbstractRoutingDataSource {

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

  public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
    super.setDefaultTargetDataSource(defaultTargetDataSource);
    super.setTargetDataSources(targetDataSources);
    super.afterPropertiesSet();
  }


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

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

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

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

5、多数据源配置类

@Configuration
public class DynamicDataSourceConfig {

  @Bean
  public DataSource master(@Autowired DataSourceProperties dataSourceProperties){
    DruidDataSource druidDataSource = new DruidDataSource();
    Map<String, String> master = dataSourceProperties.getMaster();
    druidDataSource.setUsername(master.get("username"));
    druidDataSource.setPassword(master.get("password"));
    druidDataSource.setUrl(master.get("url"));
    //其他参数配置 省略
    return druidDataSource;
  }

  @Bean
  public DataSource slave(@Autowired DataSourceProperties dataSourceProperties){
    DruidDataSource druidDataSource = new DruidDataSource();
    Map<String, String> slave = dataSourceProperties.getSlave();
    druidDataSource.setUsername(slave.get("username"));
    druidDataSource.setPassword(slave.get("password"));
    druidDataSource.setUrl(slave.get("url"));
    //其他参数配置 省略
    return druidDataSource;
  }

  @Bean
  @Primary
  public DynamicDataSource dataSource(DataSource master,DataSource slave){
    Map<Object,Object>map = new HashMap<>(4);
    map.put("master",master);
    map.put("slave",slave);
    return new DynamicDataSource(master,map);
  }
}

6、自定义@DataSource注解

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

  String name() default "master";
}

7、Aop切面类配置

@Component
@Aspect
public class DataSourceAspect {

  @Pointcut("@annotation(com.zxgeo.sso.muiltDatasource.anons.DataSource)")
  public void dataSourcePointCut(){}

  @Around(value = "dataSourcePointCut()")
  public Object around(ProceedingJoinPoint point) throws Throwable {
    MethodSignature signature = (MethodSignature) point.getSignature();
    Method method = signature.getMethod();

    DataSource dataSource = method.getAnnotation(DataSource.class);
    if(dataSource == null){
      DynamicDataSource.setDataSource("master");
    }else {
      DynamicDataSource.setDataSource(dataSource.name());
    }
    try {
      return point.proceed();
    } finally {
      DynamicDataSource.clearDataSource();
    }
  }
}

8、启动配置注解信息,重要(不然运行会报错)

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})

9、测试

(1)、service层(此处没有使用mybatis)

@Service
public class TestService {

  @Autowired
  private javax.sql.DataSource dataSource;

  @DataSource
  public Map<String,Object> getMasterDataSource() throws SQLException {
    Connection connection = dataSource.getConnection();
    Map<String,Object> map;
    try (PreparedStatement preparedStatement
           = connection.prepareStatement("SELECT * FROM AA WHERE A=10001")) {
      ResultSet resultSet = preparedStatement.executeQuery();
      map = new HashMap<>();
      while (resultSet.next()){
        map.put("A",resultSet.getString("A"));
        map.put("B",resultSet.getString("B"));
        map.put("C",resultSet.getString("C"));
      }
    }
    return map;
  }
  @DataSource(name = "slave")
  public Map<String,Object> getSlaveDataSource() throws SQLException {
    Connection connection = dataSource.getConnection();
    Map<String,Object> map;
    try (PreparedStatement preparedStatement
           = connection.prepareStatement("SELECT * FROM AA WHERE A=10002")) {
      ResultSet resultSet = preparedStatement.executeQuery();
      map = new HashMap<>();
      while (resultSet.next()){
        map.put("A",resultSet.getString("A"));
        map.put("B",resultSet.getString("B"));
        map.put("C",resultSet.getString("C"));
      }
    }
    return map;
  }
}

(2)、单元测试

@SpringBootTest
@RunWith(SpringRunner.class)
class SsoApplicationTests {

  @Autowired
  private TestService testService;

  @Test
  public void muliDatasorce() throws SQLException {
    Map<String, Object> masterDataSourceUrl = testService.getMasterDataSource();
    System.out.println(masterDataSourceUrl);
    Map<String, Object> slaveDataSourceUrl = testService.getSlaveDataSource();
    System.out.println(slaveDataSourceUrl);
  }
}

(3)、结果:

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

相关文章

  • java 二维码的生成与解析示例代码

    java 二维码的生成与解析示例代码

    本文主要介绍java二维码的生成与解析,这里提供示例代码以便大家参考和理解,希望能帮助开发Java 二维码的朋友
    2016-08-08
  • Spring Cloud Zuul路由规则动态更新解析

    Spring Cloud Zuul路由规则动态更新解析

    这篇文章主要介绍了Spring Cloud Zuul路由规则动态更新解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • spring注解@Service注解的使用解析

    spring注解@Service注解的使用解析

    这篇文章主要介绍了spring注解@Service注解的使用解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java中两个List之间的比较方法(差集、交集和并集)

    Java中两个List之间的比较方法(差集、交集和并集)

    在业务的开发过程中会经常用到两个List集合相互取值的情况,下面这篇文章主要给大家介绍了关于Java中两个List之间的比较方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • java实现两个文件的异或运算

    java实现两个文件的异或运算

    这篇文章主要为大家详细介绍了java实现两个文件的异或运算,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • Java实现读取csv文件的两种方式

    Java实现读取csv文件的两种方式

    这篇文章主要为大家详细介绍了如何利用Java读取csv文件的两种方式,文中的示例代码讲解详细,对大家的学习或工作有一定的帮助,感兴趣的小伙伴可以了解一下
    2023-12-12
  • 求1000阶乘的结果末尾有多少个0

    求1000阶乘的结果末尾有多少个0

    题目是:求1000!的结果末尾有多少个0,解题思路:两个素数2、5,相乘即可得到10,我们可以认为,有多少组2、5,结尾就有多少个0,下面是代码,需要的朋友可以参考下
    2014-02-02
  • java HashMap详解及实例代码

    java HashMap详解及实例代码

    这篇文章主要介绍了java HashMap详解及实例代码的相关资料,需要的朋友可以参考下
    2017-01-01
  • 5分钟搭建SpringCloud Eureka服务注册中心的实现

    5分钟搭建SpringCloud Eureka服务注册中心的实现

    这篇文章主要介绍了5分钟搭建SpringCloud Eureka服务注册中心的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Spring Boot Starter 的应用场景与自动配置方式

    Spring Boot Starter 的应用场景与自动配置方式

    本文介绍了Spring Boot Starter的使用场景,如何自定义Starter以及Spring Boot自动配置原理,Spring Boot Starter解决了依赖导入和配置繁琐的问题,通过自动配置类和xxxProperties类实现组件的自动注入和配置,感兴趣的朋友一起看看吧
    2025-03-03

最新评论