SpringBoot实现整合多数据源的全攻略

 更新时间:2026年03月13日 08:55:46   作者:我可能在学习如何写bug  
在实际开发中,单数据源往往无法满足复杂的业务场景,本文将从实际业务需求出发,拆解 SpringBoot 中多数据源的核心实现方式,并附上可直接运行的代码示例,需要的可以了解下

在实际开发中,单数据源往往无法满足复杂的业务场景 —— 比如读写分离、分库分表、不同业务模块对接不同数据库等。SpringBoot 作为主流的开发框架,提供了多种多数据源整合方案,从简单的静态切换到灵活的动态路由,每种方案都有其适用场景。本文将从实际业务需求出发,拆解 SpringBoot 中多数据源的核心实现方式,并附上可直接运行的代码示例。

一、多数据源核心场景与技术选型

先明确多数据源的常见使用场景,避免盲目选型:

  • 静态多数据源:不同业务模块固定对接不同数据库(如订单库、用户库),启动时加载,运行时不切换;
  • 动态切换数据源:运行时根据条件(如用户 ID、业务标识)动态选择数据源(如读写分离、分库);
  • 分布式事务:多数据源操作需保证事务一致性(本文暂不展开,后续单独讲解)。

核心依赖(基于 SpringBoot 2.7.x):

<dependencies>
    <!-- SpringBoot核心 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 数据库连接 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version>
    </dependency>
    <!-- 数据库驱动(以MySQL为例) -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- 连接池 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.16</version>
    </dependency>
    <!-- 测试 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

二、方案 1:静态多数据源(基于配置类分离)

适用场景

不同业务模块完全隔离,比如「用户模块」对接 user_db,「订单模块」对接 order_db,运行时无需切换数据源。

实现步骤

配置文件(application.yml)

spring:
  datasource:
    # 数据源1:用户库
    user:
      url: jdbc:mysql://localhost:3306/user_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
      type: com.alibaba.druid.pool.DruidDataSource
    # 数据源2:订单库
    order:
      url: jdbc:mysql://localhost:3306/order_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
      type: com.alibaba.druid.pool.DruidDataSource
# MyBatis-Plus配置
mybatis-plus:
  mapper-locations: classpath:mapper/**/*.xml
  type-aliases-package: com.example.demo.entity
  configuration:
    map-underscore-to-camel-case: true

数据源配置类

分别配置两个数据源的 Bean,指定不同的扫描路径:

用户数据源配置(UserDataSourceConfig.java):

package com.example.demo.config;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
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.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
/**
 * 用户库数据源配置
 * 扫描user模块的mapper
 */
