iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >SpringBoot怎么实现多数据源的切换
  • 118
分享到

SpringBoot怎么实现多数据源的切换

2023-06-29 09:06:27 118人浏览 薄情痞子
摘要

这篇文章主要介绍“SpringBoot怎么实现多数据源的切换”,在日常操作中,相信很多人在springBoot怎么实现多数据源的切换问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot怎么实现多

这篇文章主要介绍“SpringBoot怎么实现多数据源的切换”,在日常操作中,相信很多人在springBoot怎么实现多数据源的切换问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot怎么实现多数据源的切换”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

    前言

    我们在进行软件开发的过程中,刚开始的时候因为无法估量系统后期的访问量和并发量,所以一开始会采用单体架构,后期如果网站流量变大, 并发量变大,那么就可能会将架构扩展为微服务架构,各个微服务对应一个数据库,不过这样的成本就有点大了,可能只是有些模块用的人比较多, 有些模块没什么人用,如果都进行服务拆分,其实也没那个必要,如果有些模块用的人比较多,那么我们可以采用读写分离来减轻压力,这样的话, 可以在一定程度上提升系统的用户体验,不过这只是在数据库的I/O上面做方案,如果系统的压力很大,那么肯定要做负载均衡,我们今天就先说 实现数据库的读写分离。我们要在代码层面实现数据库的读写分离,那么核心就是数据源的切换,本文基于aop来实现数据源的切换。

    工程结构

    └─com    └─steak        └─transaction            │  TransactionDemoApplication.java            │              ├─datasource            │  │  DatasourceChooser.java            │  │  DatasourceConfiguration.java            │  │  DatasourceContext.java            │  │  DatasourceScope.java            │  │  DynamicDatasourceAspect.java            │  │              │  └─properties            │          DynamicDatasourceProperties.java            │          MainDatasourceProperties.java            │                      ├─execute            │      PlaceOrderExecute.java            │                  ├─rest            │      PlaceOrderapi.java            │                  ├─result            │      R.java            │                  └─service                    IntegralService.java                    OrderService.java                    StockService.java

    在下面的实现中,我们一个有三个数据源,其中有一个是默认的,如果不指定具体的数据源,那么就使用默认的,我们是基于申明式的方式来切换 数据源,只需要在具体的接口上加上注解便能实现数据源的切换。

    编码实现

    yml文件

    主数据源直接使用spring的配置,其他数据源采用自定义的方式,这里采用一个map结构来定义,方便进行解析,可以在yml文件里进行添加多个,在代码 逻辑层面不用改动。

    spring:  datasource:    type: com.alibaba.druid.pool.DruidDataSource    druid:      username: root      passWord: 123456      url: jdbc:mysql://127.0.0.1:3306/db?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC      driver-class-name: com.Mysql.cj.jdbc.Driverdynamic:  datasource: {    slave1: {      username: 'root',      password: '123456',      url: ' url: jdbc:mysql://127.0.0.1:3306/db?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC',      driver-class-name: 'com.mysql.cj.jdbc.Driver'    },    slave2: {      username: 'root',      password: '123456',      url: ' url: jdbc:mysql://127.0.0.1:3306/db?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC',      driver-class-name: 'com.mysql.cj.jdbc.Driver'    }  }

    主数据源MainDatasourceProperties

    对于主数据源,我们单独拿出来放在一个类里面,不过其实也可以放到dynamic里面,只是需要做一定的处理,我们就简单的放几个连接属性。

    @Component@ConfigurationProperties(prefix = "spring.datasource.druid")@Datapublic class MainDatasourceProperties {    private String username;    private String password;    private String url;    private String driverClassName;}

    其他数据源DynamicDatasourceProperties

    其他数据源使用一个Map来接受yml文件中的数据源配置

    @Component@ConfigurationProperties(prefix = "dynamic")@Datapublic class DynamicDatasourceProperties {    private Map<String,Map<String,String>> datasource;}

    数据源配置类DatasourceConfiguration

    配置类中主要对DataSource进行配置,主数据源我们按照正常的bean来定义连接属性,而其他数据数据源则使用反射的方式来进行连接属性的 配置,因为主数据源一般是不会变动的,但是其他数据源可能会发生变动,可能会添加,这时候如果通过硬编码取配置,那么每增加一个数据源,就需要 增加一个配置,显然不太行,所以就使用反射来进行赋值。

    @Configuration@AllArgsConstructorpublic class DatasourceConfiguration {    final MainDatasourceProperties mainDatasourceProperties;    final DynamicDatasourceProperties dynamicDatasourceProperties;    @Bean    public DataSource datasource(){        Map<Object,Object> datasourceMap = new HashMap<>();        DatasourceChooser datasourceChooser = new DatasourceChooser();                DruidDataSource mainDataSource = new DruidDataSource();        mainDataSource.setUsername(mainDatasourceProperties.getUsername());        mainDataSource.setPassword(mainDatasourceProperties.getPassword());        mainDataSource.setUrl(mainDatasourceProperties.getUrl());        mainDataSource.setDriverClassName(mainDatasourceProperties.getDriverClassName());        datasourceMap.put("main",mainDataSource);                Map<String, Map<String, String>> sourceMap = dynamicDatasourceProperties.getDatasource();        sourceMap.forEach((datasourceName,datasourceMaps) -> {            DruidDataSource dataSource = new DruidDataSource();            datasourceMaps.forEach((K,V) -> {                String setField = "set" + K.substring(0, 1).toUpperCase() + K.substring(1);                //转换yml文件中带有-符号的属性                String[] strings = setField.split("");                StringBuilder newStr = new StringBuilder();                for (int i = 0; i < strings.length; i++) {                    if (strings[i].equals("-")) strings[i + 1] = strings[i + 1].toUpperCase();                    if (!strings[i].equals("-")) newStr.append(strings[i]);                }                try {                    DruidDataSource.class.getMethod(newStr.toString(),String.class).invoke(dataSource,V);                } catch (Exception e) {                    e.printStackTrace();                }            });            datasourceMap.put(datasourceName,dataSource);        });        //设置目标数据源        datasourceChooser.setTargetDataSources(datasourceMap);        //设置默认数据源        datasourceChooser.setDefaultTargetDataSource(mainDataSource);        return datasourceChooser;    }}

    上面使用数据源配置类中使用反射对其他数据源进行连接属性的设置,然后设置目标数据源和默认数据源,里面有一个DatasourceChooser

    DatasourceChooser

    DatasourceChooser继承自AbstractRoutingDataSourceAbstractRoutingDataSource可以实现数据源的切换,它里面的 determineCurrentLookupKey()方法需要我们返回一个数据源的名称,它会自动给我们匹配上数据源。

    public class DatasourceChooser extends AbstractRoutingDataSource {    @Override    protected Object determineCurrentLookupKey() {        return DatasourceContext.getDatasource();    }}

    如下是AbstractRoutingDataSource的部分源码,我们可以看出数据源是一个Map结构,可以通过数据源名称查找到对应的数据源。

    package org.springframework.jdbc.datasource.lookup;public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {    @Nullable    private Map<Object, DataSource> resolvedDataSources;    public AbstractRoutingDataSource() {    }    protected DataSource determineTargetDataSource() {        Object lookupKey = this.determineCurrentLookupKey();        DataSource dataSource = (DataSource)this.resolvedDataSources.get(lookupKey);    }    @Nullable    protected abstract Object determineCurrentLookupKey();}

    DatasourceContext

    DatasourceContext内部是一个ThreadLocal,主要是用来存储每一个线程的数据源名称和获取数据源名称,而数据源的名称我们用过AOP切面 来获取。

    public class DatasourceContext {    private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();    public static void setDatasource(String key){        threadLocal.set(key);    }    public static String getDatasource(){        return threadLocal.get();    }}

    数据源注解DatasourceScope

    DatasourceScope标准在方法上面,通过scope来指定数据源,不指定默认为主数据源main

    @Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface DatasourceScope {    String scope() default "main";}

    数据源切面DynamicDatasourceAspect

    我们在访问每一个带有DatasourceScope注解的方法时,都会经过数据源切面DynamicDatasourceAspect,获取到注解上面的 scope的值后,通过DatasourceContext设置数据源名称,便可实现对数据源的切换。

    @Aspect@Componentpublic class DynamicDatasourceAspect {    @Pointcut("@annotation(dataSourceScope)")    public void dynamicPointcut(DatasourceScope dataSourceScope){}    @Around(value = "dynamicPointcut(dataSourceScope)", argNames = "joinPoint,dataSourceScope")    public Object dynamicAround(ProceedingJoinPoint joinPoint , DatasourceScope dataSourceScope) throws Throwable {        String scope = dataSourceScope.scope();        DatasourceContext.setDatasource(scope);        return joinPoint.proceed();    }}

    使用

    只需要在具体的方法上面标注数据源注解@DatasourceScope,并指定scope的值,便可实现切换,如果不指定,那么就使用主数据源。

    @Service@AllArgsConstructorpublic class OrderService {        private JdbcTemplate jdbcTemplate;        @DatasourceScope(scope = "slave1")    public R saveOrder(Integer userId , Integer commodityId){        String sql = "INSERT INTO `order`(user_id,commodity_id) VALUES("+userId+","+commodityId+")";        jdbcTemplate.execute(sql);        return R.builder().code(200).msg("save order success").build();    }}

    到此,关于“SpringBoot怎么实现多数据源的切换”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

    --结束END--

    本文标题: SpringBoot怎么实现多数据源的切换

    本文链接: https://www.lsjlt.com/news/323909.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • SpringBoot多数据源切换怎么实现
      本篇内容主要讲解“SpringBoot多数据源切换怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot多数据源切换怎么实现”吧!配置文件(YML)spring: ...
      99+
      2023-06-30
    • SpringBoot怎么实现多数据源的切换
      这篇文章主要介绍“SpringBoot怎么实现多数据源的切换”,在日常操作中,相信很多人在SpringBoot怎么实现多数据源的切换问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot怎么实现多...
      99+
      2023-06-29
    • SpringBoot实现多数据源的切换实践
      目录前言工程结构编码实现yml文件主数据源MainDatasourceProperties其他数据源DynamicDatasourceProperties数据源配置类Datasour...
      99+
      2024-04-02
    • Springboot实现多数据源切换详情
      目录1. 实现效果1.1 controller1.2 mybatis.xml1.3 application.yml1.4 启动类2. 注解2.1 @Router3. 分库策略3.1 ...
      99+
      2024-04-02
    • SpringBoot多数据源切换实现代码(Mybaitis)
      目录前言配置文件(YML)核心代码DynamicDataSourceDynamicDataSourceServiceDynamicDataSourceConfig加载YML数据库配置...
      99+
      2024-04-02
    • Springboot动态切换数据源怎么实现
      这篇文章主要介绍“Springboot动态切换数据源怎么实现”,在日常操作中,相信很多人在Springboot动态切换数据源怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Springboot动态切换数...
      99+
      2023-06-25
    • springboot中mybatis多数据源动态切换实现
      目录多数据源配置引入 动态数据源路由实现 动态数据源切换使用 案例源码 在开发中,动态数据源配置还是用的比较多的,比如在多数据源使用方面,又或者是在多个DB之间切换方面。这里给出一个...
      99+
      2024-04-02
    • SpringBoot基于AbstractRoutingDataSource实现多数据源动态切换
      目录一、场景二、原理三、代码示例一、场景 在生产业务中,有一些任务执行了耗时较长的查询操作,在实时性要求不高的时候,我们希望将这些查询sql分离出来,去从库查询,以减少应用对主数据库...
      99+
      2024-04-02
    • SpringBoot +DynamicDataSource如何切换多数据源
      小编给大家分享一下SpringBoot +DynamicDataSource如何切换多数据源,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!刚开始用一个数...
      99+
      2023-06-26
    • SpringBoot +DynamicDataSource切换多数据源的全过程
      目录固定多个数据源切换1.由于我这个版本的自带DynamicDataSource包2.在yml中配置两个数据源3.启动时启动连接池的方法获取4.载入各个连接池5.dynamicDat...
      99+
      2024-04-02
    • springboot+dynamicDataSource怎么实现动态添加切换数据源
      今天小编给大家分享一下springboot+dynamicDataSource怎么实现动态添加切换数据源的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,...
      99+
      2023-06-26
    • springboot怎么集成@DS注解实现数据源切换
      这篇文章主要介绍“springboot怎么集成@DS注解实现数据源切换”,在日常操作中,相信很多人在springboot怎么集成@DS注解实现数据源切换问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”sprin...
      99+
      2023-06-29
    • SpringBoot多数据源配置并通过注解实现动态切换数据源
      目录1. 环境准备1.1 数据库准备1.2 项目创建2. ThreadLocal类介绍3. AbstractRoutingDataSource类介绍4. 具体实现4.1 定义数据源枚...
      99+
      2022-11-13
      SpringBoot 动态切换数据源 SpringBoot 切换数据源
    • Spring多数据源AOP动态切换怎么实现
      这篇文章主要讲解了“Spring多数据源AOP动态切换怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring多数据源AOP动态切换怎么实现”吧!一:新增多数据源类public c...
      99+
      2023-06-04
    • SpringBoot基于AbstractRoutingDataSource如何实现多数据源动态切换
      本文小编为大家详细介绍“SpringBoot基于AbstractRoutingDataSource如何实现多数据源动态切换”,内容详细,步骤清晰,细节处理妥当,希望这篇“SpringBoot基于AbstractRoutingDataSour...
      99+
      2023-06-30
    • 【Java多数据源实现教程】实现动态数据源、多数据源切换方式
      前言 本文为 【Java多数据源实现教程】 相关知识,由于自己最近在做导师的项目的时候需要使用这种技术,于是自学了相关技术原理与实现,并将其整理如下,具体包含:多数据源的典型使用场景(包含业务复杂场景、读写分离场景),多数据源实现原理及实...
      99+
      2023-08-16
      java mybatis spring
    • 详解SpringBoot+Mybatis实现动态数据源切换
      业务背景 电商订单项目分正向和逆向两个部分:其中正向数据库记录了订单的基本信息,包括订单基本信息、订单商品信息、优惠卷信息、发票信息、账期信息、结算信息、订单备注信息、收货人信息等...
      99+
      2024-04-02
    • SpringBoot+Mybatis如何实现动态数据源切换
      这篇文章主要介绍了SpringBoot+Mybatis如何实现动态数据源切换,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。springboot是什么springboot一种全...
      99+
      2023-06-14
    • Spring AOP实现多数据源动态切换
      目录需求背景分析及实现配置多数据源信息Spring如何获取配置好的多个数据源信息?Spring如何选择使用数据源?结语需求背景 去年底,公司项目有一个需求中有个接口需要用到平台、算法...
      99+
      2024-04-02
    • Springboot实现根据用户ID切换动态数据源
      首先在application.yml 文件添加一下配置  #每个库可连接最大用户数 dynamic-server: #每个服务最大建库数 database-max-num...
      99+
      2024-04-02
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作