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

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

 更新時間: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)(配置簡單)

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ù)
      initial-size: 10
      # 連接池的最小空閑數(shù)量
      min-idle: 5
      # 連接池最大連接數(shù)量
      max-active: 20
      # 獲取連接時最大等待時間,單位毫秒
      max-wait: 60000
      # 申請連接的時候檢測,如果空閑時間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測連接是否有效。
      test-while-idle: true
      # 既作為檢測的間隔時間又作為testWhileIdel執(zhí)行的依據(jù)
      time-between-eviction-runs-millis: 60000
      # 銷毀線程時檢測當(dāng)前連接的最后活動時間和當(dāng)前時間差大于該值時,關(guān)閉當(dāng)前連接(配置連接在池中的最小生存時間)
      min-evictable-idle-time-millis: 30000
      # 用來檢測數(shù)據(jù)庫連接是否有效的sql 必須是一個查詢語句(oracle中為 select 1 from dual)
      validation-query: SELECT 1 FROM DUAL
      # 申請連接時會執(zhí)行validationQuery檢測連接是否有效,開啟會降低性能,默認(rèn)為true
      test-on-borrow: false
      # 歸還連接時會執(zhí)行validationQuery檢測連接是否有效,開啟會降低性能,默認(rèn)為true
      test-on-return: false
      # 是否緩存preparedStatement, 也就是PSCache,PSCache對支持游標(biāo)的數(shù)據(jù)庫性能提升巨大,比如說oracle,在mysql下建議關(guān)閉。
      pool-prepared-statements: false
      # 置監(jiān)控統(tǒng)計攔截的filters,去掉后監(jiān)控界面sql無法統(tǒng)計,stat: 監(jiān)控統(tǒng)計、Slf4j:日志記錄、waLL: 防御sqL注入
      filters: stat,wall,slf4j
      # 要啟用PSCache,必須配置大于0,當(dāng)大于0時,poolPreparedStatements自動觸發(fā)修改為true。在Druid中,不會存在Oracle下PSCache占用內(nèi)存過多的問題,可以把這個數(shù)值配置大一些,比如說100
      max-pool-prepared-statement-per-connection-size: -1
      # 合并多個DruidDataSource的監(jiān)控數(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時,跳轉(zhuǎn)到StatViewServlet
        url-pattern: /druid/*
        # 是否能夠重置數(shù)據(jù)
        reset-enable: false
        # 需要賬號密碼才能訪問控制臺,默認(rèn)為root  http://localhost:8585/druid/
        login-username: root
        login-password: 123456
        # IP白名單
        allow: 127.0.0.1
        # IP黑名單(共同存在時,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ù)源時會拋出異常,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ū)動的版本(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ū)動的版本(com.mysql.cj.jdbc.Driver 或 com.mysql.jdbc.Driver)
          driver-class-name: com.mysql.cj.jdbc.Driver

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

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

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注解可以用在方法上或類上,同時存在就近原則,方法上注解優(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來獲取會話工廠SqlSessionFactory,不然的話,baseMapper中的生成動態(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ù)庫時會調(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)容請搜索腳本之家以前的文章或繼續(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)證最簡單的一種方式,也可以說是最簡陋的一種方式,這篇文章主要介紹了Spring Security的HttpBasic登錄驗(yàn)證模式,需要的朋友可以參考下
    2019-11-11
  • IDEA 啟動 Tomcat 項(xiàng)目輸出亂碼的解決方法

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

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

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

    今天帶大家了解一下Java稀疏數(shù)組的相關(guān)知識,文中有非常詳細(xì)的介紹及代碼示例,對正在學(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ì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • java設(shè)計模式學(xué)習(xí)之工廠方法模式

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

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

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

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

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

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

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

    這篇文章主要介紹了詳解 Java中日期數(shù)據(jù)類型的處理之格式轉(zhuǎn)換的實(shí)例的相關(guān)資料,日期以及時間格式處理,在Java中時間格式一般會涉及到的數(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)勢包括分層構(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

最新評論

阿拉善右旗| 秦安县| 泌阳县| 上杭县| 阿瓦提县| 岚皋县| 四川省| 南安市| 永修县| 台江县| 阿瓦提县| 隆尧县| 永昌县| 余江县| 军事| 工布江达县| 贡嘎县| 茌平县| 翼城县| 罗平县| 泰兴市| 万源市| 临清市| 虎林市| 蚌埠市| 桂东县| 水城县| 泸定县| 宣城市| 布尔津县| 岗巴县| 柞水县| 南陵县| 宜君县| 磐石市| 佳木斯市| 郑州市| 阿拉善左旗| 台北县| 浦江县| 云阳县|