欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot動態(tài)配置數(shù)據(jù)源的三種實現(xiàn)方式

 更新時間:2025年08月13日 10:17:11   作者:Best_Liu~  
本文介紹了Spring Boot動態(tài)數(shù)據(jù)源的三種實現(xiàn)方式:通過配置文件設(shè)置數(shù)據(jù)源,自定義DynamicDataSource繼承AbstractRoutingDataSource實現(xiàn)動態(tài)切換,利用ThreadLocal管理數(shù)據(jù)源標(biāo)識,并結(jié)合AOP控制切換邏輯,同時需整合MyBatis-Plus配置,需要的朋友可以參考下

一、Apache Druid方式

1、配置文件

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    master:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&generateSimpleParameterMetadata=true&autoReconnect=true&useSSL=true
      username: root
      password: root3306
    slave:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&generateSimpleParameterMetadata=true&autoReconnect=true&useSSL=true
      username: root
      password: root3306
    druid-pool:
      #連接池的最大數(shù)據(jù)庫連接數(shù)。設(shè)為0表示無限制
      max-active: 20
      #初始化數(shù)量
      initial-size: 2
      #最大建立連接等待時間。如果超過此時間將接到異常。設(shè)為-1表示無限制
      max-wait: 60000
      #最小空閑連接:連接池中容許保持空閑狀態(tài)的最小連接數(shù)量,低于這個數(shù)量將創(chuàng)建新的連接
      min-idle: 2

2、配置數(shù)據(jù)源

配置數(shù)據(jù)源基本信息,并將所有數(shù)據(jù)源添加到動態(tài)數(shù)據(jù)源中進行進行管理

@Configuration
public class DynamicDataSourceConfig {
 
    @Value("${spring.datasource.type}")
    private Class<? extends DataSource> dataSourceType;
 
    @Value("${spring.datasource.druid-pool.initial-size}")
    private int initialSize;
    @Value("${spring.datasource.druid-pool.max-active}")
    private int maxActive;
    @Value("${spring.datasource.druid-pool.max-wait}")
    private int maxWait;
    @Value("${spring.datasource.druid-pool.min-idle}")
    private int minIdle;
 
    @Primary
    @Bean("masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        DruidDataSource druidDataSource = (DruidDataSource) DataSourceBuilder.create().type(dataSourceType).build();
        druidPoolConfig(druidDataSource);
        return druidDataSource;
    }
 
    @Bean("slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        DruidDataSource druidDataSource = (DruidDataSource) DataSourceBuilder.create().type(dataSourceType).build();
        druidPoolConfig(druidDataSource);
        return druidDataSource;
    }
 
    private void druidPoolConfig(DruidDataSource druidDataSource) {
        druidDataSource.setMaxActive(maxActive);
        druidDataSource.setMaxWait(maxWait);
        druidDataSource.setInitialSize(initialSize);
        druidDataSource.setMinIdle(minIdle);
    }
 
    @Bean("dataSource")
    @DependsOn({"masterDataSource", "slaveDataSource"})
    public DataSource dataSource(@Qualifier("masterDataSource") DataSource masterDataSource, @Qualifier("slaveDataSource") DataSource slaveDataSource) {
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put("masterDataSource", masterDataSource);
        dataSourceMap.put("slaveDataSource", slaveDataSource);
        DynamicDataSourceContextHolder.dataSourceNames.add("masterDataSource");
        DynamicDataSourceContextHolder.dataSourceNames.add("slaveDataSource");
        // 設(shè)置動態(tài)數(shù)據(jù)源
        return new DynamicDataSource(masterDataSource, dataSourceMap);
    }
}
public class DynamicDataSource extends AbstractRoutingDataSource {
 
    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
    }
 
    @Override
    public Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSource();
    }
}

自定義DynamicDataSouce并繼承AbstractRoutingDataSource 。AbstractRoutingDataSource 是 Spring 框架中用于實現(xiàn)動態(tài)數(shù)據(jù)源路由的一個抽象類。它通過實現(xiàn)數(shù)據(jù)源的動態(tài)切換來支持多數(shù)據(jù)源的應(yīng)用場景。

AbstractRoutingDataSource 的核心原理是通過一個線程本地變量(ThreadLocal)來保存當(dāng)前使用的數(shù)據(jù)源標(biāo)識,然后在每次獲取連接時,根據(jù)這個標(biāo)識來決定使用哪個數(shù)據(jù)源。

