开发者

在SpringBoot项目中动态切换数据源和数据库的详细步骤

目录
  • 前言
  • 步骤一:引入依赖
  • 步骤二:配置多个数据源
    • application.properties 示例:
  • 步骤三:自定义动态数据源
    • 1. 自定义 DynamicDataSource 类
    • 2. 定义 DataSourceContextHolder 类
    • 3. 配置动态数据源
  • 步骤四:切换数据源
    • 1. 在服务层切换数据源
    • 2. 在控制器层切换数据源
  • 步骤五:使用AOP统一切换数据源
    • 1. 自定义注解
    • 2. 切面类实现
    • 3. 使用注解切换数据源
  • 总结

    前言

    在许多企业级应用中,可能需要根据不同的业务需求来切换不同的数据库,如读写分离、分库分表等场景。Spring Boot 提供了灵活的数据源配置方式,可以通过动态切换数据源来实现这些需求。

    本文将介绍如何在 Spring Boot 项目中实现动态切换数据源和数据库的方案。我们将使用 Spring 的 AbstractRoutingDataSource 来实现动态切换数据源。

    步骤一:引入依赖

    首先,确保 Spring Boot 项目引入了以下依赖,主要包括 Spring Data JPA 和 mysql 驱动(如果使用 MySQL 数据库)。在 pom.XML 文件中添加这些依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId> <!-- 使用 HikariCP 作为连接池 -->
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-Java</artifactId>
    </dependency>
    

    步骤二:配置多个数据源

    application.propertiesapplication.yml 中配置多个数据源,假设我们配置了主数据源和从数据源。

    application.properties 示例:

    # 主数据源配置
    spring.datasource.primary.url=jdbc:mysql://localhost:3306/primary_db
    spythonpring.datasource.primary.username=root
    spring.datasource.primary.password=root_password
    spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.primary.hikari.maximum-pool-size=10
    
    # 从数据源配置
    spring.datasource.secondary.url=jdbc:mysql://localhost:3306/secondary_db
    spring.datasource.secondary.username=root
    spring.datasource.secondary.password=root_password
    spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.secondary.hikari.maximum-pool-size=10
    

    步骤三:自定义动态数据源

    Spring Boot 默认的配置是固定的单一数据源,但我们可以通过自定义 AbstractRoutingDataSource 来实现动态数据源切换。

    1. 自定义 DynamicDataSource 类

    AbstractRoutingDataSource 是 Spring 提供的一个用于路由到不同数据源的抽象类,我们继承该类并重写 determineCurrentLookupKey() 方法,根据当前线程或请求上下文来决定使用哪个数据源。

    public class DynamicDataSource extends AbstractRoutingDataSource {
    
        @javascriptOverride
        protected Object determineCurrentLookupKey() {
            return DataSourceContextHolder.getDataSourceType();
        }
    }
    

    2. 定义 DataSourceContextHolder 类

    为了实现线程安全地存储当前数据源的上下文,我们使用 ThreadLocal 来保存当前线程的数据源标识。

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

    3. 配置动态数据源

    在配置类中,将多个数据源(如主数据库和从数据库)与 DynamicDataSource 关联,并将 DynamicDataSource 设置为 Spring 管理的数据源。

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(basePackages = "com.example.repository")
    public class DataSourceConfig {
    
        @Primary
        @Bean
        public DynamicDataSource dynamicDataSource(
            @Qualifier("primaryDataSource") DataSource primaryDataSource,
            @Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
            
            Map<Object, Object> targetDataSources = new HashMap<>();
            targetDataSources.put("primary", primaryDataSource);
            targetDataSources.put("secondary", secondaryDataSource);
    
            DynamicDataSource dynamicDataSource = new DynamicDataSource();
            dynamicDataSource.setDefaultTargetDataSource(primaryDataSource);
            dynamicDataSource.setTargetDataSources(targetDataSources);
            return dynamicDataSource;
        }
    
        @Primary
        @Bean
        @ConfigurationProperties(prefix = "spring.datasource.primary")
        public DataSource primaryDataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean
        @ConfigurationProperties(prefix = "spring.datasource.secondary")
        public DataSource secondaryDataSource() {
            return DataSourceBuilder.create().build();
        }
    }
    

    步骤四:切换数据源

    为了动态切换数据源,我们可以在需要切换数据源的地方设置数据源类型(如读写分离、业务模块分库等)。

    1. 在服务层切换数据源

    在服务方法中,我们可以通过 DataSourceContextHolder.setDataSourceType("primary")DataSourceContextHolder.setDataSourceType("secondary") 来切换数据源。

    @Service
    public class DataService {
    
        // 使用主数据源
      android  public void usePrimaryDataSource() {
            DataSourceContextHolder.setDataSourceType("primary");
            // 执行主数据库相关操作
        }
    
        // 使用从数据源
        public void useSecondaryDataSource() {
            DataSourceContextHolder.setDataSourceType("secondary");
            // 执行从数据库相关操作
        }
    
        // 清除数据源设置
        public void clearDataSource() {
            DataSourceContextHolder.clearDataSourceType();
        }
    }
    

    2. 在控制器层切换数据源

    在控制器层中,可以根据请求的不同选择使用不同的数据源。

    @RestController
    @RequestMapping("/data")
    public class DataController {
    
        @Autowired
        private DataService dataService;
    
        @GetMapping("/usePrimary")
        public String usePrimaryDataSource() {
            dataService.usePrimaryDataSource();
            return "Using Primary DataSource";
        }
    
        @GetMapping("/useSecondary")
        public String useSecondaryDataSource() {
            dataService.useSecondaryDataSource();
            return "Using Secondary DataSource";
        }
    }
    

    步骤五:使用AOP统一切换数据源

    为了更优雅地切换数据源并解耦,我们可以通过 AOP(面向切面编程)来统一处理数据源切换。我们可以创建一个自定义注解来标识哪些方法需要切换数据源。

    1. 自定义注解

    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DataSourceSwitch {
        String value() default "primary"; // 默认使用主数据源
    }
    

    2. 切面类实现

    创建切面类,在方法执行前根据注解指定的数据源值来切换数据源。

    @ASPect
    @Component
    public class DataSourceAspect {
    
        @Before("@annotation(dataSourceSwitch)")
        public void switchDataSource(DataSourceSwitch dataSourceSwitch) {
            String dataSourceType = dataSourceSwitch.value();
            DataSourceContextHolder.setDataSourceType(dataSourceType);
        }
    
        @After("@annotation(dataSourceSwitch)")
        public void clearDataSource(DataSourceSwitch dataSourceSwitch) {
            DataSourceCophpntextHolder.clearDataSourceType();
        }
    }
    

    3. 使用注解切换数据源

    @Service
    public class DataService {
    
        @DataSourceSwitch("primary")
        public void usePrimaryDataSource() {
            // 使用主数据源
        }
    
        @DataSourceSwitch("secondary")
        public void useSecondaryDataSource() {
            // 使用从数据源
        }
    }
    

    总结

    通过在 Spring Boot 中实现动态数据源切换,我们可以灵活地管理不同数据库的使用,满足不同业务场景的需求。无论是简单的读写分离、分库还是更复杂的业务需求,都可以通过动态切换数据源来完成。通过结合 AOP 和注解,我们可以更加优雅地管理和切换数据源,避免了硬编码和重复代码的情况,提升了代码的可维护性和扩展性。

    以上就是在SpringBoot项目中动态切换数据源和数据库的详细步骤的详细内容,更多关于SpringBoot动态切换数据源和数据库的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