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

SpringBoot集成Druid實現(xiàn)多數(shù)據(jù)源的兩種方式

 更新時間:2024年03月10日 14:53:33   作者:濤哥是個大帥比  
這篇文章主要介紹了SpringBoot集成Druid實現(xiàn)多數(shù)據(jù)源的兩種方式,集成com.baomidou的方式和基于AOP手動實現(xiàn)多數(shù)據(jù)源原生的方式,文中通過代碼示例講解的非常詳細,需要的朋友可以參考下

項目場景:

Spring Boot集成Druid實現(xiàn)多數(shù)據(jù)源的兩種方式:

1、集成com.baomidou,引入dynamic-datasource依賴;

2、原生的方式,基于AOP手動實現(xiàn)多數(shù)據(jù)源;

一、集成com.baomidou的方式

1、maven依賴:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>
 
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

2、 配置文件:

1.spring.datasource.dynamic前綴,是baomidou源碼里固定的;

2.first、second是自定義的名稱,可以更改;

# 多數(shù)據(jù)源配置,默認master
spring.datasource.dynamic.primary = first
# 數(shù)據(jù)源1
spring.datasource.dynamic.datasource.first.driverClassName = com.mysql.cj.jdbc.Driver
spring.datasource.dynamic.datasource.first.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.dynamic.datasource.first.url = jdbc:mysql://127.0.0.1:3306/mp_dm?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.dynamic.datasource.first.username = test
spring.datasource.dynamic.datasource.first.password = test1
# 數(shù)據(jù)源2
spring.datasource.dynamic.datasource.second.driverClassName = com.mysql.cj.jdbc.Driver
spring.datasource.dynamic.datasource.second.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.dynamic.datasource.second.url = jdbc:mysql://127.0.0.1:18306/mp_dm?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.dynamic.datasource.second.username = test
spring.datasource.dynamic.datasource.second.password = test1
 