主要方法包括:

1)determineCurrentLookupKey():這是一個抽象方法,需要子類實現(xiàn)。它用于確定當(dāng)前使用的數(shù)據(jù)源標(biāo)識。根據(jù)返回的標(biāo)識,AbstractRoutingDataSource 會從預(yù)先配置的數(shù)據(jù)源中選擇對應(yīng)的數(shù)據(jù)源。

2)setTargetDataSources():用于設(shè)置數(shù)據(jù)源的映射關(guān)系。這個方法接受一個 Map<Object, Object> 類型的參數(shù),鍵為數(shù)據(jù)源標(biāo)識,值為具體的數(shù)據(jù)源對象。

3)setDefaultTargetDataSource():用于設(shè)置默認的數(shù)據(jù)源。如果沒有找到匹配的數(shù)據(jù)源標(biāo)識,就會使用默認的數(shù)據(jù)源。

4)afterPropertiesSet():檢查配置,確保 targetDataSources 和 defaultTargetDataSource 屬性已被設(shè)置;初始化映射,將指定的默認數(shù)據(jù)源和目標(biāo)數(shù)據(jù)源映射解析并存儲到相應(yīng)的內(nèi)部變量中。

public class DynamicDataSourceContextHolder {
    private static final ThreadLocal<String> DATASOURCE_CONTEXT_HOLDER = new ThreadLocal<>();
    /**
     * 管理全部數(shù)據(jù)源
     */
    public static List<String> dataSourceNames = new ArrayList<>();
 
    /**
     * 判斷是否存在指定數(shù)據(jù)源
     */
    public static boolean containsDataSource(String dataSourceName) {
        return dataSourceNames.contains(dataSourceName);
    }
    /**
     * 設(shè)置當(dāng)前數(shù)據(jù)源
     */
    public static void setDataSource(String dataSourceName) {
        DATASOURCE_CONTEXT_HOLDER.set(dataSourceName);
    }
    /**
     * 獲取當(dāng)前數(shù)據(jù)源
     */
    public static String getDataSource() {
        return DATASOURCE_CONTEXT_HOLDER.get();
    }
    /**
     * 清除數(shù)據(jù)源
     */
    public static void clear() {
        DATASOURCE_CONTEXT_HOLDER.remove();
    }
}

ThreadLocal是Java中的一個工具類,能夠為每個線程提供一個獨立的變量副本,從而實現(xiàn)線程隔離。利用ThreadLocal管理當(dāng)前使用的數(shù)據(jù)源,DynamicDataSourceContextHolder可以在不同的線程間隔離數(shù)據(jù)源的使用,實現(xiàn)數(shù)據(jù)源的動態(tài)切換。

如果整合使用了Mybatis-Plus,則還需要添加Mybatis-Plus的相關(guān)配置,否則會報錯,如下所示

@Configuration
@MapperScan(basePackages = {"com.practice.mapper"}, sqlSessionTemplateRef = "sqlTemplateDefault")
public class MybatisConfig {
    @Bean(name = "sqlFactoryDefault")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource)
            throws Exception {
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        factoryBean.setDataSource(dynamicDataSource);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        factoryBean.setMapperLocations(resolver.getResources("classpath*:mapper/*/*.xml"));
        MybatisConfiguration mybatisConfiguration = new MybatisConfiguration();
        mybatisConfiguration.setLogImpl(StdOutImpl.class);
        factoryBean.setConfiguration(mybatisConfiguration);
        return factoryBean.getObject();
    }
 
    @Bean(name = "sqlTemplateDefault")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlFactoryDefault") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

3、利用AOP動態(tài)切換

自定義數(shù)據(jù)源標(biāo)識注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DS {
    String value() default "masterDataSource";
}

利用AOP實現(xiàn)動態(tài)切換數(shù)據(jù)源

@Component
@Aspect
@Slf4j
public class DynamicDataSourceAspect {
    private static final String DEFAULT_DATASOURCE = "masterDataSource";
 
    @Pointcut("@annotation(com.practice.annotation.DS)")
    public void dsPointCut() {}
 
