首页 > 其他分享 >SpringBoot下动态数据源

SpringBoot下动态数据源

时间:2023-03-31 20:05:44浏览次数:38  
标签:return SpringBoot 数据源 datasource org import 动态 public

第一种:Mybatis-Plus的dynamic-datasource

  Gitee地址:https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter

要实现其实很简单,一个注解就可以了

1、创建两个一库,一样的表进行测试

SpringBoot下动态数据源_spring

2、搭建SpringBoot引入dynamic-datasource依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.6.1</version>
</dependency>

3、修改SpringBoot配置

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/datasource-1?serverTimezone=UTC
          username: root
          password: xxx
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave_1:
          url: jdbc:mysql://localhost:3306/datasource-2?serverTimezone=UTC
          username: root
          password: xxx
          driver-class-name: com.mysql.cj.jdbc.Driver

4、在方法上面添加@DS注解

SpringBoot下动态数据源_数据源_02

第二种:使用Aop自己实现动态数据源的切换

  Git地址:https://gitee.com/zhang-zhixi/dynamic-datasource-springboot

1、创建两个一库,一样的表进行测试

2、搭建SpringBoot环境

3、自定义切换数据源注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface UsingDataSource {
    String value() default "";
}

4、编写存储自定义数据源的容器

/**
 * @author zhixi
 * 存储数据源的key,使用线程安全方式进行添加数据源
 */
public class DataSourceContextHolder {

    public static ThreadLocal<String> key = new ThreadLocal<>();

    public static void setKey(String key) {
        DataSourceContextHolder.key.set(key);
    }

    public static String getKey() {
        return key.get();
    }

    public static void clearKey() {
        key.remove();
    }
}

5、确定使用的数据源

/**
 * @author zhixi
 * AbstractRoutingDataSource是一个抽象类,是Spring提供的用于动态数据源切换的类。
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    /**
     * 查找哪个数据源的时候使用的key,该方法用于确定当前数据源
     * @return 数据源
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getKey();
    }
}

6、重写Spring相关配置

package com.zhixi.config;

import com.zhixi.datasource.DynamicDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
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.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

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

/**
 * @author zhixi
 * Spring相关配置
 */
@Configuration
public class DataSourceConfig {

    /**
     * 为每个数据源单独设置一个Bean
     *
     * @return 数据源1
     */
    @ConfigurationProperties("datasource1")
    @Bean
    public DataSource dataSource1() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 为每个数据源单独设置一个Bean
     *
     * @return 数据源2
     */
    @Bean
    @ConfigurationProperties("datasource2")
    public DataSource dataSource2() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 添加数据源
     *
     * @return 自定义数据源
     */
    @Bean
    public DynamicDataSource dynamicDataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("ds1", dataSource1());
        targetDataSources.put("ds2", dataSource2());

        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 设置目标数据源
        dynamicDataSource.setTargetDataSources(targetDataSources);
        // 设置默认目标数据源
        dynamicDataSource.setDefaultTargetDataSource(dataSource1());
        return dynamicDataSource;
    }

    /**
     * 使用DynamicDataSource作为数据源。
     *
     * @param dynamicDataSource 数据源
     * @return 配置好的SqlSessionFactoryBean对象,以便将其用作MyBatis框架的数据源。
     * @throws IOException 异常
     */
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DynamicDataSource dynamicDataSource) throws IOException {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        /*设置mybatis configuration 扫描路径 */
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        //加载配置文件的地址
        bean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
        bean.setDataSource(dynamicDataSource);
        return bean;
    }


    /**
     * 使用返回的数据源创建一个DataSourceTransactionManager对象。
     * DataSourceTransactionManager是Spring提供的事务管理器,用于管理基于数据源的事务
     * @return 事务管理器
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}

7、使用AOP,在方法调用前设置使用的数据源

package com.zhixi.datasource;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * @author zhixi
 * Aop切面,对注解进行切面
 */
@Aspect
@Component
public class DataSourceAspect {
    
    @Pointcut("@annotation(com.zhixi.datasource.UsingDataSource)")
    public void checkPointCut() {

    }

    /**
     * 方法调用之前设置数据源
     * @param usingDataSource 拿到注解的数据源的值
     */
    @Before("checkPointCut() && @annotation(usingDataSource)")
    public void checkBefore(UsingDataSource usingDataSource) {
        // 添加数据源的key
        DataSourceContextHolder.setKey(usingDataSource.value());
    }