@Configuration
@MapperScan(basePackages = "com.example.demo.mapper.user", sqlSessionTemplateRef = "userSqlSessionTemplate")
public class UserDataSourceConfig {
    /**
     * 配置用户库数据源
     */
    @Bean(name = "userDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.user")
    @Primary // 主数据源(必须指定一个主数据源)
    public DataSource userDataSource() {
        return DataSourceBuilder.create().type(com.alibaba.druid.pool.DruidDataSource.class).build();
    }
    /**
     * 配置用户库SqlSessionFactory
     */
    @Bean(name = "userSqlSessionFactory")
    @Primary
    public SqlSessionFactory userSqlSessionFactory(@Qualifier("userDataSource") DataSource dataSource,
                                                   MybatisPlusInterceptor interceptor) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        // 配置MyBatis-Plus
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        sqlSessionFactory.setConfiguration(configuration);
        // 分页插件(可选)
        sqlSessionFactory.setPlugins(interceptor);
        // Mapper文件路径
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/user/*.xml"));
        return sqlSessionFactory.getObject();
    }
    /**
     * 配置用户库SqlSessionTemplate
     */
    @Bean(name = "userSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate userSqlSessionTemplate(@Qualifier("userSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

订单数据源配置(OrderDataSourceConfig.java):

package com.example.demo.config;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
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 javax.sql.DataSource;

/**
 * 订单库数据源配置
 * 扫描order模块的mapper
 */
@Configuration
@MapperScan(basePackages = "com.example.demo.mapper.order", sqlSessionTemplateRef = "orderSqlSessionTemplate")
public class OrderDataSourceConfig {

    @Bean(name = "orderDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.order")
    public DataSource orderDataSource() {
        return DataSourceBuilder.create().type(com.alibaba.druid.pool.DruidDataSource.class).build();
    }

    @Bean(name = "orderSqlSessionFactory")
    public SqlSessionFactory orderSqlSessionFactory(@Qualifier("orderDataSource") DataSource dataSource,
                                                   MybatisPlusInterceptor interceptor) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        sqlSessionFactory.setConfiguration(configuration);
        sqlSessionFactory.setPlugins(interceptor);
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/order/*.xml"));
        return sqlSessionFactory.getObject();
    }

    @Bean(name = "orderSqlSessionTemplate")
    public SqlSessionTemplate orderSqlSessionTemplate(@Qualifier("orderSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

业务代码示例

用户 Mapper(UserMapper.java):放在com.example.demo.mapper.user包下

package com.example.demo.mapper.user;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

订单 Mapper(OrderMapper.java):放在com.example.demo.mapper.order包下

package com.example.demo.mapper.order;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.Order;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}

业务层调用:

package com.example.demo.service.impl;

import com.example.demo.entity.Order;
import com.example.demo.entity.User;
import com.example.demo.mapper.order.OrderMapper;
import com.example.demo.mapper.user.UserMapper;
import com.example.demo.service.DataSourceService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class DataSourceServiceImpl implements DataSourceService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private OrderMapper orderMapper;

    @Override
    public User getUserById(Long id) {
        // 自动使用用户库数据源
        return userMapper.selectById(id);
    }

    @Override
    public Order getOrderById(Long id) {
        // 自动使用订单库数据源
        return orderMapper.selectById(id);
    }
}

优缺点

优点:配置简单、无侵入性、性能高,适合模块隔离的场景;

缺点:无法动态切换,新增数据源需新增配置类,灵活性低。

三、方案 2:动态切换数据源(基于 AbstractRoutingDataSource)

适用场景

需要根据业务逻辑动态切换数据源,比如「读写分离」(读库 / 写库切换)、「分库」(按用户 ID 路由到不同库)。

核心思路:继承 Spring 提供的AbstractRoutingDataSource,重写determineCurrentLookupKey方法,通过 ThreadLocal 存储当前线程的数据源标识,实现动态路由。

实现步骤

配置文件(application.yml)

spring:
  datasource:
    # 主库(写)
    master:
      url: jdbc:mysql://localhost:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    # 从库(读)
    slave:
      url: jdbc:mysql://localhost:3306/slave_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

核心工具类

数据源上下文 Holder(DynamicDataSourceContextHolder.java):

package com.example.demo.config.dynamic;

/**
 * 数据源上下文 Holder,基于ThreadLocal存储当前线程的数据源标识
 */
public class DynamicDataSourceContextHolder {

    /**
     * 线程本地变量:存储当前线程使用的数据源标识
     */
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();

    /**
     * 设置数据源标识
     */
    public static void setDataSourceKey(String key) {
        CONTEXT_HOLDER.set(key);
    }

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

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

动态数据源路由类(DynamicRoutingDataSource.java):

package com.example.demo.config.dynamic;

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

/**
 * 动态数据源路由:重写determineCurrentLookupKey方法,返回当前线程的数据源标识
 */
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        // 从ThreadLocal中获取当前线程的数据源标识
        return DynamicDataSourceContextHolder.getDataSourceKey();
    }
}

数据源配置类

package com.example.demo.config.dynamic;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
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.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

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

/**
 * 动态数据源配置
 */
@Configuration
@MapperScan(basePackages = "com.example.demo.mapper", sqlSessionFactoryRef = "dynamicSqlSessionFactory")
public class DynamicDataSourceConfig {

    /**
     * 配置主库数据源
     */
    @Bean(name = "masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().type(com.alibaba.druid.pool.DruidDataSource.class).build();
    }

    /**
     * 配置从库数据源
     */
    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().type(com.alibaba.druid.pool.DruidDataSource.class).build();
    }

    /**
     * 配置动态数据源(核心)
     */
    @Bean(name = "dynamicDataSource")
    @Primary
    public DataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
                                       @Qualifier("slaveDataSource") DataSource slaveDataSource) {
        DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
        // 1. 配置默认数据源(主库)
        dynamicRoutingDataSource.setDefaultTargetDataSource(masterDataSource);
        // 2. 配置所有数据源(key为数据源标识,value为数据源)
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put("master", masterDataSource);
        dataSourceMap.put("slave", slaveDataSource);
        dynamicRoutingDataSource.setTargetDataSources(dataSourceMap);
        return dynamicRoutingDataSource;
    }

    /**
     * 配置SqlSessionFactory
     */
    @Bean(name = "dynamicSqlSessionFactory")
    public SqlSessionFactory dynamicSqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource,
                                                     MybatisPlusInterceptor interceptor) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/**/*.xml"));
        sqlSessionFactory.setPlugins(interceptor);
        return sqlSessionFactory.getObject();
    }
}

