【Java】SpringBoot中实现多数据源切换

这篇具有很好参考价值的文章主要介绍了【Java】SpringBoot中实现多数据源切换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在日常项目开发中,某些需求会让不同的数据落实到不同的数据库,也或许是不同的页面需要不同数据库中的数据,在这种场景下,我们可以使用多数据源的配置来完成,通过在springboot中的yml文件配置多个数据源方式即可完成该需求,接下来看一下我的案例。

这篇案例采用自定义注解 + aop切面的方式来完成动态数据源的切换,关于自定义注解的使用可以去我的另一篇文章去查看怎样使用。

自定义注解使用方式:【Java】自定义注解和AOP切面的使用_java自定义切面_保加利亚的风的博客-CSDN博客

使用@DS自定义注解来完成动态数据源的切换,如果不指定则使用默认的数据源。

    @GetMapping("/listDb1")
    public List<Db1User> listDb1() {
        return db1UserService.list();
    }
    
    @GetMapping("/listDb2")
    @DS("db2")
    public List<Db2User> listDb2() {
        return db2UserService.list();
    }

准备工作

数据库(Mysql):两个数据库,分别是db1_datasourcedb2_datasource

表:每个数据库都有一个user表,分别是db1_userdb2_user

数据:db1_user表中数据为4条db2_user表中数据为2条

开始

项目结构图

【Java】SpringBoot中实现多数据源切换

2 application.yml配置文件

server:
  port: 8111

mybatis:
  mapper-locations: classpath:mapper/*.xml #扫描xml文件路径
  configuration:
    map-underscore-to-camel-case: true
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #日志打印

db1: #数据源1
  datasource:
    jdbc-url: jdbc:mysql://localhost:3306/db1_datasource?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
db2: #数据源2
  datasource:
    jdbc-url: jdbc:mysql://localhost:3306/db2_datasource?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

注意:这里采用的是Hikari连接池,因为Hikari没有url属性,但是有一个jdbcUrl属性,如果配置多数据源,则数据库连接的url需要替换为jdbc-url

3 创建 DatasourceConfig类,读取配置项,加载ioc容器

@Configuration
@EnableConfigurationProperties
public class DatasourceConfig {

    //获取前缀为`db1.datasource`的配置项
    @Bean
    @ConfigurationProperties(prefix = "db1.datasource")
    public HikariConfig db1Config() {
        return new HikariConfig();
    }

    //获取前缀为`db2.datasource`的配置项
    @Bean
    @ConfigurationProperties(prefix = "db2.datasource")
    public HikariConfig db2Config() {
        return new HikariConfig();
    }
}

4 创建一个DynamicDataSourceContextHolder类,这个类主要是来维护我们的线程变量的,基于ThreadLocal方式来进行数据源的存储和获取。

public class DynamicDataSourceContextHolder {
    /**
     * 使用ThreadLocal维护变量
     */
    private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();

    /**
     * 存放所有数据源名称
     */
    public static List<String> dataSources = new ArrayList<>();

    /**
     * 设置当前数据源类型
     */
    public static void setDataSourceType(String dataSourceType) {
        threadLocal.set(dataSourceType);
    }

    /**
     * 获取当前threadLocal变量的数据源
     */
    public static String getDataSourceType() {
        return threadLocal.get();
    }

    /**
     * 清空当前threadLocal变量中所有数据源
     */
    public static void clearDataSourceType() {
        threadLocal.remove();
    }

    /**
     * 判断指定DataSource当前是否存在
     *
     * @param dataSource 数据源
     * @return
     */
    public static boolean containsDataSource(String dataSource) {
        return dataSources.contains(dataSource);
    }
}

5 创建DynamicDatasource类,这个类的主要作用就是来对我们的数据源进行获取,并且该类继承了一个名为AbstractRoutingDataSource类,它是一个轻量级的数据源切换类,我们只需要继承它并重写它的方法即可。

public class DynamicDatasource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        //返回当前threadLocal变量中的数据源类型
        return DynamicDataSourceContextHolder.getDataSourceType();
    }
}

6 完成维护工作后,我们回到DatasourceConfig配置类中,去处理设置数据源的功能。

