Spring Boot 动态切换数据源三——动态获取配置文件中的配置信息

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35981283/article/details/82145486

这块内容前前后后总共写了三篇
1. Spring Boot HikariCP 一 ——集成多数据源
2. Spring Boot 动态切换数据源二——负载均衡
3. Spring Boot 动态切换数据源三——动态获取配置文件中的配置信息

这里是接上篇文章
Spring Boot 动态切换数据源(负载均衡)

留下的问题,配置文件中数据库的信息更改后代码中能够动态获取。所以这里重点说下优化后的内容。

先看配置文件

slave:
  hosts: slave1,slave2
hikari:
  - master:
    jdbc-url: jdbc:mysql://master-host:3306/mydb?useUnicode=true&characterEncoding=utf8&useSSL=true&allowMultiQueries=true&verifyServerCertificate=false
    username: root
    password: root
    maximum-pool-size: 10
    pool-name: master
    connection-timeout: 30000
    idle-timeout: 600000
    max-lifetime: 1765000
    data-source-properties:
      cachePrepStmts: true
      prepStmtCacheSize: 250
      prepStmtCacheSqlLimit: 2048
      useServerPrepStmts: true
      useLocalSessionState: true
      useLocalTransactionState: true
      rewriteBatchedStatements: true
      cacheResultSetMetadata: true
      cacheServerConfiguration: true
      elideSetAutoCommits: true
      maintainTimeStats: false
  - slave1:
    jdbc-url: jdbc:mysql://slave1-host:3306/mydb?useUnicode=true&characterEncoding=utf8&useSSL=true&allowMultiQueries=true&verifyServerCertificate=false
    username: root
    password: root
    maximum-pool-size: 10
    pool-name: slave1
    connection-timeout: 30000
    idle-timeout: 600000
    max-lifetime: 1765000
    read-only: true
  - slave2:
    jdbc-url: jdbc:mysql://slave2-host:3306/mydb?useUnicode=true&characterEncoding=utf8&useSSL=true&allowMultiQueries=true&verifyServerCertificate=false
    username: root
    password: root
    maximum-pool-size: 10
    pool-name: slave2
    connection-timeout: 30000
    idle-timeout: 600000
    max-lifetime: 1765000
    read-only: true

这里的改动是master和slave前面加了“-”用来支持集合获取这块信息。
另外pool-name改为了master和slave1、slave2,这个很重要,后边有用到。因为获取不到前边的- master和-slave等信息,所以这里使用pool-name来确定是哪个数据源。

DBProperties

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Map;
/**
 * @author Created by pangkunkun on 2017/12/18.
 */
@Component
@ConfigurationProperties(prefix = "")
public class DBProperties {
    //一次性从配置文件中读取所有数据源的配置
    private Map<String, HikariDataSource> hikari;

    public Map<String, HikariDataSource> getHikari() {
        return hikari;
    }

    public void setHikari(Map<String, HikariDataSource> hikari) {
        this.hikari = hikari;
    }
}

这里做了重点改动,原先是针对配置文件中的字段名来定义字段的,这里我直接用一个map来获取配置文件中配置的所有数据库相关信息。通过ConfigurationProperties来获取配置文件中集合这块不属于本文的讲解,所以有需要的自己了解下。

DataSourceConfig

import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.PlatformTransactionManager;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Created by pangkunkun on 2018/8/28.
 */
@Configuration
public class DataSourceConfig {

    private static final Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);

    @Autowired
    private DBProperties properties;

    private static final String KEY_MASTER = "master";

    @Bean(name = "dataSource")
    public DataSource dataSource() {
        //按照目标数据源名称和目标数据源对象的映射存放在Map中
        Map<Object, Object> targetDataSources = new HashMap<>();
        //获取配置文件中的数据源
        Map<String, HikariDataSource> hikaris = properties.getHikari();
        Set<String> keys = hikaris.keySet();
        HikariDataSource hikariDataSource = null;
        HikariDataSource masterDB = null;
        String poolName = "";
        for (String key : keys){
            hikariDataSource = hikaris.get(key);
            poolName = hikariDataSource.getPoolName();
            targetDataSources.put(hikariDataSource.getPoolName(),hikariDataSource);
            if (poolName.equals(KEY_MASTER)){
                masterDB = hikariDataSource;
            }
        }

        //采用是想AbstractRoutingDataSource的对象包装多数据源
        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);
        //设置默认的数据源,当拿不到数据源时,使用此配置
        if (null != masterDB){
            dataSource.setDefaultTargetDataSource(masterDB);
        }else {
            logger.error("Can't find master db, project will be exit");
            System.exit(0);
        }
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager txManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

在上篇文章中这块代码是将DBProperties中的几个数据库信息一一放到map中,这里通过DBProperties中的map获取所有数据库信息放到数据源的map中,通过poolname来区分数据库的信息。并且增加了master数据库的判断,如果识别不到master数据库就会退出项目(这个功能看情况自己选择是否需要)。

最后提一点,我打算最近抽时间把这块做成一个公共组件,所有动态信息通过配置文件设置,以后就不用再动这块代码了(希望自己能搞定吧^_^)。

猜你喜欢

转载自blog.csdn.net/qq_35981283/article/details/82145486