最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot項(xiàng)目配置多數(shù)據(jù)源的兩種方式詳解

 更新時(shí)間:2026年01月22日 09:43:06   作者:愛吃面條的猿  
這篇文章主要為大家詳細(xì)介紹了SpringBoot項(xiàng)目配置多數(shù)據(jù)源的兩種方式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

前提項(xiàng)目架構(gòu):SpringBoot+mybatis-plus-Druid

方式一、基于dynamic-datasource-spring-boot-starter實(shí)現(xiàn)(配置簡(jiǎn)單)

1、添加依賴

<!--引入多數(shù)據(jù)源需要的依賴包-->
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  <version>3.1.1</version>
</dependency>

2、在application.yml中配置多數(shù)據(jù)源

spring:
  application:
    name: zhangjiadayuan-server
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    # Druid的其他屬性配置
    druid:
      # 初始化時(shí)建立物理連接的個(gè)數(shù)
      initial-size: 10
      # 連接池的最小空閑數(shù)量
      min-idle: 5
      # 連接池最大連接數(shù)量
      max-active: 20
      # 獲取連接時(shí)最大等待時(shí)間,單位毫秒
      max-wait: 60000
      # 申請(qǐng)連接的時(shí)候檢測(cè),如果空閑時(shí)間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測(cè)連接是否有效。
      test-while-idle: true
      # 既作為檢測(cè)的間隔時(shí)間又作為testWhileIdel執(zhí)行的依據(jù)
      time-between-eviction-runs-millis: 60000
      # 銷毀線程時(shí)檢測(cè)當(dāng)前連接的最后活動(dòng)時(shí)間和當(dāng)前時(shí)間差大于該值時(shí),關(guān)閉當(dāng)前連接(配置連接在池中的最小生存時(shí)間)
      min-evictable-idle-time-millis: 30000
      # 用來檢測(cè)數(shù)據(jù)庫連接是否有效的sql 必須是一個(gè)查詢語句(oracle中為 select 1 from dual)
      validation-query: SELECT 1 FROM DUAL
      # 申請(qǐng)連接時(shí)會(huì)執(zhí)行validationQuery檢測(cè)連接是否有效,開啟會(huì)降低性能,默認(rèn)為true
      test-on-borrow: false
      # 歸還連接時(shí)會(huì)執(zhí)行validationQuery檢測(cè)連接是否有效,開啟會(huì)降低性能,默認(rèn)為true
      test-on-return: false
      # 是否緩存preparedStatement, 也就是PSCache,PSCache對(duì)支持游標(biāo)的數(shù)據(jù)庫性能提升巨大,比如說oracle,在mysql下建議關(guān)閉。
      pool-prepared-statements: false
      # 置監(jiān)控統(tǒng)計(jì)攔截的filters,去掉后監(jiān)控界面sql無法統(tǒng)計(jì),stat: 監(jiān)控統(tǒng)計(jì)、Slf4j:日志記錄、waLL: 防御sqL注入
      filters: stat,wall,slf4j
      # 要啟用PSCache,必須配置大于0,當(dāng)大于0時(shí),poolPreparedStatements自動(dòng)觸發(fā)修改為true。在Druid中,不會(huì)存在Oracle下PSCache占用內(nèi)存過多的問題,可以把這個(gè)數(shù)值配置大一些,比如說100
      max-pool-prepared-statement-per-connection-size: -1
      # 合并多個(gè)DruidDataSource的監(jiān)控?cái)?shù)據(jù)
      use-global-data-source-stat: true
      # 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄
      connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      web-stat-filter:
        # 是否啟用StatFilter默認(rèn)值true
        enabled: true
        # 添加過濾規(guī)則
        url-pattern: /*
        # 忽略過濾的格式
        exclusions: /druid/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico

      stat-view-servlet:
        # 是否啟用StatViewServlet默認(rèn)值true
        enabled: true
        # 訪問路徑為/druid時(shí),跳轉(zhuǎn)到StatViewServlet
        url-pattern: /druid/*
        # 是否能夠重置數(shù)據(jù)
        reset-enable: false
        # 需要賬號(hào)密碼才能訪問控制臺(tái),默認(rèn)為root  http://localhost:8585/druid/
        login-username: root
        login-password: 123456
        # IP白名單
        allow: 127.0.0.1
        # IP黑名單(共同存在時(shí),deny優(yōu)先于allow)
        deny:
    dynamic:
      primary: master #設(shè)置默認(rèn)的數(shù)據(jù)源或者數(shù)據(jù)源組
      strict: false #嚴(yán)格匹配數(shù)據(jù)源,默認(rèn)為false,true未匹配到數(shù)據(jù)源時(shí)會(huì)拋出異常,false使用默認(rèn)數(shù)據(jù)源
      datasource:
        master:
          # 數(shù)據(jù)源基本配置
          username: root
          password: root123
          url: jdbc:mysql://127.0.0.1:3306/zhangjiadayuan?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
          # driver-class需要注意mysql驅(qū)動(dòng)的版本(com.mysql.cj.jdbc.Driver 或 com.mysql.jdbc.Driver)
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave:
          # 數(shù)據(jù)源基本配置
          username: root
          password: root123
          url: jdbc:mysql://127.0.0.1:3306/zhangjiadayuan2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
          # driver-class需要注意mysql驅(qū)動(dòng)的版本(com.mysql.cj.jdbc.Driver 或 com.mysql.jdbc.Driver)
          driver-class-name: com.mysql.cj.jdbc.Driver

3、排除掉Druid的數(shù)據(jù)源自動(dòng)配置類

在啟動(dòng)類中需要排除掉DruidDataSourceAutoConfigure.class,就是取消Druid的數(shù)據(jù)源的自動(dòng)配置類。

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;


@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class})
@ComponentScan("cn.zhang.*")
@MapperScan("cn.zhang.mapper")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

4、切換數(shù)據(jù)源

使用@DS("數(shù)據(jù)源名字")切換數(shù)據(jù)源,@DS注解可以用在方法上或類上,同時(shí)存在就近原則,方法上注解優(yōu)先于類上;沒有使用@DS默認(rèn)使用默認(rèn)數(shù)據(jù)源。

方式二、基于自定義注解

1、配置文件配置多數(shù)據(jù)源

spring:
  datasource:
    druid:
      db1:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/db1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL&autoReconnect=true
        username: root
        password: 123456
      db2:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/db2?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL&autoReconnect=true
        username: root
        password: 123456
      test-on-borrow: true

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

該類的作用就是初始化數(shù)據(jù)源DataSource實(shí)例,以及初始化SqlSessionFactory實(shí)例。這里需要注意的是必須使用MybatisSqlSessionFactoryBean來獲取會(huì)話工廠SqlSessionFactory,不然的話,baseMapper中的生成動(dòng)態(tài)SQL的方法就不能使用了。

@Configuration(basePackages = MyBatisConfig.BASE_PACKAGE, sqlSessionTemplateRef = "sqlSessionTemplate")
public class DataSourceConfigurer {
    //mapper模式下的接口層
    static final String BASE_PACKAGE = "cn.zhang.mapper";
	public static final String CLASSPATH_MAPPING_XML = "classpath*:mapper/*.xml";
    /**
     * 配置數(shù)據(jù)源
     *
     * @return
     */
    @Bean(name = "db1")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.druid.db1")
    public DataSource db1() {
        return DruidDataSourceBuilder.create().build();
    }
    /**
     * 配置數(shù)據(jù)源
     *
     * @return
     */
    @Bean(name = "db2")
    @ConfigurationProperties(prefix = "spring.datasource.druid.db2")
    public DataSource db2() {
        return DruidDataSourceBuilder.create().build();
    }
    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
        Map<Object, Object> dataSourceMap = new HashMap<Object, Object>(2);
        dataSourceMap.put(DataSourceKey.Master.getName(), db1());
        dataSourceMap.put(DataSourceKey.SLAVE.getName(), db2());
        dynamicRoutingDataSource.setDefaultTargetDataSource(dcs());
        dynamicRoutingDataSource.setTargetDataSources(dataSourceMap);
        DynamicDataSourceContextHolder.dataSourceKeys.addAll(dataSourceMap.keySet());
        return dynamicRoutingDataSource;
    }
    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        //MybatisPlus使用的是MybatisSqlSessionFactory
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource());
        //此處設(shè)置為了解決找不到mapper文件的問題
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(CLASSPATH_MAPPING_XML));
        return sqlSessionFactoryBean.getObject();
    }
    @Bean
    public SqlSessionTemplate sqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory());
    }
    /**
     * 事務(wù)
     *
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }
/**
 * 該類繼承自 AbstractRoutingDataSource 類,
 * 在訪問數(shù)據(jù)庫時(shí)會(huì)調(diào)用該類的 determineCurrentLookupKey() 方法獲取數(shù)據(jù)庫實(shí)例的 key
 */
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        logger.info("current datasource is : {}", DynamicDataSourceContextHolder.getDataSourceKey());
        return DynamicDataSourceContextHolder.getDataSourceKey();
    }
}
public class DynamicDataSourceContextHolder {
    private static ThreadLocal<Object> CONTEXT_HOLDER = ThreadLocal.withInitial(() -> DataSourceKey.DCS.getName());
    public static List<Object> dataSourceKeys = new ArrayList<Object>();
    public static void setDataSourceKey(String key){
        CONTEXT_HOLDER.set(key);
    }
    public static Object getDataSourceKey(){
        return CONTEXT_HOLDER.get();
    }
    public static void clearDataSourceKey(){
        CONTEXT_HOLDER.remove();
    }
    public static Boolean containDataSourceKey(String key){
        return dataSourceKeys.contains(key);
    }
}
public enum DataSourceKey {
	MASTER("db1"),
	SLAVE("db2");
	
