springboot dynamic-datasource 实现动态切换数据源-多租户-配置文件切换-基于dynamic-datasource

这篇具有很好参考价值的文章主要介绍了springboot dynamic-datasource 实现动态切换数据源-多租户-配置文件切换-基于dynamic-datasource。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、目标

1、实现动态切换数据源
2、实现配置多数据源
3、实现读写分离也可以用多数据源方式
4、选择
dynamic-datasource集成了很多ORM的框架,其中,使用比较多的是druid,但有一些东西开始收费了
druid也可以自行配置,配置多了点

目前版本只支持单一位置加载数据源(只能从配置文件或者自定义加载数据源),不能多位置加载数据源
目前版本未实现动态添加数据源(在切换数据源时,不存在的数据源在数据库查询,添加进数据源连接池)

2、源代码

springboot版本:2.3.1.RELEASE
dynamic-datasource版本:3.5.1
官方文档:https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611
实现源代码地址

3、实现

pom.xml配置

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

application.yml配置


spring:
  application:
    name: microservice-boot-common
  # Jackson 配置项
  jackson:
    #    serialization:
    #      write-dates-as-timestamps: true # 设置 Date 的格式,使用时间戳
    #      write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401
    #      write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳
    #      fail-on-empty-beans: false # 允许序列化无属性的 Bean
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        druid: # Druid 【监控】相关的全局配置
          web-stat-filter:
            enabled: true
          stat-view-servlet:
            enabled: true
            allow: # 设置白名单,不填则允许所有访问
            url-pattern: /druid/*
            login-username: test
            login-password: test
          filter:
            stat:
              enabled: true
              log-slow-sql: true # 慢 SQL 记录
              slow-sql-millis: 1000
              merge-sql: true
            wall:
              config:
                multi-statement-allow: true
          initial-size: 4 # 初始连接数
          min-idle: 4 # 最小连接池数量
          max-active: 50 # 最大连接池数量
          max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
          time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
          min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
          max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
          validation-query: SELECT 1 # 配置检测连接是否有效
          test-while-idle: true
          test-on-borrow: false
          test-on-return: false
          name: master
        master:
          driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
          url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&allowPublicKeyRetrieval=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true&nullCatalogMeansCurrent=true
          username: root
          password: 123456
        slave_1:
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://127.0.0.1:3306/test2?useUnicode=true&allowPublicKeyRetrieval=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true&nullCatalogMeansCurrent=true
          username: root
          password: 123456




# MyBatis Plus 的配置项
mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
  global-config:
    db-config:
      #      id-type: NONE # “智能”模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。
      id-type: AUTO # 自增 ID,适合 MySQL 等直接自增的数据库
      #      id-type: INPUT # 用户输入 ID,适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库
      #      id-type: ASSIGN_ID # 分配 ID,默认使用雪花算法。注意,Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
      logic-delete-field: deleted_tag
      table-prefix: t_
    banner: false
  type-aliases-package: org.lwd.microservice.boot.common.dao
  mapper-locations: classpath*:/mapper/**/*.xml

手动切换

    @DS("slave_1")
     @Override
    public BaseResult<TenantDataSourceDTO> getTenantDataSourceByPk(String pk) {
        BaseResult<TenantDataSourceDTO> baseResult = BaseResult.success();
        TenantDataSource domain = this.getById(pk);
        baseResult.setData(TenantDataSourceConvertor.INSTANCE.toDTO(domain));
        return baseResult;
     }

动态切换-aop模式

package org.lwd.microservice.boot.common.aop;

import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;

/**
 * 数据源拦截-aop模式
 *
 * @author weidong
 * @version V1.0.0
 * @since 2023/6/13
 */
@Order(1)
@Aspect
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Component
@Slf4j
public class DataSourceChangeAdvisor {
    /**
     * 按需设置需要切换的模式
     */
    @Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
    public void pointDataSource() {
    }

    /**
     * 需要定义模块的规则
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("pointDataSource()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            //获取当前请求对象
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                String uri = request.getRequestURI();
                //String url = request.getRequestURL().toString();
                String[] uriArr = uri.split("/");
                if (uriArr[uriArr.length - 1].equals("detail")) {
                    log.info("datasource1------");
                    DynamicDataSourceContextHolder.push("master");
                } else {
                    log.info("datasource2------");
                    DynamicDataSourceContextHolder.push("slave_1");
                } 
            }
        } catch (Exception e) {
            log.error("日志拦截异常", e);
        } finally {
            return joinPoint.proceed();
        }
    }
}


动态切换-拦截器模式

package org.lwd.microservice.boot.common.interceptor;

import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 动态数据源-拦截器模式-需要自定义规则
 * @author weidong
 * @version V1.0.0
 * @since 2023/6/16
 */
@Slf4j
public class DynamicDataSourceChangeInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();
        //String url = request.getRequestURL().toString();
        String[] uriArr = uri.split("/");
        if (uriArr[uriArr.length - 1].equals("detail")) {
            log.info("interceptor datasource1------");
            DynamicDataSourceContextHolder.push("master");
        } else {
            log.info("interceptor datasource2------");
            DynamicDataSourceContextHolder.push("slave_1");
        } 
        return true;
    }
}

package org.lwd.microservice.boot.common.interceptor;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * mvc拦截器-自定义拦截路径
 * @author weidong
 * @version V1.0.0
 * @since 2023/6/16
 */