# druid多數(shù)據(jù)源全局配置
spring.datasource.dynamic.druid.filter.stat.log-slow-sql = true
spring.datasource.dynamic.druid.filter.stat.slow-sql-millis = 1000
spring.datasource.dynamic.druid.min-evictable-idle-time-millis = 300000
spring.datasource.dynamic.druid.test-on-borrow = false
spring.datasource.dynamic.druid.filter.stat.merge-sql = false
spring.datasource.dynamic.druid.test-on-return = false
spring.datasource.dynamic.druid.initial-size = 10
spring.datasource.dynamic.druid.min-idle = 10
spring.datasource.dynamic.druid.max-wait = 60000
spring.datasource.dynamic.druid.pool-prepared-statements = true
spring.datasource.dynamic.druid.test-while-idle = true
spring.datasource.dynamic.druid.validation-query = select 1
spring.datasource.dynamic.druid.filter.wall.config.multi-statement-allow = true
spring.datasource.dynamic.druid.time-between-eviction-runs-millis = 60000
spring.datasource.dynamic.druid.max-pool-prepared-statement-per-connection-size = 20
spring.datasource.dynamic.druid.max-active = 100
# druid監(jiān)控全局配置
spring.datasource.druid.stat-view-servlet.enabled = true
spring.datasource.druid.stat-view-servlet.url-pattern = /druid/*

驗證配置文件是否生效:Spring Boot集成Druid查看配置是否生效

3、 使用注解切換數(shù)據(jù)源: 

@DS注解說明:

1.注解在方法上、類上、接口、枚舉,同時存在就近原則,方法上注解優(yōu)先于類上注解;

2.不使用@DS注解,默認主數(shù)據(jù)源;

類上:

@DS("db2")
public class test(){}

方法上:

@DS("db2")
public void test(){}

mapper方法上

@Select("SELECT * FROM TEST WHERE A = #{A}")
@DS("db2")
Map<String, Object> test(@Param("A") String A);

二、基于AOP手動實現(xiàn)多數(shù)據(jù)源原生的方式

1、maven依賴:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

2、 配置文件:

1.Spring Boot 2.X 版本不再支持配置繼承,多數(shù)據(jù)源的話每個數(shù)據(jù)源的所有配置都需要單獨配置,否則配置不會生效;

2.first、second是自定義的名稱,對應(yīng)DynamicDataSourceConfig配置類,可以更改;

# 多數(shù)據(jù)源配置
spring.datasource.type = com.alibaba.druid.pool.DruidDataSource
# 數(shù)據(jù)源1
spring.datasource.druid.first.name = first
spring.datasource.druid.first.driverClassName = com.mysql.cj.jdbc.Driver
spring.datasource.druid.first.url = jdbc:mysql://127.0.0.1:3306/mp_dm?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.druid.first.username = test
spring.datasource.druid.first.password = test1
# 數(shù)據(jù)源2
spring.datasource.druid.second.name = second
spring.datasource.druid.second.driverClassName = com.mysql.cj.jdbc.Driver
spring.datasource.druid.second.url = jdbc:mysql://127.0.0.1:18306/mp_dm?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.druid.second.username = test
spring.datasource.druid.second.password = test1
 
# druid數(shù)據(jù)源1
spring.datasource.druid.first.filter.stat.log-slow-sql = true
spring.datasource.druid.first.filter.stat.slow-sql-millis = 1000
spring.datasource.druid.first.min-evictable-idle-time-millis = 300000
spring.datasource.druid.test-on-borrow = false
spring.datasource.druid.first.filter.stat.merge-sql = false
spring.datasource.druid.test-on-return = false
spring.datasource.druid.first.initial-size = 10
spring.datasource.druid.first.min-idle = 10
spring.datasource.druid.first.max-wait = 60000
spring.datasource.druid.first.pool-prepared-statements = true
spring.datasource.druid.first.test-while-idle = true
spring.datasource.druid.first.validation-query = select 1
spring.datasource.druid.first.filter.wall.config.multi-statement-allow = true
spring.datasource.druid.first.time-between-eviction-runs-millis = 60000
spring.datasource.druid.first.max-pool-prepared-statement-per-connection-size = 20
spring.datasource.druid.first.max-active = 100
# druid數(shù)據(jù)源2
spring.datasource.druid.second.filter.stat.log-slow-sql = true
spring.datasource.druid.second.filter.stat.slow-sql-millis = 1000
spring.datasource.druid.second.min-evictable-idle-time-millis = 300000
spring.datasource.druid.second.test-on-borrow = false
spring.datasource.druid.second.filter.stat.merge-sql = false
spring.datasource.druid.second.test-on-return = false
spring.datasource.druid.second.initial-size = 10
spring.datasource.druid.second.min-idle = 10
spring.datasource.druid.second.max-wait = 60000
spring.datasource.druid.second.pool-prepared-statements = true
spring.datasource.druid.second.test-while-idle = true
spring.datasource.druid.second.validation-query = select 1
spring.datasource.druid.second.filter.wall.config.multi-statement-allow = true
spring.datasource.druid.second.time-between-eviction-runs-millis = 60000
spring.datasource.druid.second.max-pool-prepared-statement-per-connection-size = 20
spring.datasource.druid.second.max-active = 100
# druid監(jiān)控全局配置
spring.datasource.druid.stat-view-servlet.enabled = true
spring.datasource.druid.stat-view-servlet.url-pattern = /druid/*

驗證配置文件是否生效:Spring Boot集成Druid查看配置是否生效

3、 多數(shù)據(jù)源名稱類

package com.test.datasources;
 
/**
 * 增加多數(shù)據(jù)源,在此配置
 */
public interface DataSourceNames {
    String FIRST = "first";
    String SECOND = "second";
 
} 

4、自定義注解

package com.test.datasources.annotation;
 
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * 多數(shù)據(jù)源注解
 */
//同時支持方法注解和類注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    String value() default "";
}

5、配置類

package com.test.datasources;
 
import java.util.HashMap;
import java.util.Map;
 
import javax.sql.DataSource;
 
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
 
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
 
/**
 * 配置多數(shù)據(jù)源
 */
@Configuration
public class DynamicDataSourceConfig {
 
    @Bean
    @ConfigurationProperties("spring.datasource.druid.first")
    public DataSource firstDataSource(){
        return DruidDataSourceBuilder.create().build();
    }
 
    @Bean
    @ConfigurationProperties("spring.datasource.druid.second")
    public DataSource secondDataSource(){
        return DruidDataSourceBuilder.create().build();
    }
 
    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource firstDataSource, DataSource secondDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceNames.FIRST, firstDataSource);
        targetDataSources.put(DataSourceNames.SECOND, secondDataSource);
        return new DynamicDataSource(firstDataSource, targetDataSources);
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate() {
     return new JdbcTemplate(firstDataSource());
    }
}

6、動態(tài)數(shù)據(jù)源配置

package com.test.datasources;
 
import java.util.Map;
 
import javax.sql.DataSource;
 
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
 