自定义注解 + AOP 实现自动切换

数据源注解(DataSource.java):

package com.example.demo.annotation;

import java.lang.annotation.*;

/**
 * 自定义数据源注解:标注在方法/类上,指定使用的数据源
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    /**
     * 数据源标识,对应dynamicDataSource中的key
     */
    String value() default "master";
}

AOP 切面(DataSourceAspect.java):

package com.example.demo.aspect;

import com.example.demo.annotation.DataSource;
import com.example.demo.config.dynamic.DynamicDataSourceContextHolder;
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;

/**
 * 数据源切换切面:拦截@DataSource注解,设置对应的数据源标识
 */
@Aspect
@Component
@Order(-1) // 保证切面优先级高于事务
public class DataSourceAspect {

    /**
     * 切入点:拦截所有标注@DataSource的方法/类
     */
    @Pointcut("@annotation(com.example.demo.annotation.DataSource) || @within(com.example.demo.annotation.DataSource)")
    public void dataSourcePointCut() {}

    /**
     * 环绕通知:切换数据源
     */
    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 1. 获取注解中的数据源标识
        String dataSourceKey = getDataSourceKey(point);
        // 2. 设置数据源标识到ThreadLocal
        DynamicDataSourceContextHolder.setDataSourceKey(dataSourceKey);
        try {
            // 3. 执行目标方法
            return point.proceed();
        } finally {
            // 4. 清除数据源标识,避免线程复用导致的问题
            DynamicDataSourceContextHolder.clearDataSourceKey();
        }
    }

    /**
     * 获取方法/类上的数据源标识
     */
    private String getDataSourceKey(ProceedingJoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        // 优先获取方法上的注解
        DataSource methodAnnotation = method.getAnnotation(DataSource.class);
        if (methodAnnotation != null) {
            return methodAnnotation.value();
        }
        // 方法上没有则获取类上的注解
        Class<?> targetClass = point.getTarget().getClass();
        DataSource classAnnotation = targetClass.getAnnotation(DataSource.class);
        if (classAnnotation != null) {
            return classAnnotation.value();
        }
        // 默认使用主库
        return "master";
    }
}

业务代码示例

package com.example.demo.service.impl;

import com.example.demo.annotation.DataSource;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    /**
     * 写操作:使用主库
     */
    @Override
    @DataSource("master")
    public void saveUser(User user) {
        userMapper.insert(user);
    }

    /**
     * 读操作:使用从库
     */
    @Override
    @DataSource("slave")
    public User getUserById(Long id) {
        return userMapper.selectById(id);
    }
}

优缺点

优点:灵活性高,支持运行时动态切换,可扩展至 N 个数据源;

缺点:需要手动管理 ThreadLocal,切面优先级需高于事务,否则切换失效。

四、方案 3:基于 MyBatis-Plus 插件(dynamic-datasource-spring-boot-starter)

适用场景

追求极简配置,快速实现多数据源切换(推荐生产环境使用)。

dynamic-datasource-spring-boot-starter 是 MyBatis-Plus 团队提供的多数据源插件,封装了 AbstractRoutingDataSource 的底层逻辑,支持注解、spel 表达式、分布式场景等,无需手动编写切面和路由类。

实现步骤

引入依赖

<!-- 动态数据源插件(核心) -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.6.1</version>
</dependency>

配置文件(application.yml)

spring:
  # 动态数据源配置
  dynamic:
    datasource:
      # 主库(默认)
      master:
        url: jdbc:mysql://localhost:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
      # 从库1
      slave1:
        url: jdbc:mysql://localhost:3306/slave1_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
      # 从库2
      slave2:
        url: jdbc:mysql://localhost:3306/slave2_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
    # 配置默认数据源
    primary: master
    # 配置Druid连接池
    type: com.alibaba.druid.pool.DruidDataSource

业务代码示例

直接使用插件提供的@DS注解切换数据源:

package com.example.demo.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    /**
     * 默认使用主库(可不加注解)
     */
    @Override
    public void saveUser(User user) {
        userMapper.insert(user);
    }

    /**
     * 使用从库1
     */
    @Override
    @DS("slave1")
    public User getUserById(Long id) {
        return userMapper.selectById(id);
    }

    /**
     * 使用从库2
     */
    @Override
    @DS("slave2")
    public User getUserByPhone(String phone) {
        return userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
    }
}

进阶用法:spel 表达式动态路由

支持根据方法参数动态选择数据源(比如按用户 ID 取模分库):

