springboot整合多数据源的配置以及动态切换数据源,注解切换数据源

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

在许多应用程序中,可能需要使用多个数据库或数据源来处理不同的业务需求。Spring Boot提供了简便的方式来配置和使用多数据源,使开发人员能够轻松处理多个数据库连接。如果你的项目中可能需要随时切换数据源的话,那我这篇文章可能能帮助到你

ℹ️:这里对于pom文件中坐标的引入我就不多赘言了

配置文件

1️⃣:properties文件中

# 数据源配置
spring.datasource.mysql.primary.url=jdbc:mysql://127.0.0.1:3351/tally_book?characterEncoding=utf8&serverTimezone=UTC
spring.datasource.mysql.primary.username=root
spring.datasource.mysql.primary.password=123456
spring.datasource.mysql.primary.driver-class-name=com.mysql.cj.jdbc.Driver

# 数据源配置
spring.datasource.mysql.slave1.url=jdbc:mysql://127.0.0.1:3351/dingding_mid?characterEncoding=utf8&serverTimezone=UTC
spring.datasource.mysql.slave1.username=root
spring.datasource.mysql.slave1.password=123456
spring.datasource.mysql.slave1.driver-class-name=com.mysql.cj.jdbc.Driver

上面的配置文件中我只写了两个源,而且都是mysql 的,primary和slave1就是区分

2️⃣:配置类实现多数据源配置

package com.todoitbo.tallybookdasmart.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.todoitbo.tallybookdasmart.multiDataSource.DataSourceType;
import com.todoitbo.tallybookdasmart.multiDataSource.DynamicDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

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

/**
 * @author xiaobo
 * @date 2023/5/19
 */
@Configuration
@Slf4j
public class MultiDataSourceConfig {

    @Bean
    public PlatformTransactionManager platformTransactionManager(DataSource dynamicDataSource) {
        return new DataSourceTransactionManager(dynamicDataSource);
    }

    @Bean
    @Primary
    @DependsOn("primaryDataSource")
    public DataSource dynamicDataSource(@Qualifier(DataSourceType.PRIMARY) DataSource primaryDataSource,
                                        @Qualifier(DataSourceType.SECOND) DataSource secondDataSource) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();

        // 1.设置默认数据源
        dynamicDataSource.setDefaultTargetDataSource(primaryDataSource);
        // 2.配置多数据源
        Map<Object, Object> map = new HashMap<>();
        map.put(DataSourceType.PRIMARY, primaryDataSource);
        map.put(DataSourceType.SECOND, secondDataSource);
        // 3.存放数据源集
        dynamicDataSource.setTargetDataSources(map);
        return dynamicDataSource;
    }

    @Bean(name = DataSourceType.PRIMARY)
    @ConfigurationProperties(prefix = "spring.datasource.mysql.primary")
    public DataSource primaryDataSource() {
        log.info("主数据库连接池创建中.......");
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = DataSourceType.SECOND)
    @ConfigurationProperties(prefix = "spring.datasource.mysql.slave1")
    public DataSource secondDataSource() {
        log.info("second数据库连接池创建中.......");
        return DruidDataSourceBuilder.create().build();
    }

}

3️⃣:自定义注解实现,可使用自定义注解来切换数据源

package com.todoitbo.tallybookdasmart.multiDataSource;

import java.lang.annotation.*;

/**
 * description: 自定义注解,标记数据源
 *
 * @author bo
 * @version 1.0
 * @date 2023/5/19 08:45
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DataSource {
    String value() default DataSourceType.PRIMARY;
}

4️⃣:定义一个切面类

这段代码是一个切面类DataSourceAspect,用于在方法调用前后切换数据源。以下是代码的解释:

  1. @Aspect:指定该类为切面类,用于定义切面的切入点和增强逻辑。
  2. @Order(value=1):指定切面的执行顺序,数值越小优先级越高。
  3. @Component:将该切面类声明为Spring的组件,使其可以被自动扫描并装配到Spring容器中。
  4. @Pointcut(value = "execution(* com.todoitbo.tallybookdasmart.service.*.*(..)) || execution(* com.todoitbo.tallybookdasmart.*.*(..))"):定义切入点表达式,指定需要切入的目标方法。
  5. @Around("dataSourcePointCut()"):定义环绕通知,表示在目标方法执行前后执行切面逻辑。
  6. public Object around(ProceedingJoinPoint joinPoint) throws Throwable:环绕通知方法,包含切面逻辑。
  7. 在方法中通过反射获取目标方法的注解信息,判断是否存在@DataSource注解,并获取注解中设置的数据源名称。
  8. 调用DataSourceContextHolder.setDataSource(dataSource)方法,将获取到的数据源名称设置到当前线程的上下文中。
  9. 调用joinPoint.proceed()方法,继续执行目标方法。
  10. finally块中调用DataSourceContextHolder.clearDataSourceType()方法,清除当前线程中存储的数据源信息。
package com.todoitbo.tallybookdasmart.multiDataSource;

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.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;


/**
 * @author xiaobo
 */