    @After("checkPointCut()")
    public void checkAfter() {
        DataSourceContextHolder.clearKey();
    }
}

8、启动类配置

/**
 * @author zhixi
 * exclude = {DataSourceAutoConfiguration.class}:排除SpringBoot自带的数据源配置
 * EnableAspectJAutoProxy:启动动态代理
 */
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@MapperScan("com.zhixi.mapper")
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class DynamicDatasourceSpringbootApplication {

    public static void main(String[] args) {
        SpringApplication.run(DynamicDatasourceSpringbootApplication.class, args);
    }

}

9、编写Controller进行测试

SpringBoot下动态数据源_mybatis-plus_03



标签:return,SpringBoot,数据源,datasource,org,import,动态,public
From: https://blog.51cto.com/zhangzhixi/6162235

相关文章

  • 行业动态 | 第一个支持与 ChatGPT 进行面对面聊天的机器人女友(免费可聊)
    生成式AI急速发展GPT-4的上线、文心一言的发布、加上GPT-4植入Office全家桶,不少人感叹:我们每天醒来都被AI的快速发展所震惊,但是更多人感叹自己没有参与其中。国内可用!今天小A介绍一款新的机器人爱丽丝,这是一个免费的网页程序ChatD-ID——世界上第一个允许用户与数字人进行实时对......
  • SpringBoot微服务集成keycloak实现跨平台统一认证授权
    //项目架构微服务划分://auth认证微服务实现登录认证拦截,获取token//gateway网关微服务//user用户微服务用户权限管理//system系统微服务核心逻辑处理//xxx其他微服务//common模块//1、common模块引入keycloak认证相关依赖<properties><keyc......
  • 动态规划-背包问题
    前言浅谈上篇博客上篇博客是我的第一篇博客,在写完那篇博客后我发现我对ST表的理解比我写博客之前更加透彻了,简单思考后我发现是由于我以前都是简单的学习算法和数据结构,对于一个问题不会去深刻地思考,但是在写博客时,为了防止出错,同时为了更好的讲解,我会去尽可能地查找资料,追究更......
  • SpringBoot中常见的各种初始化场景分析
    大家能区分出以下各种初始化适用的场景吗ApplicationRunner,CommandLineRunner,BeanFactoryPostProcessor,InitializingBean,BeanPostProcessor首先可以简单分类Springboot的钩子        1,ApplicationRunner        2,CommandLineRunner上述2个钩子其实没啥......
  • SpringBoot 使用RedisTemplate
    1.导入Maven依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>2.配置连接信息spring:redis:host:127.0.0.1......
  • SpringBoot 集成支付宝的各种应用场景
    SpringBoot是一个非常流行的Java框架,它提供了一种快速、简便的方式来开发基于Java的Web应用程序。支付宝是中国最大的第三方支付平台,它提供了丰富的API,支持多种支付方式。在本篇博客中,我将介绍如何使用SpringBoot集成支付宝支付,包括以下几个场景:手机网站支付电脑网站支付移动支付......
  • SpringBoot 集成微信支付的各种支付产品
    SpringBoot是一款非常流行的Java开发框架,而微信支付则是众多移动支付产品中的佼佼者,整合两者可以让我们更方便地开发各种支付产品。在本篇博客中,我将介绍如何在SpringBoot中整合微信支付的各种支付产品。准备工作微信支付官网注册一个微信支付商户账号创建一个微信支付应用......
  • 1-SpringBoot快速入门
    SpringBoot快速入门1.什么是SpringBoot回顾什么是Spring?Spring是一个开源框架,2003年兴起的一个轻量级的Java开发框架,作者:RodJohnson。Spring是为了解决企业级应用开发的复杂性而创建的,简化开发。Spring是如何简化Java开发的?为了降低Java开发的复杂性,Spring采用......
  • 使用SpringBoot异步方法优化报销单查询接口,提高接口响应速度
    合理使用异步方法可以提高接口性能。异步方法适用于逻辑与逻辑之间可以相互分割互不影响的业务中。SpringBoot支持异步方法调用。具体用法:在启动类添加@EnableAsync注解,声明开启异步方法在异步方法添加@Async注解,被@Async注解修改的方法由SpringBoot默认线程池(SimpleAsyncTas......
  • 接口自动化之测试数据动态生成并替换
    一、测试数据1.随机库random查看内置random方法,该方法自行学习,不再介绍。showprint([namefornameindir(random)ifcallable(getattr(random,name))])['Random','SystemRandom','_Sequence','_Set','_accumulate','_acos......