@Bean
    public DataSource getDatasource() {
        //将数据源存入map集合
        Map<Object, Object> dataSourceMap = new HashMap<>();
        DataSource db1 = new HikariDataSource(db1Config());
        DataSource db2 = new HikariDataSource(db2Config());
        dataSourceMap.put("db1", db1);
        dataSourceMap.put("db2", db2);

        // 设置动态数据源
        DynamicDatasource dataSource = new DynamicDatasource();
        dataSource.setTargetDataSources(dataSourceMap);

        // 记录多数据源名称
        DynamicDataSourceContextHolder.dataSources.add("db1");
        DynamicDataSourceContextHolder.dataSources.add("db2");

        //设置默认的数据源
        dataSource.setDefaultTargetDataSource(db1);
        return dataSource;
    }

到这步我们就完成了动态切换数据源的配置了,那么我们该如何使用呢?

在文章开始我们说到,需要用到AOP切面+注解的方式来实现动态数据源的切换功能,接下来我们看该如何操作。

1 创建一个注解类,名为DS

@Target({ElementType.METHOD,ElementType.TYPE}) //加在方法和类型上
@Retention(RetentionPolicy.RUNTIME)
public @interface DS {
    String value() default "";
}

2 在使用切面编程前,需要先引入相关依赖。

        <!--切面-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>

3 定义切面类DatasourceAspect,处理切换数据源的逻辑。

@Aspect
@Component
@Order(5)
public class DatasourceAspect {

    //定义切入点,即切入到自定义的注解类的路径
    @Pointcut("@annotation(com.it.annotation.DS)")
    public void datasourceAspect() {
    }

    //切入点之前进行的操作
    @Before("datasourceAspect() && @annotation(ds)")
    public void beforeDatasource(JoinPoint joinPoint, DS ds) {
        //获取注解中的值
        String value = ds.value();
        //判断当前注解里的值是否存在
        if (DynamicDataSourceContextHolder.containsDataSource(value)) {
            //如果存在,则使用注解中的数据
            DynamicDataSourceContextHolder.setDataSourceType(value);
        } else {
            //不存在则使用默认数据源
            DynamicDataSourceContextHolder.setDataSourceType("db1");
        }
    }

    //执行完方法之后,将threadLocal变量的数据源清空
    @After("@annotation(ds)")
    public void remoteDatasource(JoinPoint point, DS ds) {
        DynamicDataSourceContextHolder.clearDataSourceType();
    }
}

完成这些配置之后,我们就可以使用注解的方式来完成数据源的动态切换了,接下来看一下代码示例。

测试

我们可以看到文章最开始的使用案例,接下来我们来进行测试查看是否成功。

    @GetMapping("/listDb1")
    public List<Db1User> listDb1() {
        return db1UserService.list();
    }
    
    @GetMapping("/listDb2")
    @DS("db2")
    public List<Db2User> listDb2() {
        return db2UserService.list();
    }

这里有两个接口,一个是查询db1数据库的,一个是查询db2数据库的,db1没有使用注解所以使用默认数据源。

测试结果

db1

    {
        "id": 1651767622561959937,
        "username": "苏秀兰",
        "age": 18,
        "address": "山东省 烟台市 莱山区",
        "createTime": "2023-04-28 09:57:42"
    },
    {
        "id": 1651767632389214210,
        "username": "韩静",
        "age": 18,
        "address": "湖北省 咸宁市 通山县",
        "createTime": "2023-04-28 09:57:45"
    },
    {
        "id": 1651767641637654529,
        "username": "周刚",
        "age": 18,
        "address": "甘肃省 定西市 漳县",
        "createTime": "2023-04-28 09:57:47"
    },
    {
        "id": 1651781461856866306,
        "username": "白秀兰",
        "age": 18,
        "address": "湖北省 黄石市 西塞山区",
        "createTime": "2023-04-28 10:52:42"
    }

db2

    {
        "id": 1651768320674619394,
        "username": "孟涛",
        "age": 18,
        "address": "台湾 台南市 将军区",
        "createTime": "2023-04-28 10:00:29"
    },
    {
        "id": 1651781496703143938,
        "username": "徐军",
        "age": 18,
        "address": "陕西省 延安市 黄陵县",
        "createTime": "2023-04-28 10:52:50"
    }

总结

使用动态数据源可以减轻数据库很多的压力,不同的数据可以存入不同的数据库中,常常应用在一些读写分离、分库分表的模式下。

如果这篇文章对你有帮助的话,请点个赞吧。文章来源地址https://www.toymoban.com/news/detail-428386.html