    @Before("dsPointCut() && @annotation(ds)")
    public void changeDataSource(JoinPoint joinPoint, DS ds) {
        String dataSourceName = ds.value();
        if (DynamicDataSourceContextHolder.containsDataSource(dataSourceName)) {
            DynamicDataSourceContextHolder.setDataSource(dataSourceName);
            log.info("切換到數(shù)據(jù)源:{}", dataSourceName);
        } else {
            log.error("數(shù)據(jù)源不存在:{}", dataSourceName);
        }
    }
 
    @After("@annotation(ds)")
    public void clearDataSource(JoinPoint joinPoint, DS ds) {
        DynamicDataSourceContextHolder.clear();
    }
}

以上就是SpringBoot動態(tài)配置數(shù)據(jù)源的三種實現(xiàn)方式的詳細內(nèi)容,更多關(guān)于SpringBoot動態(tài)配置數(shù)據(jù)源的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 解決JAVA遍歷List集合,刪除數(shù)據(jù)時出現(xiàn)的問題

    解決JAVA遍歷List集合,刪除數(shù)據(jù)時出現(xiàn)的問題

    這篇文章主要介紹了解決JAVA遍歷List集合時,刪除數(shù)據(jù)出現(xiàn)的問題,文中講解非常細致,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • MyBatis3傳遞多個參數(shù)(Multiple Parameters)

    MyBatis3傳遞多個參數(shù)(Multiple Parameters)

    這篇文章主要介紹了MyBatis3傳遞多個參數(shù),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java基礎(chǔ)知識雜文

    Java基礎(chǔ)知識雜文

    這篇文章主要介紹了Java基礎(chǔ)知識雜文,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Java代理模式實例詳解【靜態(tài)代理與動態(tài)代理】

    Java代理模式實例詳解【靜態(tài)代理與動態(tài)代理】

    這篇文章主要介紹了Java代理模式,結(jié)合實例形式詳細分析了java靜態(tài)代理與動態(tài)代理模式相關(guān)概念、原理、操作技巧與注意事項,需要的朋友可以參考下
    2019-09-09
  • Java?MyBatis實戰(zhàn)之QueryWrapper中and和or拼接技巧大全

    Java?MyBatis實戰(zhàn)之QueryWrapper中and和or拼接技巧大全

    在Java中QueryWrapper是MyBatis-Plus框架中的一個查詢構(gòu)造器,它提供了豐富的查詢方法,其中包括and和or方法,可以用于構(gòu)建復(fù)雜的查詢條件,這篇文章主要給大家介紹了關(guān)于Java?MyBatis實戰(zhàn)之QueryWrapper中and和or拼接技巧的相關(guān)資料,需要的朋友可以參考下
    2024-07-07
  • 一步步教你寫一個SpringMVC框架

    一步步教你寫一個SpringMVC框架

    現(xiàn)在主流的Web MVC框架除了Struts這個主力外,其次就是Spring MVC了,因此這也是作為一名程序員需要掌握的主流框架,這篇文章主要給大家介紹了關(guān)于如何一步步寫一個SpringMVC框架的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • java程序運行時內(nèi)存分配詳解

    java程序運行時內(nèi)存分配詳解

    這篇文章主要介紹了java程序運行時內(nèi)存分配詳解 ,需要的朋友可以參考下
    2016-07-07
  • SpringBoot3.3.0升級方案

    SpringBoot3.3.0升級方案

    本文介紹了由SpringBoot2升級到SpringBoot3.3.0升級方案,新版本的升級可以解決舊版本存在的部分漏洞問題,感興趣的可以了解一下
    2024-08-08
  • springboot統(tǒng)一異常處理(返回json)并格式化異常

    springboot統(tǒng)一異常處理(返回json)并格式化異常

    這篇文章主要介紹了springboot統(tǒng)一異常處理(返回json)并格式化異常,對spring boot的默認異常處理方式進行修改,要統(tǒng)一返回數(shù)據(jù)格式,優(yōu)雅的數(shù)據(jù)交互,優(yōu)雅的開發(fā)應(yīng)用,需要的朋友可以參考下
    2023-07-07
  • 分析SpringBoot的啟動原理

    分析SpringBoot的啟動原理

    這篇文章主要分析了SpringBoot的啟動原理,幫助大家更好的理解和使用spring boot框架,感興趣的朋友可以了解下
    2020-09-09

最新評論