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的Console类的使用方法及实例

    java的Console类的使用方法及实例

    这篇文章主要介绍了java的Console类的使用方法及实例的相关资料,需要的朋友可以参考下
    2017-07-07
  • DoytoQuery中关于N+1查询问题解决方案详解

    DoytoQuery中关于N+1查询问题解决方案详解

    这篇文章主要为大家介绍了DoytoQuery中关于N+1查询问题解决方案详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • SpringBoot集成QQ第三方登陆的实现

    SpringBoot集成QQ第三方登陆的实现

    这篇文章主要介绍了SpringBoot集成QQ第三方登陆的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • java如何将int数组转化为Integer数组

    java如何将int数组转化为Integer数组

    这篇文章主要介绍了java如何将int数组转化为Integer数组,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 剑指Offer之Java算法习题精讲字符串与二叉搜索树

    剑指Offer之Java算法习题精讲字符串与二叉搜索树

    跟着思路走,之后从简单题入手,反复去看,做过之后可能会忘记,之后再做一次,记不住就反复做,反复寻求思路和规律,慢慢积累就会发现质的变化
    2022-03-03
  • Springboot中的@ComponentScan注解使用解析

    Springboot中的@ComponentScan注解使用解析

    这篇文章主要介绍了Springboot中的@ComponentScan注解使用解析,@ComponentScan用于类或接口上主要是指定扫描路径,spring会把指定路径下带有指定注解的类注册到IOC容器中,需要的朋友可以参考下
    2024-01-01
  • 浅谈JAVA实现选择排序,插入排序,冒泡排序,以及两个有序数组的合并

    浅谈JAVA实现选择排序,插入排序,冒泡排序,以及两个有序数组的合并

    这篇文章主要介绍了JAVA实现选择排序,插入排序,冒泡排序,以及两个有序数组的合并,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • java中调用super的实例讲解

    java中调用super的实例讲解

    在本篇文章里小编给大家分享了一篇关于java中调用super的实例讲解内容,有兴趣的朋友们可以学习下。
    2020-12-12
  • JVM虚拟机的类加载机制详解

    JVM虚拟机的类加载机制详解

    这篇文章主要介绍了JVM虚拟机的类加载机制详解,类是在运行期间第一次使用时动态加载的,而不是一次性加载所有类,因为如果一次性加载,那么会占用很多的内存,需要的朋友可以参考下
    2023-12-12
  • springboot 如何修改默认端口及application.properties常用配置

    springboot 如何修改默认端口及application.properties常用配置

    这篇文章主要介绍了springboot 如何修改默认端口及application.properties常用配置操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08

最新评论