/**
 * 動態(tài)數(shù)據(jù)源,關(guān)鍵代碼
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
 
    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }
 
    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }
 
    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }
 
    public static String getDataSource() {
        return contextHolder.get();
    }
 
    public static void clearDataSource() {
        contextHolder.remove();
    }
 
}

7、AOP切面攔截注解

package com.test.datasources.aspect;
 
import java.lang.reflect.Method;
 
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
 
import com.test.datasources.DataSourceNames;
import com.test.datasources.DynamicDataSource;
import com.test.datasources.annotation.DataSource;
 
/**
 * 多數(shù)據(jù)源,切面處理類
 */
@Aspect
@Component
public class DataSourceAspect implements Ordered {
    protected Logger logger = LoggerFactory.getLogger(getClass());
 
    /*
     * @annotation匹配指定注解的方法
     * @within匹配指定注解的類
     * 注意:這里只攔截所注解的類,如果調(diào)用的是父類的方法,那么不會攔截,除非父類方法在子類中被覆蓋。
     */
    @Pointcut("@annotation(com.test.datasources.annotation.DataSource) || @within(com.test.datasources.annotation.DataSource)")
    public void dataSourcePointCut() {
 
    }
 
    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Class<?> dataClass = Class.forName(signature.getDeclaringTypeName());
        
        DataSource dsMethod = method.getAnnotation(DataSource.class);
        DataSource dsClass = dataClass.getAnnotation(DataSource.class);
        if(dsMethod != null){
        	//方法優(yōu)先,如果方法上存在注解,則優(yōu)先使用方法上的注解
        	DynamicDataSource.setDataSource(dsMethod.value());
            logger.debug("set datasource is " + dsMethod.value());
        }else if(dsClass != null){
            //其次類優(yōu)先,如果類上存在注解,則使用類上的注解
        	DynamicDataSource.setDataSource(dsClass.value());
            logger.debug("set datasource is " + dsClass.value());
        }else{
        	//如果都不存在,則使用默認
        	DynamicDataSource.setDataSource(DataSourceNames.FIRST);
            logger.debug("set datasource is " + DataSourceNames.FIRST);
        }
 
        try {
            return point.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
            logger.debug("clean datasource");
        }
    }
 
    @Override
    public int getOrder() {
        return 1;
    }
}

8、Dao層,跟正常一樣的

package com.test.mapper;
 
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
 
import com.test.entity.Test1Entity;
 
@Mapper
public interface Test1Dao {
	
	@Select("select * from test1")
	Test1Entity getById(@Param("id")Integer id);
}
package com.test.mapper;
 
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
 
import com.test.entity.Test2Entity;
 
@Mapper
public interface Test2Dao {
	@Select("select * from test2")
	Test2Entity getById(@Param("id")Integer id);
}

9、service層,加上多數(shù)據(jù)源注解

package com.test.service;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.test.datasources.DataSourceNames;
import com.test.datasources.annotation.DataSource;
import com.test.entity.Test1Entity;
import com.test.mapper.Test1Dao;
 
@Service
@DataSource(DataSourceNames.FIRST)
public class Test1Service {
 
	@Autowired
	private Test1Dao test1Dao;
	
	public Test1Entity getById(int id) {
		return test1Dao.getById(id);
	}
}
package com.test.service;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.test.datasources.DataSourceNames;
import com.test.datasources.annotation.DataSource;
import com.test.entity.Test2Entity;
import com.test.mapper.Test2Dao;
 
@Service
@DataSource(DataSourceNames.SECOND)
public class Test2Service  {
 
	@Autowired
	private Test2Dao test2Dao;
	
	public Test2Entity getById(int id) {
		return test2Dao.getById(id);
	}
}

10、Controller測試

package com.test.controller;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
import com.test.entity.Test1Entity;
import com.test.entity.Test2Entity;
import com.test.service.Test1Service;
import com.test.service.Test2Service;
 
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
 
/**
 * 動態(tài)數(shù)據(jù)源測試
 */
@Api(tags = "動態(tài)數(shù)據(jù)源測試")
@RestController
@RequestMapping("/test")
public class DynamicController {
 
	@Autowired
	private Test1Service test1Service;
	@Autowired
	private Test2Service test2Service;
	
	@ApiOperation(value = "數(shù)據(jù)源1")
	@RequestMapping(value = "/test1", method = RequestMethod.GET)
	public String test1() {
		Test1Entity entity = test1Service.getById(1);
		return entity.getName();
	}
	
	@ApiOperation(value = "數(shù)據(jù)源2")
	@RequestMapping(value = "/test2", method = RequestMethod.GET)
	public String test2() {
		Test2Entity entity = test2Service.getById(2);
		return entity.getName();
	}
}

三、結(jié)果展示

服務(wù)啟動會打印日志:

com.alibaba.druid.pool.DruidDataSource   : {dataSource-1,first} inited
com.alibaba.druid.pool.DruidDataSource   : {dataSource-2,second} inited

druid監(jiān)控頁面:

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

相關(guān)文章

  • Java數(shù)據(jù)結(jié)構(gòu)與算法之插值查找解析

    Java數(shù)據(jù)結(jié)構(gòu)與算法之插值查找解析

    這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)與算法之插值查找解析,插值查找算法類似于二分查找,不同的就是插值查找每次從自適應(yīng)mid處開始查找,需要的朋友可以參考下
    2023-12-12
  • Java無需Office環(huán)境實現(xiàn)Word轉(zhuǎn)HTML功能

    Java無需Office環(huán)境實現(xiàn)Word轉(zhuǎn)HTML功能

    在企業(yè)級開發(fā)、文檔管理系統(tǒng)、在線預(yù)覽等場景中,Word?文檔轉(zhuǎn)換為?HTML?是高頻需求,?本文將從環(huán)境配置、基礎(chǔ)轉(zhuǎn)換、高級定制等維度,全面講解基于該庫的?Word?轉(zhuǎn)?HTML?技術(shù)實現(xiàn),希望對大家有所幫助
    2026-05-05
  • 利用JavaFX工具構(gòu)建Reactive系統(tǒng)

    利用JavaFX工具構(gòu)建Reactive系統(tǒng)

    這篇文章主要介紹了使用JavaFX構(gòu)建Reactive系統(tǒng),利用JavaFX工具集中的新的超棒特性來構(gòu)建響應(yīng)式的快速應(yīng)用程序,感興趣的小伙伴們可以參考一下
    2016-02-02
  • maven配置阿里云倉庫的實現(xiàn)方法

    maven配置阿里云倉庫的實現(xiàn)方法

    本文主要介紹了maven配置阿里云倉庫的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • Java字符串的intern方法有何奧妙之處

    Java字符串的intern方法有何奧妙之處

    intern() 方法返回字符串對象的規(guī)范化表示形式。它遵循以下規(guī)則:對于任意兩個字符串 s 和 t,當且僅當 s.equals(t) 為 true 時,s.intern() == t.intern() 才為 true
    2021-10-10
  • IDEA中Maven爆紅以及依賴下載失敗的最全解決方案

    IDEA中Maven爆紅以及依賴下載失敗的最全解決方案

    這篇文章主要介紹了IDEA中Maven爆紅,依賴下載失敗的最全解決方案,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • servlet實現(xiàn)簡單的權(quán)限管理和敏感詞過濾功能

    servlet實現(xiàn)簡單的權(quán)限管理和敏感詞過濾功能

    JavaEE課要求用servlet和過濾器實現(xiàn)權(quán)限管理和敏感詞過濾功能,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05
  • JVM的常用命令匯總

    JVM的常用命令匯總

    監(jiān)測java應(yīng)用,最方便的就是直接使用jdk提供的現(xiàn)成工具,在jdk的安裝的bin目錄下,已經(jīng)提供了多種命令行監(jiān)測工具。本文為大家總結(jié)了幾個JVM的常用命令,需要的可以參考一下
    2022-10-10
  • Java異常架構(gòu)和異常關(guān)鍵字圖文詳解

    Java異常架構(gòu)和異常關(guān)鍵字圖文詳解

    Java異常是Java提供的一種識別及響應(yīng)錯誤的一致性機制,下面這篇文章主要給大家介紹了關(guān)于Java異常架構(gòu)和異常關(guān)鍵字的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-05-05
  • 淺析Java中的WeakHashMap

    淺析Java中的WeakHashMap

    這篇文章主要介紹了淺析Java中的WeakHashMap,WeakHashMap其實和HashMap大多數(shù)行為是一樣的,只是WeakHashMap不會阻止GC回收key對象,那么WeakHashMap是怎么做到的呢,這就是我們研究的主要問題,需要的朋友可以參考下
    2023-09-09

最新評論

黑水县| 固原市| 诏安县| 尚志市| 晋江市| 南陵县| 南昌县| 论坛| 墨玉县| 方城县| 定陶县| 神木县| 宝清县| 河南省| 横山县| 闻喜县| 济南市| 丹巴县| 塔河县| 宁津县| 招远市| 民丰县| 融水| 吴旗县| 海淀区| 新巴尔虎右旗| 安陆市| 耒阳市| 沐川县| 南平市| 青岛市| 阿拉善盟| 丹寨县| 越西县| 宁阳县| 娄烦县| 神木县| 平舆县| 瓦房店市| 石楼县| 兴安县|