@Aspect
@Order(value=1)
@Component
@Slf4j
public class DataSourceAspect {

    /** 定义切入点表达式*/
    @Pointcut(value = "execution(* com.todoitbo.tallybookdasmart.service.*.*(..)) || execution(* com.todoitbo.tallybookdasmart.*.*(..))")
    public void dataSourcePointCut() {
    }
    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object target = joinPoint.getTarget();
        String method = joinPoint.getSignature().getName();
        Class<?> classz = target.getClass();
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();
        try {
            // 使用反射获取目标类中指定方法名和参数类型的方法对象
            Method m = classz.getMethod(method, parameterTypes);
            // 设置默认的数据源名称
            String dataSource = DataSourceType.PRIMARY;
            // 判断方法是否被@DataSource注解标记。
            if (m.isAnnotationPresent(DataSource.class)) {
                // 通过getAnnotation()方法获取方法上的@DataSource注解对象。
                DataSource ds = m.getAnnotation(DataSource.class);
                // 获取注解对象中设置的数据源名称
                dataSource = ds.value();
            }
            // 将获取到的数据源名称设置到当前线程的上下文中
            DataSourceContextHolder.setDataSource(dataSource);
            // 继续执行目标方法
            return joinPoint.proceed();
        } finally {
            DataSourceContextHolder.clearDataSourceType();
        }
    }

}

5️⃣:存储和获取当前线程数据源的上下文工具类

这段代码是一个用于存储和获取当前线程数据源的上下文工具类。它使用了Netty的FastThreadLocal来实现线程本地的快速存取。

  1. 创建FastThreadLocal对象:在类中定义了一个名为CONTEXT_HOLDERFastThreadLocal对象,用于存储当前线程的数据源信息。
  2. 设置数据源:setDataSource方法用于将数据源名称设置到当前线程的上下文中。通过调用CONTEXT_HOLDER.set(dataSource),将数据源名称存储在当前线程中。
  3. 获取数据源:getDataSource方法用于从当前线程的上下文中获取数据源名称。通过调用CONTEXT_HOLDER.get(),可以获取当前线程的数据源名称。
  4. 清除数据源:clearDataSourceType方法用于清除当前线程中存储的数据源信息。通过调用CONTEXT_HOLDER.remove(),可以清除当前线程中的数据源信息。
package com.todoitbo.tallybookdasmart.multiDataSource;

import io.netty.util.concurrent.FastThreadLocal;

/**
 * description: 存储和获取当前线程数据源的上下文工具类
 *
 * @author bo
 * @version 1.0
 * @date 2023/5/19 08:44
 */
public class DataSourceContextHolder {

    /**
     * 创建FastThreadLocal对象,存储当前线程的数据源信息
     */
    private static final FastThreadLocal<String> CONTEXT_HOLDER = new FastThreadLocal<String>();

    /**
     * 设置数据源
     */
    public static void setDataSource(String dataSource) {
        CONTEXT_HOLDER.set(dataSource);
    }

    /**
     * 获取数据源
     */
    public static String getDataSource() {
        return CONTEXT_HOLDER.get();
    }

    /**
     * 清除数据源
     */
    public static void clearDataSourceType() {
        CONTEXT_HOLDER.remove();
    }

}

6️⃣:数据源类型

package com.todoitbo.tallybookdasmart.multiDataSource;


/**
 * @author xiaobo
 */
public class DataSourceType {
    public static final String PRIMARY = "primaryDataSource";
    public static final String SECOND = "secondDataSource";
}

7️⃣:根据当前线程中的数据源上下文获取对应的数据源

package com.todoitbo.tallybookdasmart.multiDataSource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * description: 根据当前线程中的数据源上下文获取对应的数据源。
 *
 * @author bo
 * @version 1.0
 * @date 2023/5/19 08:46
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSource();
    }

}

具体实现

在service的实现类的方法上加入注解即可

package com.todoitbo.tallybookdasmart.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.todoitbo.tallybookdasmart.entity.TbConfig;
import com.todoitbo.tallybookdasmart.mapper.TbConfigMapper;
import com.todoitbo.tallybookdasmart.multiDataSource.DataSource;
import com.todoitbo.tallybookdasmart.multiDataSource.DataSourceType;
import com.todoitbo.tallybookdasmart.service.ITbConfigService;
import com.todoitbo.tallybookdasmart.service.base.BaseServiceImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;