	private String name;
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	private DataSourceKey(String name) {
		this.name = name;
	}
}

3、自定義注解和定義切面

//該注解只是作用在方法上,這里默認(rèn)的數(shù)據(jù)源是DB1
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
    String value() default "db1";
}

 切面顧名思義就是攔擊標(biāo)注自定義注解@TargetDataSource注解的方法,并且根據(jù)注解指定的數(shù)據(jù)源的key切換數(shù)據(jù)源。

@Aspect
@Component
public class DynamicDataSourceAspect {
    private Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);
    @Before("@annotation(targetDataSource)")
    public void switchDataSource(JoinPoint joinPoint, TargetDataSource targetDataSource) {
        if (!DynamicDataSourceContextHolder.containDataSourceKey(targetDataSource.value().getName())) {
            logger.error("DataSource [{}] doesn't exist, use default DataSource [{}]", targetDataSource.value());
        } else {
            DynamicDataSourceContextHolder.setDataSourceKey(targetDataSource.value().getName());
            logger.info("Switch DataSource to [{}] in Method [{}]", DynamicDataSourceContextHolder.getDataSourceKey(), joinPoint.getSignature());
        }
    }
    @After("@annotation(targetDataSource)")
    public void restoreDataSource(JoinPoint joinPoint, TargetDataSource targetDataSource) {
        DynamicDataSourceContextHolder.clearDataSourceKey();
        logger.info("Restore DataSource to [{}] in Method [{}]", DynamicDataSourceContextHolder.getDataSourceKey(), joinPoint.getSignature());
    }
}

