java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot 动态数据源切换

SpringBoot实现动态数据源切换的项目实践

作者:拥抱AI

在实际开发过程中,我们经常遇到需要同时操作多个数据源的情况,本文主要介绍了SpringBoot实现动态数据源切换的项目实践,具有一定的参考价值,感兴趣的可以了解一下

本文将介绍如何在 Spring Boot 应用中实现动态数据源切换,包括具体实现步骤和示例代码。通过本文的学习,你将能够轻松应对多种数据源切换的场景,提高应用程序的灵活性和可扩展性。

一. 引言

在实际开发过程中,我们经常遇到需要同时操作多个数据源的情况。例如,可能需要从不同的数据库中读取数据,或者根据业务需求将数据写入不同的数据库。在这种情况下,动态数据源切换就变得尤为重要。Spring Boot 提供了强大的数据源配置功能,使得动态数据源切换变得相对简单。本文将详细介绍如何在 Spring Boot 应用中实现动态数据源切换。

二. 准备工作

在开始实现动态数据源切换之前,我们需要做一些准备工作:

1.创建 Spring Boot 项目

首先,我们需要创建一个 Spring Boot 项目。可以使用 Spring Initializr(https://start.spring.io/)快速生成项目骨架。在创建项目时,选择合适的 JDK 版本、项目构建工具(如 Maven 或 Gradle)以及项目元数据(如项目名称、描述、包名等)。

2.添加依赖

在项目的 pom.xml 文件中添加以下依赖:

<dependencies>
    <!-- Spring Boot Web 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring Boot 数据源依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- 数据库驱动依赖,以 MySQL 为例 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
</dependencies>

三. 实现动态数据源切换

接下来,我们将介绍如何实现动态数据源切换。主要分为以下几个步骤:

1.配置数据源

在 application.properties 或 application.yml 文件中配置多个数据源,如下所示:

spring:
  datasource:
    primary:
      url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
    secondary:
      url: jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver

2.创建数据源配置类

创建一个数据源配置类,用于生成 DataSource 对象。这里我们使用 Java 配置的方式,如下所示:

@Configuration
public class DynamicDataSourceConfig {
    @Primary
    @Bean(name = "primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource dataSource1() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = "secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource dataSource2() {
        return DataSourceBuilder.create().build();
    }
}

3.创建动态数据源路由

创建一个动态数据源路由类,用于根据不同的条件切换不同的数据源。如下所示:

public class DynamicDataSourceContextHolder {
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
    public static void setDataSourceType(String dataSourceType) {
        CONTEXT_HOLDER.set(dataSourceType);
    }
    public static String getDataSourceType() {
        return CONTEXT_HOLDER.get();
    }
    public static void clearDataSourceType() {
        CONTEXT_HOLDER.remove();
    }
}

4.配置数据源路由

在 application.properties 或 application.yml 文件中配置数据源路由,如下所示:

spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    dynamic:
      primary: primaryDataSource
      secondary: secondaryDataSource

5.创建数据源切换切面

创建一个切面类,用于在方法执行前切换数据源,在方法执行后恢复数据源。如下所示:

@Aspect
@Component
public class DynamicDataSourceAspect {
    @Before("@annotation(TargetDataSource)")
    public void switchDataSource(JoinPoint point) {
        // 获取方法上的注解
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        TargetDataSource ds = method.getAnnotation(TargetDataSource.class);
        // 判断注解是否为空
        if (ds == null) {
            return;
        }
        // 切换数据源
        DynamicDataSourceContextHolder.setDataSourceType(ds.name());
    }
    @After("@annotation(TargetDataSource)")
    public void restoreDataSource(JoinPoint point) {
        // 获取方法上的注解
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        TargetDataSource ds = method.getAnnotation(TargetDataSource.class);
        // 判断注解是否为空
        if (ds == null) {
            return;
        }
        // 恢复数据源
        DynamicDataSourceContextHolder.clearDataSourceType();
    }
}

6.创建自定义注解

创建一个自定义注解,用于标记需要切换数据源的方法。如下所示:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TargetDataSource {
    String name();
}

7.使用自定义注解

在需要切换数据源的方法上使用自定义注解,如下所示:

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @TargetDataSource(name = "primary")
    public List<User> findUsersFromPrimary() {
        return userMapper.findAll();
    }
    @TargetDataSource(name = "secondary")
    public List<User> findUsersFromSecondary() {
        return userMapper.findAll();
    }
}

四. 测试动态数据源切换

为了验证我们的动态数据源切换是否生效,我们可以编写一些测试用例来模拟不同的数据源切换场景。
首先,我们需要创建一个简单的实体类和对应的仓库接口:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    // 省略 getter 和 setter
}
public interface UserRepository extends JpaRepository<User, Long> {
}

然后,我们可以编写一个测试类来测试动态数据源的切换:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    private UserService userService;
    @Test
    public void testDynamicDataSource() {
        List<User> usersFromPrimary = userService.findUsersFromPrimary();
        List<User> usersFromSecondary = userService.findUsersFromSecondary();
        
        // 假设我们期望从主数据源和从数据源分别查询到不同的用户列表
        assertNotNull(usersFromPrimary);
        assertNotNull(usersFromSecondary);
        assertNotEquals(usersFromPrimary, usersFromSecondary);
    }
}

在这个测试类中,我们注入了 UserService,并调用了两个方法来分别从主数据源和从数据源查询用户列表。我们使用了 assertNotNull 和 assertNotEquals 来验证查询结果,确保我们从两个不同的数据源获取到了不同的数据。

五. 注意事项

在实现动态数据源切换时,有几个注意事项需要牢记:

六. 总结

本文详细介绍了在 Spring Boot 应用中实现动态数据源切换的方法。通过配置多个数据源、创建数据源路由、使用切面编程和自定义注解,我们可以在运行时根据业务需求灵活地切换数据源。这种方法特别适合于需要同时访问多个数据库或数据源的应用场景。虽然动态数据源切换增加了系统的复杂性,但正确使用它可以为应用带来更高的灵活性和可扩展性。

到此这篇关于SpringBoot实现动态数据源切换的项目实践的文章就介绍到这了,更多相关SpringBoot 动态数据源切换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文