/**
 * 根据用户ID取模,路由到不同从库
 */
@Override
@DS("#{id % 2 == 0 ? 'slave1' : 'slave2'}")
public User getUserById(Long id) {
    return userMapper.selectById(id);
}

优缺点

优点:零配置成本、功能丰富(支持读写分离、负载均衡、分布式锁)、官方维护;

缺点:依赖第三方插件,深度定制化场景需二次开发。

五、方案对比与选型建议

方案优点缺点适用场景
静态多数据源(配置类)配置简单、性能高、无侵入无法动态切换、扩展性差模块隔离的固定多数据源场景
自定义动态数据源高度自定义、灵活性高需手动编写代码、易出问题特殊定制化的动态切换场景
dynamic-datasource极简配置、功能丰富、稳定性高依赖第三方插件大部分生产环境(推荐)

六、注意事项

  • 事务问题:动态数据源切换需保证切面优先级高于事务(@Order (-1)),否则事务内切换数据源失效;
  • 线程安全:ThreadLocal 需在方法执行完毕后清除,避免线程池复用导致数据源串用;
  • 连接池配置:多数据源场景下需合理配置连接池大小,避免连接耗尽;
  • 读写分离:从库建议设置为只读,避免写入数据导致主从同步异常。

总结

SpringBoot 整合多数据源的核心思路是「数据源路由」,不同方案只是封装程度不同。对于大部分开发者来说,优先选择 dynamic-datasource 插件,兼顾效率和稳定性;特殊定制化场景可基于 AbstractRoutingDataSource 手动实现;模块隔离场景则用静态多数据源即可。

本文所有代码均可直接复制运行,建议根据实际业务场景调整数据源配置和切换逻辑。

以上就是SpringBoot实现整合多数据源的全攻略的详细内容,更多关于SpringBoot整合多数据源的资料请关注脚本之家其它相关文章!

相关文章

  • Java程序快速合并多个Word(docx)文档

    Java程序快速合并多个Word(docx)文档

    这篇文章主要为大家介绍了如何使用Java程序快速合并多个Word(docx)文档实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • mybatis plus数据权限插件在项目中的使用方式

    mybatis plus数据权限插件在项目中的使用方式

    本文介绍了如何在MyBatis中实现数据权限拦截器,通过自定义注解和拦截器,动态地在SQL中添加数据权限条件
    2026-01-01
  • Activiti7与Spring以及Spring Boot整合开发

    Activiti7与Spring以及Spring Boot整合开发

    这篇文章主要介绍了Activiti7与Spring以及Spring Boot整合开发,在Activiti中核心类的是ProcessEngine流程引擎,与Spring整合就是让Spring来管理ProcessEngine,有感兴趣的同学可以参考阅读
    2023-03-03
  • Mybatis环境配置及测试详解

    Mybatis环境配置及测试详解

    这篇文章主要介绍了Mybatis环境配置及测试详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Maven多模块之父子关系的创建

    Maven多模块之父子关系的创建

    这篇文章主要介绍了Maven多模块之父子关系的创建,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Java创建线程池的几种方式代码示例

    Java创建线程池的几种方式代码示例

    这篇文章主要介绍了Java中创建线程池的四种方式,包括使用Executors类、ThreadPoolExecutor类、Future和Callable接口以及Spring的ThreadPoolTaskExecutor,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-01-01
  • SpringBoot整合Swagger2的示例

    SpringBoot整合Swagger2的示例

    这篇文章主要介绍了SpringBoot整合Swagger2的示例,帮助大家更好的理解和学习springboot框架,感兴趣的朋友可以了解下
    2020-11-11
  • Java面试题冲刺第十四天--PRC框架

    Java面试题冲刺第十四天--PRC框架

    这篇文章主要为大家分享了最有价值的三道关于PRC框架的面试题,涵盖内容全面,包括数据结构和算法相关的题目、经典面试编程题等,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • java中哈希表及其应用详解

    java中哈希表及其应用详解

    Java中哈希表(Hashtable)是如何实现的呢?Hashtable中有一个内部类Entry,用来保存单元数据,我们用来构建哈希表的每一个数据是Entry的一个实例。假设我们保存下面一组数据,第一列作为key, 第二列作为value。
    2015-06-06
  • SpringBoot Actuator监控的项目实践

    SpringBoot Actuator监控的项目实践

    本文主要结合 Spring Boot Actuator,跟大家一起分享微服务Spring Boot Actuator 的常见用法,方便我们在日常中对我们的微服务进行监控治理,感兴趣的可以了解一下
    2024-01-01

最新评论