一文詳解SpringBoot實(shí)現(xiàn)多數(shù)據(jù)源的自動(dòng)切換
在現(xiàn)代企業(yè)級(jí)應(yīng)用中,為了提高系統(tǒng)的可維護(hù)性和擴(kuò)展性,多數(shù)據(jù)源的配置和使用變得越來(lái)越常見(jiàn)。特別是在處理跨數(shù)據(jù)庫(kù)操作、讀寫(xiě)分離、分庫(kù)分表等場(chǎng)景時(shí),動(dòng)態(tài)數(shù)據(jù)源切換技術(shù)顯得尤為重要。本文將介紹如何在Spring Boot項(xiàng)目中實(shí)現(xiàn)多數(shù)據(jù)源的自動(dòng)切換。
1. 引言
隨著業(yè)務(wù)的不斷增長(zhǎng),單一的數(shù)據(jù)源往往難以滿足高并發(fā)、大數(shù)據(jù)量的需求。通過(guò)引入多數(shù)據(jù)源,可以有效地解決這些問(wèn)題。Spring Boot提供了靈活的配置機(jī)制,使得多數(shù)據(jù)源的管理變得更加簡(jiǎn)便。
2. 環(huán)境準(zhǔn)備
Java版本:1.8+
Spring Boot版本:2.3.4.RELEASE
數(shù)據(jù)庫(kù):MySQL 5.7+
3. 添加依賴
首先,在??pom.xml??文件中添加必要的依賴:
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- HikariCP 數(shù)據(jù)源 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
</dependencies>4. 配置多數(shù)據(jù)源
在??application.yml??中配置多個(gè)數(shù)據(jù)源:
spring:
datasource:
master:
url: jdbc:mysql://localhost:3306/db_master?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
slave:
url: jdbc:mysql://localhost:3306/db_slave?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver5. 創(chuàng)建數(shù)據(jù)源配置類(lèi)
創(chuàng)建一個(gè)配置類(lèi)來(lái)管理多個(gè)數(shù)據(jù)源,并將其注冊(cè)到Spring容器中:
import com.zaxxer.hikari.HikariDataSource;
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.jdbc.datasource.lookup.AbstractRoutingDataSource;
@Configuration
public class DataSourceConfig {
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "spring.datasource.master")
public HikariDataSource masterDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "spring.datasource.slave")
public HikariDataSource slaveDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean(name = "dynamicDataSource")
public AbstractRoutingDataSource dynamicDataSource(@Qualifier("masterDataSource") HikariDataSource masterDataSource,
@Qualifier("slaveDataSource") HikariDataSource slaveDataSource) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
Map<Object, Object> dataSourceMap = new HashMap<>();
dataSourceMap.put("master", masterDataSource);
dataSourceMap.put("slave", slaveDataSource);
dynamicDataSource.setTargetDataSources(dataSourceMap);
return dynamicDataSource;
}
}6. 實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換
創(chuàng)建一個(gè)??DynamicDataSource??類(lèi)繼承??AbstractRoutingDataSource??,并重寫(xiě)??determineCurrentLookupKey??方法來(lái)決定當(dāng)前使用的數(shù)據(jù)源:
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSource();
}
}創(chuàng)建一個(gè)??DataSourceContextHolder??類(lèi)來(lái)管理數(shù)據(jù)源上下文:
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}7. 使用AOP實(shí)現(xiàn)自動(dòng)切換
使用Spring AOP來(lái)實(shí)現(xiàn)數(shù)據(jù)源的自動(dòng)切換:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class DataSourceAspect {
@Pointcut("@annotation(com.example.demo.annotation.TargetDataSource)")
public void dataSourcePointCut() {}
@Before("dataSourcePointCut()")
public void switchDataSource(JoinPoint point) {
MethodSignature signature = (MethodSignature) point.getSignature();
TargetDataSource targetDataSource = signature.getMethod().getAnnotation(TargetDataSource.class);
if (targetDataSource != null) {
DataSourceContextHolder.setDataSource(targetDataSource.value());
}
}
}創(chuàng)建一個(gè)自定義注解??TargetDataSource??用于標(biāo)記需要切換數(shù)據(jù)源的方法:
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
String value();
}8. 測(cè)試
創(chuàng)建一些測(cè)試用的服務(wù)類(lèi)和控制器來(lái)驗(yàn)證多數(shù)據(jù)源切換是否正常工作:
import com.example.demo.annotation.TargetDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
@TargetDataSource("master")
public List<Map<String, Object>> getUserFromMaster() {
return jdbcTemplate.queryForList("SELECT * FROM user");
}
@TargetDataSource("slave")
public List<Map<String, Object>> getUserFromSlave() {
return jdbcTemplate.queryForList("SELECT * FROM user");
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/master")
public List<Map<String, Object>> getUsersFromMaster() {
return userService.getUserFromMaster();
}
@GetMapping("/slave")
public List<Map<String, Object>> getUsersFromSlave() {
return userService.getUserFromSlave();
}
}9.方法補(bǔ)充
在實(shí)際應(yīng)用中,特別是在大型系統(tǒng)或微服務(wù)架構(gòu)中,經(jīng)常會(huì)遇到需要操作多個(gè)數(shù)據(jù)庫(kù)的情況。Spring Boot 提供了靈活的配置和擴(kuò)展機(jī)制,可以方便地實(shí)現(xiàn)多數(shù)據(jù)源的支持。下面是一個(gè)簡(jiǎn)單的示例,展示如何在 Spring Boot 應(yīng)用中配置和使用動(dòng)態(tài)數(shù)據(jù)源。
添加依賴
首先,在 ??pom.xml?? 文件中添加必要的依賴:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
</dependencies>配置多數(shù)據(jù)源
在 ??application.yml?? 中配置兩個(gè)數(shù)據(jù)源:
spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
secondary:
url: jdbc:mysql://localhost:3306/db2?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver創(chuàng)建數(shù)據(jù)源配置類(lèi)
創(chuàng)建一個(gè)配置類(lèi)來(lái)配置多個(gè)數(shù)據(jù)源,并將它們注冊(cè)到 Spring 容器中:
import com.zaxxer.hikari.HikariDataSource;
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.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean
@ConfigurationProperties("spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean
@Primary
public DynamicDataSource dataSource(@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.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(primaryDataSource);
return dynamicDataSource;
}
}創(chuàng)建動(dòng)態(tài)數(shù)據(jù)源類(lèi)
創(chuàng)建一個(gè)繼承自 ??AbstractRoutingDataSource?? 的類(lèi)來(lái)實(shí)現(xiàn)數(shù)據(jù)源的動(dòng)態(tài)切換:
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSource();
}
}創(chuàng)建數(shù)據(jù)源上下文管理類(lèi)
創(chuàng)建一個(gè)工具類(lèi)來(lái)管理數(shù)據(jù)源的切換:
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}使用 AOP 切換數(shù)據(jù)源
使用 AOP 來(lái)切面管理數(shù)據(jù)源的切換,例如根據(jù)方法注解來(lái)切換數(shù)據(jù)源:
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class DataSourceAspect {
@Before("@annotation(com.example.demo.annotation.TargetDataSource)")
public void changeDataSource(JoinPoint point) {
MethodSignature signature = (MethodSignature) point.getSignature();
TargetDataSource targetDataSource = signature.getMethod().getAnnotation(TargetDataSource.class);
if (targetDataSource != null) {
DataSourceContextHolder.setDataSource(targetDataSource.value());
}
}
@After("@annotation(com.example.demo.annotation.TargetDataSource)")
public void restoreDataSource(JoinPoint point) {
DataSourceContextHolder.clearDataSource();
}
}自定義注解
創(chuàng)建一個(gè)自定義注解來(lái)標(biāo)記需要切換數(shù)據(jù)源的方法:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TargetDataSource {
String value();
}使用示例
在服務(wù)層中使用自定義注解來(lái)切換數(shù)據(jù)源:
import com.example.demo.annotation.TargetDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
@TargetDataSource("primary")
public void doSomethingWithPrimaryDB() {
jdbcTemplate.execute("SELECT * FROM user");
}
@TargetDataSource("secondary")
public void doSomethingWithSecondaryDB() {
jdbcTemplate.execute("SELECT * FROM user");
}
}方法二:
在Spring Boot應(yīng)用中實(shí)現(xiàn)多數(shù)據(jù)源的動(dòng)態(tài)切換是一個(gè)常見(jiàn)的需求,尤其是在需要訪問(wèn)多個(gè)數(shù)據(jù)庫(kù)或不同環(huán)境下的數(shù)據(jù)庫(kù)時(shí)。下面將詳細(xì)介紹如何在Spring Boot中配置和使用動(dòng)態(tài)數(shù)據(jù)源。
添加依賴
首先,確保你的??pom.xml??文件中包含必要的依賴項(xiàng)。通常情況下,你需要Spring Boot的Web和JPA/MyBatis等ORM框架的依賴,以及相應(yīng)的數(shù)據(jù)庫(kù)驅(qū)動(dòng)依賴。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
<!-- 其他數(shù)據(jù)庫(kù)驅(qū)動(dòng)依賴 -->
</dependencies>配置數(shù)據(jù)源
在??application.yml??或??application.properties??文件中配置多個(gè)數(shù)據(jù)源。
spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
secondary:
url: jdbc:mysql://localhost:3306/db2?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver創(chuàng)建數(shù)據(jù)源配置類(lèi)
創(chuàng)建一個(gè)配置類(lèi)來(lái)定義和配置多個(gè)數(shù)據(jù)源。
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return new BasicDataSource();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return new BasicDataSource();
}
@Bean
public DataSource dynamicDataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource,
@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("primary", primaryDataSource);
targetDataSources.put("secondary", secondaryDataSource);
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(primaryDataSource);
return dynamicDataSource;
}
@Bean
public PlatformTransactionManager transactionManager(DynamicDataSource dynamicDataSource) {
return new DataSourceTransactionManager(dynamicDataSource);
}
}創(chuàng)建動(dòng)態(tài)數(shù)據(jù)源類(lèi)
創(chuàng)建一個(gè)自定義的??DynamicDataSource??類(lèi),用于管理多個(gè)數(shù)據(jù)源的切換。
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSource();
}
}創(chuàng)建數(shù)據(jù)源上下文持有類(lèi)
創(chuàng)建一個(gè)線程安全的上下文持有類(lèi),用于存儲(chǔ)當(dāng)前線程的數(shù)據(jù)源標(biāo)識(shí)。
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}創(chuàng)建數(shù)據(jù)源切換注解
創(chuàng)建一個(gè)注解,用于在方法或類(lèi)上標(biāo)記數(shù)據(jù)源切換。
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String value() default "";
}創(chuàng)建切面類(lèi)
創(chuàng)建一個(gè)切面類(lèi),用于攔截帶有??@DataSource??注解的方法或類(lèi),并進(jìn)行數(shù)據(jù)源切換。
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class DataSourceAspect {
@Pointcut("@annotation(com.example.demo.DataSource)")
public void dataSourcePointCut() {}
@Before("dataSourcePointCut() && @annotation(dataSource)")
public void switchDataSource(DataSource dataSource) {
DataSourceContextHolder.setDataSource(dataSource.value());
}
}使用示例
在Service層或Controller層使用??@DataSource??注解來(lái)切換數(shù)據(jù)源。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@DataSource("primary")
public User getUserFromPrimary(int id) {
return userRepository.findById(id).orElse(null);
}
@DataSource("secondary")
public User getUserFromSecondary(int id) {
return userRepository.findById(id).orElse(null);
}
}配置JPA或MyBatis
如果你使用的是JPA或MyBatis,需要確保它們能夠正確地使用動(dòng)態(tài)數(shù)據(jù)源。對(duì)于JPA,你可能需要配置實(shí)體管理器工廠;對(duì)于MyBatis,需要配置SqlSessionFactory。
JPA配置
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.example.demo.repository",
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager"
)
public class JpaConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
@Qualifier("dynamicDataSource")
private DataSource dynamicDataSource;
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(dynamicDataSource)
.properties(jpaProperties.getProperties())
.packages("com.example.demo.entity")
.persistenceUnit("default")
.build();
}
@Primary
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}MyBatis配置
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.example.demo.mapper", sqlSessionTemplateRef = "sqlSessionTemplate")
public class MyBatisConfig {
@Autowired
@Qualifier("dynamicDataSource")
private DataSource dynamicDataSource;
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dynamicDataSource);
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}通過(guò)以上步驟,你可以在Spring Boot應(yīng)用中實(shí)現(xiàn)多數(shù)據(jù)源的動(dòng)態(tài)切換。
到此這篇關(guān)于一文詳解SpringBoot實(shí)現(xiàn)多數(shù)據(jù)源的自動(dòng)切換的文章就介紹到這了,更多相關(guān)SpringBoot數(shù)據(jù)源自動(dòng)切換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot和MyBatis環(huán)境下實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換過(guò)程
- SpringBoot實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源的示例代碼
- 在SpringBoot項(xiàng)目中動(dòng)態(tài)切換數(shù)據(jù)源和數(shù)據(jù)庫(kù)的詳細(xì)步驟
- SpringBoot實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)切換的最佳姿勢(shì)
- SpringBoot項(xiàng)目中如何動(dòng)態(tài)切換數(shù)據(jù)源、數(shù)據(jù)庫(kù)
- SpringBoot中實(shí)現(xiàn)多數(shù)據(jù)源連接和切換的方案
- SpringBoot實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的項(xiàng)目實(shí)踐
- Springboot如何設(shè)置多數(shù)據(jù)源,隨時(shí)切換
- Springboot實(shí)現(xiàn)多數(shù)據(jù)源切換詳情
相關(guān)文章
關(guān)于yml文件字符串,List,Map的書(shū)寫(xiě)方式并使用@ConfigurationProperties注入配置類(lèi)
這篇文章主要介紹了關(guān)于yml文件字符串,List,Map的書(shū)寫(xiě)方式并使用@ConfigurationProperties注入配置類(lèi),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Netty分布式高性能工具類(lèi)recycler的使用及創(chuàng)建
這篇文章主要為大家介紹了Netty分布式高性能工具類(lèi)recycler的使用和創(chuàng)建,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03
SpringBoot中使用攔截器攔截跳轉(zhuǎn)登錄的兩種實(shí)現(xiàn)方法
攔截器(Interceptor)是Spring框架提供的一種機(jī)制,用于在請(qǐng)求的生命周期中插入自定義邏輯,如身份驗(yàn)證、日志記錄等,本文將詳細(xì)介紹兩種在SpringBoot中使用攔截器來(lái)控制用戶登錄并跳轉(zhuǎn)到指定頁(yè)面的方法,需要的朋友可以參考下2024-11-11
解決SpringCloud Feign傳對(duì)象參數(shù)調(diào)用失敗的問(wèn)題
這篇文章主要介紹了解決SpringCloud Feign傳對(duì)象參數(shù)調(diào)用失敗的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
詳解Java實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)之并查集
并查集這種數(shù)據(jù)結(jié)構(gòu),可能出現(xiàn)的頻率不是那么高,但是還會(huì)經(jīng)常性的見(jiàn)到,其理解學(xué)習(xí)起來(lái)非常容易,通過(guò)本文,一定能夠輕輕松松搞定并查集2021-06-06
SpringBoot2.1.4中的錯(cuò)誤處理機(jī)制
這篇文章主要介紹了SpringBoot2.1.4中的錯(cuò)誤處理機(jī)制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
elasticsearch索引index之Translog數(shù)據(jù)功能分析
這篇文章主要為大家介紹了elasticsearch索引index之Translog數(shù)據(jù)功能分析,主要分析translog的結(jié)構(gòu)及寫(xiě)入方式,有需要的朋友可以借鑒參考下2022-04-04

