在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.properties
或 application.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)其它相关文章!
精彩评论