@Configuration
public class DynamicDataSourceChangeInterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //如果拦截全部可以设置为 /**
        String [] path = {"/tenantDataSource/**"};
        //不需要拦截的接口路径
        String [] excludePath = {};
        DynamicDataSourceChangeInterceptor dynamicDataSourceChangeInterceptor = new DynamicDataSourceChangeInterceptor();
        registry.addInterceptor(dynamicDataSourceChangeInterceptor).addPathPatterns(path).excludePathPatterns(excludePath);
    }
}

4、总结

这种方式是配置文件的方式,可对立的配置文件配置多个数据源,
但是动态增加或者减少数据源,需要自己实现一部分代码,看下一篇文章文章来源地址https://www.toymoban.com/news/detail-487419.html

外传

😜 原创不易,如若本文能够帮助到您的同学
🎉 支持我:关注我+点赞👍+收藏⭐️
📝 留言:探讨问题,看到立马回复
💬 格言:己所不欲勿施于人 扬帆起航、游历人生、永不言弃!🔥

到了这里,关于springboot dynamic-datasource 实现动态切换数据源-多租户-配置文件切换-基于dynamic-datasource的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • shardingsphere5.x整合springboot+dynamic-datasource多数据源实战

    本文是在springboot整合分库分表的基础上添加了多数据源,建议先看上一篇shardingsphere5.x整合springboot分库分表实战_任人人人呢的博客-CSDN博客 pom.xml配置: yml配置: 添加多数据源配置类: 添加多数据源常量类: Mapper文件

    2024年02月13日
    浏览(33)
  • Springboot+mybatis-plus+dynamic-datasource+Druid 多数据源 分布式事务

    背景 处理多数据源事务一直是一个复杂而棘手的问题,通常我们有两种主流的解决方法。 第一种是通过Atomikos手动创建多数据源事务,这种方法更适合数据源数量较少,参数配置不复杂,对性能要求不高的项目。然而,这种方法的最大困难在于需要手动配置大量设置,这可能

    2024年02月11日
    浏览(29)
  • dynamic-datasource can not find primary datasource

    动态数据源找不到主数据源 可能导入多数据源依赖导致 把依赖注释 运行成功

    2024年02月08日
    浏览(32)
  • 【源码解析】多数据源 dynamic-datasource快速入门及源码解析

    启动的时候,会加载在 dynamic-datasource-spring-boot-starter 的jar包中的 spring.factories 在 DynamicDataSourceAutoConfiguration 会注入 DynamicRoutingDataSource DynamicRoutingDataSource#afterPropertiesSet ,系统启动的时候会加载所有的数据源 在 DynamicDataSourceAutoConfiguration 会注入 DynamicDataSourceProvider AbstractData

    2023年04月21日
    浏览(50)
  • dynamic-datasource Please check the setting of primary解决方案

    报这个错的原因是数据库使用多数据源没有指定主数据源导致的错误。  解决方法如图所示,通过配置指定dynamic的primary指定主数据库的配置 切记箭头两处的名称一样

    2024年02月13日
    浏览(40)
  • spring boot mybatis-plus dynamic-datasource 配置文件 相关依赖环境配置

    spring boot mybatis-plus dynamic-datasource 配置文件 相关依赖环境配置 ##yaml配置 ##父级pom.xml配置 ##子模块pom.xml配置 ##表结构 ##Test.java ##TestMapper.xml ##TestMapper.java ##TestService.java ##TestController ##项目启动类BootStrap.java ##浏览器访问 192.168.3.188:8866/yym/test/v1/test

    2024年02月02日
    浏览(34)
  • 使用mybatis和dynamic-datasource-spring-boot-starter动态切换数据源操作数据库

    记录 :415 场景 :使用mybatis和dynamic-datasource-spring-boot-starter动态切换数据源操作数据库。 版本 :JDK 1.8,Spring Boot 2.6.3,dynamic-datasource-spring-boot-starter-3.3.2,mybatis-3.5.9。 源码 :https://github.com/baomidou/dynamic-datasource-spring-boot-starter dynamic-datasource-spring-boot-starter :一个基于springboot的快

    2023年04月19日
    浏览(32)
  • 使用dynamic-datasource-spring-boot-starter动态切换数据源操作数据库(MyBatis-3.5.9)

    记录 :383 场景 :使用dynamic-datasource-spring-boot-starter动态切换数据源,使用MyBatis操作数据库。提供三种示例:一,使用@DS注解作用到类上。二,使用@DS注解作用到方法上。三,不使用注解,使用DynamicDataSourceContextHolder类在方法内灵活切换不同数据源。 源码: https://github.com/

    2024年01月20日
    浏览(40)
  • MyBatis Plus 插件 动态数据源实现原理与源码讲解 (dynamic-datasource-spring-boot-starter-master)

    目录 1. 介绍 2. 基本原理 3. 源码介绍 3.1 使用 AOP 拦截,方法执行前获取到当前方法要用的数据源 3.2 实现自定义 DataSource 接口,实现 DataSource 接口的 getConnect 方法做动态处理 多数据源即一个项目中同时存在多个不同的数据库连接池。 比如 127.0.0.1:3306/test   127.0.0.1:3307/test 

    2024年02月07日
    浏览(29)
  • Dynamic DataSource 多数据源配置【 Springboot + DataSource + MyBatis Plus + Druid】

    MybatisPlus多数据源配置主要解决的是多数据库连接和切换的问题。在一些大型应用中,由于数据量的增长或者业务模块的增多,可能需要访问多个数据库。这时,就需要配置多个数据源。 2.1.1、引用依赖 2.1.2、application.yml 配置 2.1.3、通用配置类 2.1.4、使用方式 这里便不过多的

    2024年02月03日
    浏览(35)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包