到了这里,关于【Java】SpringBoot中实现多数据源切换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot从数据库读取数据数据源配置信息,动态切换数据源

            首先准备多个数据库,主库smiling-datasource,其它库test1、test2、test3         接下来,我们在主库smiling-datasource中,创建表databasesource,用于存储多数据源相关信息。表结构设计如下         创建好表之后,向表databasesource中存储test1、test2、test3三个数据库的相关配置

    2024年01月16日
    浏览(51)
  • springboot hive mysql 多数据源切换

    本次实验重在多数据源切换 性能不在考虑其中 开发环境: hive 3.1.3 mysql 8.0.33 jdk 1.8 maven 3.9.1 idea 2023.1 springboot 2.7.11 HikariCP 连接池 实验效果:从 hive 中迁移数据到 MySQL pom.xml springboot 配置文件 application.yml pojo 类 mapper 接口 mybatis 映射配置文件 多数据配置 多数据源切换工具类

    2024年02月01日
    浏览(63)
  • springboot使用DynamicDataSource来动态切换数据源

    DynamicDataSource是一个数据源路由器,可以根据上下文动态选择数据源。可以在每个请求或线程中将数据源设置为当前需要使用的数据. 创建一个 DynamicDataSource 类,它继承自 AbstractRoutingDataSource 。在该类中重写**determineCurrentLookupKey()**方法,该方法返回一个字符串,用于指示当前

    2024年02月05日
    浏览(33)
  • springBoot-Mybatis-Plus 多数据源切换实现

    前言:本文主要通过AbstractRoutingDataSource,实现根据 http 访问携带的标识动态切换数据源; 1 AbstractRoutingDataSource 介绍: AbstractRoutingDataSource 是 Spring 框架中的一个抽象类,它可以用来实现动态数据源切换。在多数据源场景下,AbstractRoutingDataSource 可以根据不同的请求来动态地选

    2024年02月03日
    浏览(38)
  • SpringBoot整合多数据源,并支持动态新增与切换(详细教程)

    推荐文章:     1、springBoot对接kafka,批量、并发、异步获取消息,并动态、批量插入库表;     2、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据;     3、java后端接口API性能优化技巧     4、SpringBoot+MyBatis流式查询,处理大规模数据,提高系统的性能和响应能力。 一

    2024年02月10日
    浏览(33)
  • SpringBoot整合Druid数据库连接池&多数据源&注解切换&动态添加

    配置好之后 Druid 会通过 DruidDataSourceAutoConfigure 自动装配 属性配置 数据源枚举 动态数据源 继承 AbstractRoutingDataSource 就可以实现动态数据源了 实现了一个动态数据源类的构造方法,主要是为了设置默认数据源,以及以Map保存的各种目标数据源。其中Map的key是设置的数据源名称

    2024年03月22日
    浏览(49)
  • 基于注解切换、Hikari实现的SpringBoot动态数据源(支持JNDI)

    先说效果,要实现方法级别注解切换当前数据源,不设置注解时走默认数据源,同时支持JNDI源。 Spring框架中存在一个抽象类 AbstractRoutingDataSource ,他是一个可以动态选择当前DataSource的路由类,我们就是要从这里入手,重新实现数据源的切换选择逻辑。然后借助注解和切面,

    2024年02月08日
    浏览(68)
  • springboot dynamic-datasource 实现动态切换数据源-多租户-配置文件切换-基于dynamic-datasource

    1、实现动态切换数据源 2、实现配置多数据源 3、实现读写分离也可以用多数据源方式 4、选择 dynamic-datasource集成了很多ORM的框架,其中,使用比较多的是druid,但有一些东西开始收费了 druid也可以自行配置,配置多了点 目前版本只支持单一位置加载数据源(只能从配置文件或

    2024年02月09日
    浏览(42)
  • SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换

    SpringBoot+MybatisPlus+dynamic-datasources实现连接Postgresql和mysql多数据源: SpringBoot+MybatisPlus+dynamic-datasources实现连接Postgresql和mysql多数据源-CSDN博客 上面实现通过注解和配置文件的方式去进行多数据源操作。 如果业务需求,比如查询第三方接口时提供的是sqlserver的视图连接方式时,

    2024年01月20日
    浏览(35)
  • JAVA:Springboot动态装配Druid多数据源

    1、简介 最近打算搭建一个鉴权中心服务,采用springboot+FastMybatis装配Druid,考虑后续拓展采用Druid多数据源配置,以一个数据源为主,多个动态数据源为辅的结构。除了数据库,后续会结合shiro安全框架来搭建。 2、引用 在pom.xml添加框架Springboot +FastMybatis + Druid相关maven引用。

    2024年02月09日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包