4、使用切換數(shù)據(jù)源

//也可用與Service方法或類上
@TargetDataSource("db2")
String getClassStudent(@Param("open_id") String openId);

到此這篇關(guān)于SpringBoot項(xiàng)目配置多數(shù)據(jù)源的兩種方式詳解的文章就介紹到這了,更多相關(guān)SpringBoot配置多數(shù)據(jù)源內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Spring Security中的HttpBasic登錄驗(yàn)證模式

    詳解Spring Security中的HttpBasic登錄驗(yàn)證模式

    HttpBasic登錄驗(yàn)證模式是Spring Security實(shí)現(xiàn)登錄驗(yàn)證最簡(jiǎn)單的一種方式,也可以說是最簡(jiǎn)陋的一種方式,這篇文章主要介紹了Spring Security的HttpBasic登錄驗(yàn)證模式,需要的朋友可以參考下
    2019-11-11
  • IDEA 啟動(dòng) Tomcat 項(xiàng)目輸出亂碼的解決方法

    IDEA 啟動(dòng) Tomcat 項(xiàng)目輸出亂碼的解決方法

    這篇文章主要介紹了IDEA 啟動(dòng) Tomcat 項(xiàng)目輸出亂碼的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 淺談Java數(shù)據(jù)結(jié)構(gòu)之稀疏數(shù)組知識(shí)總結(jié)

    淺談Java數(shù)據(jù)結(jié)構(gòu)之稀疏數(shù)組知識(shí)總結(jié)

    今天帶大家了解一下Java稀疏數(shù)組的相關(guān)知識(shí),文中有非常詳細(xì)的介紹及代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • 詳解Java創(chuàng)建多線程的四種方式以及優(yōu)缺點(diǎn)

    詳解Java創(chuàng)建多線程的四種方式以及優(yōu)缺點(diǎn)

    這篇文章主要介紹了Java創(chuàng)建多線程的四種方式以及優(yōu)缺點(diǎn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • java設(shè)計(jì)模式學(xué)習(xí)之工廠方法模式

    java設(shè)計(jì)模式學(xué)習(xí)之工廠方法模式

    這篇文章主要介紹了java設(shè)計(jì)模式學(xué)習(xí)之工廠方法模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • JDK1.8、JDK1.7、JDK1.6區(qū)別看這里

    JDK1.8、JDK1.7、JDK1.6區(qū)別看這里

    這篇文章主要為大家詳細(xì)介紹了JDK1.8、JDK1.7、JDK1.6中的源碼,對(duì)比閱讀,發(fā)現(xiàn)修改問題以及改進(jìn)點(diǎn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • SpringBoot如何引入緩存提高單次查詢數(shù)據(jù)效率

    SpringBoot如何引入緩存提高單次查詢數(shù)據(jù)效率

    這篇文章主要介紹了SpringBoot如何引入緩存提高單次查詢數(shù)據(jù)效率問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 詳解 Java中日期數(shù)據(jù)類型的處理之格式轉(zhuǎn)換的實(shí)例

    詳解 Java中日期數(shù)據(jù)類型的處理之格式轉(zhuǎn)換的實(shí)例

    這篇文章主要介紹了詳解 Java中日期數(shù)據(jù)類型的處理之格式轉(zhuǎn)換的實(shí)例的相關(guān)資料,日期以及時(shí)間格式處理,在Java中時(shí)間格式一般會(huì)涉及到的數(shù)據(jù)類型包括Calendar類和Date類,需要的朋友可以參考下
    2017-08-08
  • 使用Maven將Java項(xiàng)目打包為Docker鏡像的實(shí)戰(zhàn)方法

    使用Maven將Java項(xiàng)目打包為Docker鏡像的實(shí)戰(zhàn)方法

    本文介紹了兩種使用Maven將Java項(xiàng)目打包為Docker鏡像的實(shí)戰(zhàn)方法: Google Jib插件方案:無需Dockerfile,直接通過Maven插件構(gòu)建鏡像,優(yōu)勢(shì)包括分層構(gòu)建、安全高效、鏡像體積小,特別適合SpringBoot項(xiàng)目,文章詳細(xì)展示了使用Maven構(gòu)建Java項(xiàng)目并生成Docker鏡像的完整流程
    2026-02-02
  • IDEA 使用 SpotBugs 找出你代碼中的bug問題

    IDEA 使用 SpotBugs 找出你代碼中的bug問題

    這篇文章主要介紹了IDEA 使用 SpotBugs 找出你代碼中的bug問題,重點(diǎn)給大家介紹SpotBugs 在 idea 中的安裝和使用,感興趣的朋友跟隨小編一起看看吧
    2021-07-07

最新評(píng)論

留坝县| 合作市| 阜康市| 象州县| 佳木斯市| 元氏县| 景东| 康乐县| 壶关县| 东阳市| 六安市| 南宁市| 木里| 伊川县| 新平| 沈阳市| 泰兴市| 穆棱市| 昌邑市| 准格尔旗| 广东省| 五大连池市| 乌拉特前旗| 西林县| 天门市| 扎赉特旗| 新平| 贡嘎县| 绥江县| 泾川县| 胶州市| 炉霍县| 高碑店市| 大竹县| 二连浩特市| 镇宁| 政和县| 马关县| 威宁| 龙州县| 迭部县|