中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot中怎么實現動態數據源

發布時間:2021-07-30 16:05:45 來源:億速云 閱讀:141 作者:Leah 欄目:大數據

springboot中怎么實現動態數據源,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

/**
 * 作用:保存一個線程安全的DatabaseType容器
 */
public class DatabaseContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    /**
     * 當需要操作數據庫前,也就是調用mapper.c/r/u/d方法前,可以調用該方法
     * 該方法的作用是設置需要連接的數據庫
     * 由于是線程安全,如果一個新的controller連接請求,在操作數據庫前沒有顯式的調用該方法,則get到的databaseType將會為null
     * 但這并不影響數據庫的操作,因為在數據源的設置中已經設置了默認的數據源
     * 當在同一個線程中(也就是本系統controller的同一個請求處理中),如果該方法被調用過
     * 則后面的數據庫操作,也就是mapper.c/r/u/d的時,get到的都是set好的數據源,除非再次顯式的調用這個set方法改變數據源
     */
    public static void setDatabaseType(String type) {
        contextHolder.set(type);
    }

    /**
     * 當通過mapper.c/r/u/d方法等操作數據庫時
     * 該方法會自動被determineCurrentLookupKey方法調用到
     * determineCurrentLookupKey是重寫了Spring里的AbstractRoutingDataSource類的determineCurrentLookupKey方法
     *
     * @see DynamicDataSource
     */
    public static String getDatabaseType() {
        return contextHolder.get();
    }
}


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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.core.env.Environment;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 數據源工具類
 */
@Configuration
@Slf4j
public class DataSourceUtil {

    @Autowired
    private Environment env;

    //默認數據源
    private DataSource defaultDataSource;

    //用戶自定義數據源
    private Map<String, DataSource> slaveDataSources = new HashMap<>();

    /**
     * @see org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
     */
    @Bean
    @Primary
    public DynamicDataSource dataSource() throws Exception {
        initDefaultDataSource();
        initSlaveDataSources();

        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("", defaultDataSource);
        targetDataSources.putAll(slaveDataSources);

        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setDefaultTargetDataSource(defaultDataSource);// 該方法是AbstractRoutingDataSource的方法,默認數據源
        dataSource.setTargetDataSources(targetDataSources);// 該方法是AbstractRoutingDataSource的方法,數據源map
        return dataSource;
    }

    private void initDefaultDataSource() {
        // 讀取主數據源
        Map<String, String> dsMap = new HashMap<>();
        dsMap.put("driver", env.getProperty("spring.datasource.driver"));
        dsMap.put("url", env.getProperty("spring.datasource.url"));
        dsMap.put("username", env.getProperty("spring.datasource.username"));
        dsMap.put("password", env.getProperty("spring.datasource.password"));
        defaultDataSource = buildDataSource(dsMap);
    }


    private void initSlaveDataSources() {
        // 讀取配置文件獲取更多數據源
        String dsPrefixs = env.getProperty("slave.datasource.names");
        for (String dsPrefix : dsPrefixs.split(",")) {
            // 多個數據源
            Map<String, String> dsMap = new HashMap<>();
            dsMap.put("driver", env.getProperty("slave.datasource." + dsPrefix + ".driver"));
            dsMap.put("url", env.getProperty("slave.datasource." + dsPrefix + ".url"));
            dsMap.put("username", env.getProperty("slave.datasource." + dsPrefix + ".username"));
            dsMap.put("password", env.getProperty("slave.datasource." + dsPrefix + ".password"));
            DataSource ds = buildDataSource(dsMap);
            slaveDataSources.put(dsPrefix, ds);
        }
    }

    //指定默認數據源(springboot2.0默認數據源是hikari如何想使用其他數據源可以自己配置)
    private static final String DATASOURCE_TYPE_DEFAULT = "com.zaxxer.hikari.HikariDataSource";

    private DataSource buildDataSource(Map<String, String> dataSourceMap) {
        try {
            Object type = dataSourceMap.get("type");
            if (type == null) {
                type = DATASOURCE_TYPE_DEFAULT;// 默認DataSource
            }
            log.debug("data source type:{}", type);
            Class<? extends DataSource> dataSourceType;
            dataSourceType = (Class<? extends DataSource>) Class.forName((String) type);
            String driverClassName = dataSourceMap.get("driver");
            String url = dataSourceMap.get("url");
            String username = dataSourceMap.get("username");
            String password = dataSourceMap.get("password");
            // 自定義DataSource配置
            DataSourceBuilder factory = DataSourceBuilder.create().driverClassName(driverClassName).url(url)
                    .username(username).password(password).type(dataSourceType);
            return factory.build();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}


import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * 動態數據源(需要繼承AbstractRoutingDataSource)
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DatabaseContextHolder.getDatabaseType();
    }
}


    @Value("#{'${slave.datasource.names}'.split(',')}")
    private List<String> dsNameList;

    public int monitor() {
        // 默認數據源
        if (heartBeatDatabase(Strings.EMPTY) == 0)
            isError = true;

        // 其他數據源
        for (String dsName : dsNameList) {
            if (heartBeatDatabase(dsName) == 0)
                isError = true;
        }

        // 出現異常
        if (isError) {
            isError = false;
            return 0;
        }

        return 1;
    }

    private int heartBeatDatabase(String dsName) {
        try {
            DatabaseContextHolder.setDatabaseType(dsName);
            return monitorDao.select();
        }
        catch (Exception e) {
            log.error("heartbeat error!");
            try {
                sendMail(dsName);
            } catch (MessagingException e1) {
                log.error("send mail error!", e);
            }
        }
        return 0;
    }


# mysql配置
spring.datasource.url=jdbc:mysql://130.51.23.249:3306/vacdb01?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root1
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# ds1,ds2等其他數據源,記得不要漏!否則下面配置了也是白配。
slave.datasource.names=ds1,ds2,ds3
# ds1
slave.datasource.ds1.driver=com.mysql.cj.jdbc.Driver
slave.datasource.ds1.url=jdbc:mysql://130.51.23.249:3306/flowable?useSSL=false
slave.datasource.ds1.username=flowable
slave.datasource.ds1.password=
# ds2
slave.datasource.ds2.driver=com.mysql.cj.jdbc.Driver
slave.datasource.ds2.url=jdbc:mysql://132.120.2.134:3300/motor?useSSL=false
slave.datasource.ds2.username=motor
slave.datasource.ds2.password=
# ds3
slave.datasource.ds3.driver=com.mysql.cj.jdbc.Driver
slave.datasource.ds3.url=jdbc:mysql://130.51.23.249:8066/VACDB?useUnicode=true&characterEncoding=utf-8
slave.datasource.ds3.username=vac
slave.datasource.ds3.password=

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

无极县| 清原| 舟山市| 新邵县| 海城市| 阿拉善左旗| 桂林市| 桦南县| 黄龙县| 正宁县| 漳州市| 嘉鱼县| 丘北县| 鄱阳县| 岳池县| 互助| 浮梁县| 松潘县| 吉木乃县| 舒城县| 璧山县| 南充市| 遂川县| 阜南县| 绥化市| 荃湾区| 万盛区| 抚远县| 河东区| 成都市| 仙游县| 肥乡县| 文昌市| 莱西市| 观塘区| 大田县| 宝应县| 府谷县| 如皋市| 宣汉县| 镇坪县|