版权声明:本文为博主原创文章,未经博主允许不得转载。 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数据库就会退出项目(这个功能看情况自己选择是否需要)。
最后提一点,我打算最近抽时间把这块做成一个公共组件,所有动态信息通过配置文件设置,以后就不用再动这块代码了(希望自己能搞定吧^_^)。