/**
 * (TbConfig)服务
 *
 * @author bo
 * @since 2023-04-18 21:13:14
 */
@Service
public class TbConfigServiceImpl extends BaseServiceImpl<TbConfigMapper,TbConfig> implements ITbConfigService {

    @Resource
    protected TbConfigMapper mapper;

    @Override
    @DataSource(DataSourceType.SECOND)
    public List<TbConfig> testList() {
        return mapper.selectList(new QueryWrapper<>());
    }
}

效果图:

springboot多数据源配置和切换,springboot,spring boot,java,spring

⚠️:这里只是想展示他确实是走了从数据源了文章来源地址https://www.toymoban.com/news/detail-689851.html

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

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

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

相关文章

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

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

    2024年01月16日
    浏览(67)
  • SpringBoot整合(五)HikariCP、Druid数据库连接池—多数据源配置

    在项目中,数据库连接池基本是必不可少的组件。在目前数据库连接池的选型中,主要是 Druid ,为 监控 而生的数据库连接池。 HikariCP ,号称 性能 最好的数据库连接池。 在Spring Boot 2.X 版本,默认采用 HikariCP 连接池。而阿里大规模采用 Druid 。下面介绍在SpringBoot中使用Hika

    2024年02月17日
    浏览(78)
  • SpringBoot整合mysql、postgres、sqlserver实现多数据源配置案例

            分享一下近期处理的一个小demo,关于配置多数据源实现不同服务之间的数据推送和数据治理。第一次接触到pg库和sqlserver一头雾水,选择了JDBC+mybatis-plus的方式去链接。 1、首先要引入以下依赖 2、demo的项目结构如下 3、yml配置文件 4、配置类 5、controller、dao、service以

    2024年02月06日
    浏览(46)
  • SpringBoot整合Mybatis-Plus、Druid配置多数据源

    目录 1.初始化项目 1.1.初始化工程 1.2.添加依赖 1.3.配置yml文件 1.4.Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹 1.5.配置使用数据源 1.5.1.注解方式 1.5.2.基于AOP手动实现多数据源原生的方式 2.结果展示 Mybatis-Plus:简介 | MyBatis-Plus (baomidou.com) 在正式开始之前,先初始

    2024年02月11日
    浏览(48)
  • Springboot 配置动态多数据源(Mybatis-plus)

    前言:在项目中需要用到动态切换多数据源,查阅Mybatis-plus文档得知可以通过@DS注解,但该方法主要针对不同内容的数据源,而目前场景是相同内容的数据库需要在运行时根据请求头动态切换,因此文档方法不适用。 注意,不要使用dynamic-datasource-spring-boot-starter依赖包。 应用

    2024年02月12日
    浏览(41)
  • grpc + springboot + mybatis-plus 动态配置数据源

    前言 这是我在这个网站整理的笔记,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 1.1 项目初始化 项目初始化的时候会调用com.baomidou.dynamic.datasource.DynamicRoutingDataSource对象的addDataSource方法添加数据源,数据源存进dataSourceMap中。 1.2 接口请求时候 进行数据操作时,

    2024年02月09日
    浏览(41)
  • SpringBoot整合MybatisPlus多数据源

    相信在很多使用MybatisPlus框架的小伙伴都会遇到多数据源的配置问题,并且官网也给出了推荐使用多数据源 (dynamic-datasource-spring-boot-starter) 组件来实现。由于最近项目也在使用这个组件来实现多数据源切换,因此想了解一下该组件是如何运行的,经过自己的调试,简单记录一

    2024年02月13日
    浏览(37)
  • springboot整合kafka多数据源

    在很多与第三方公司对接的时候,或者处在不同的网络环境下,比如在互联网和政务外网的分布部署服务的时候,我们需要对接多台kafka来达到我们的业务需求,那么当kafka存在多数据源的情况,就与单机的情况有所不同。 单机的情况 如果是单机的kafka我们直接通过springboot自

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

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

    2024年02月09日
    浏览(55)
  • MyBatis整合Springboot多数据源实现

    数据源,实际就是数据库连接池,负责管理数据库连接,在 Springboot 中,数据源通常以一个 bean 的形式存在于 IOC 容器中,也就是我们可以通过依赖注入的方式拿到数据源,然后再从数据源中获取数据库连接。 那么什么是多数据源呢,其实就是 IOC 容器中有多个数据源的 bea

    2023年04月22日
    浏览(64)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包