SpringBoot多数据源(主从数据源)配置
前⾔
学习springboot配置多数据源,先回顾⼀下springboot配置单数据源的⽅式
主从数据源搭建
项⽬依赖
本次记录多数据源配置主要是通过druid + mybatis plus + aop的形式实现的,mybatis plus是⼀个很⽅便的数据库操作框架,⾃⼰也有实现多数据源的jar包,这⾥没有使⽤她封装的⽅法,主要是学习所以是⾃⾏实现了⼀遍简单的多数据源配置和动态切换数据源。
<!-- mybatis-plus多数据源配置jar -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
使⽤到的依赖
<dependencies>
<!-- druid数据连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- mybatis plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- spring-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- springboot配置依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
springboot aop<optional>true</optional>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
Yml⽂件配置数据源
这⾥可以看到数据源配置属性路径并⾮spring.datasource, 这⾥主要是想通过学习spring-boot配置⽂件⾃动装配, 来获取配置并初始化数据源。
# 主从数据源配置
datasource:
dynamic:
master:
driverClassName: sql.cj.jdbc.Driver
url: jdbc:mysql://192.168.92.10:3306/utmost_01?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&se rverTimezone=GMT%2B8
userName: root
password: root
slave:
enabled:true # 是否启⽤从数据源
driverClassName: sql.cj.jdbc.Driver
url: jdbc:mysql://192.168.92.10:3306/utmost_02?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&se rverTimezone=GMT%2B8
userName: root
password: root
@Getter
@Setter
@ConfigurationProperties(prefix = UtmostDataSourceProperties.PREFIX)
public class UtmostDataSourceProperties {
/**
* 配置前缀
*/
public static final String PREFIX ="utmost.datasource.dynamic";
/**
* master数据源配置前缀
*/
public static final String MASTER_PREFIX ="utmost.datasource.dynamic.master";
/**
* slave数据源配置前缀
*/
public static final String SLAVE_PREFIX ="utmost.datasource.dynamic.slave";
/**
* 设置默认数据库, 默认master
*/
public String primary ="master";
/**
* 设置启⽤数据源, 默认true
*/
public boolean enabled =true;
/**
* 主数据源
*/
public SingleDataSourceProperty master;
/
**
* 从数据源
*/
public SingleDataSourceProperty slave;
}
@Accessors(chain =true)
public class SingleDataSourceProperty {
/**
* JDBC driver
*/
private String driverClassName;
/
**
* JDBC 数据库地址
*/
private String url;
/**
* JDBC ⽤户名
*/
private String userName;
/**
* JDBC ⽤户密码
*/
private String password;
}
怎么通过UtmostDataSourceProperties类来获取属性, 主要通过@ConfigurationProperties注解实现, 前⾯依赖中引⼊了spring-boot-configuration-processor依赖, 在使⽤yml配置数据源时就会出现⼀定的提⽰作⽤。这是因为在打包编译的时候会⽣成⼀个spring-configuration-metadata.json⽂件,这⾥就不赘述了,先了解到这是springboot帮助我们⽣成的作⽤于提⽰的⽂件就可以了。
mybatis-plus配置
# mybatis-plus 配置
mybatis-plus:
configuration:
# 开启驼峰
map-underscore-to-camel-case:true
# 关闭⼀级缓存
local-cache-scope: statement
# 关闭⼆级缓存
cache-enabled:false
# sql xml⽂件映射路径
mapper-locations: classpath*:/mapper/*.xml
# MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名
type-aliases-package: ity
数据源装配
数据源配置类
@Configuration
@AllArgsConstructor
@EnableConfigurationProperties(UtmostDataSourceProperties.class)
@ConditionalOnProperty(prefix = UtmostDataSourceProperties.PREFIX, name ="enabled", havingValue ="true", matchIfMissing =true) public class UtmostDataSourceAutoConfiguration {
private final UtmostDataSourceProperties utmostDataSourceProperties;
/**
* 主数据源(这⾥配置写的繁琐⼀点, 可根据个⼈喜好进⾏简化.)
*
* @return DataSource
*/
@Bean(name ="masterDataSource")
@ConfigurationProperties(UtmostDataSourceProperties.MASTER_PREFIX)
public DataSource masterDataSource(){
SingleDataSourceProperty master = utmostDataSourceProperties.master;
DruidDataSource druidDataSource =new DruidDataSource();
druidDataSource.setName(DataSourceConstants.MASTER);
druidDataSource.DriverClassName());
druidDataSource.Url());
druidDataSource.UserName());
druidDataSource.Password());
return druidDataSource;
}
/**
* 从数据源(这⾥配置写的繁琐⼀点, 可根据个⼈喜好进⾏简化.)
*
* @return DataSource
*/
@Bean(name ="slaveDataSource")
@ConfigurationProperties(UtmostDataSourceProperties.SLAVE_PREFIX)
@ConditionalOnProperty(prefix = UtmostDataSourceProperties.SLAVE_PREFIX, name ="enabled", havingValue ="true")
public DataSource slaveDataSource(){
SingleDataSourceProperty slave = utmostDataSourceProperties.slave;
DruidDataSource druidDataSource =new DruidDataSource();
druidDataSource.setName(DataSourceConstants.SLAVE);
druidDataSource.DriverClassName());
druidDataSource.Url());
druidDataSource.UserName());
druidDataSource.Password());
return druidDataSource;
}
/**
* 动态数据源
*
* @return DynamicDataSource
*/
@Bean
@Primary
public DynamicDataSource dynamicDataSource(){
Map<Object, Object> targetMap =new HashMap<>(2);
targetMap.put(DataSourceConstants.MASTER,masterDataSource());
targetMap.put(DataSourceConstants.SLAVE,slaveDataSource());
DynamicDataSource dynamicDataSource =new DynamicDataSource(masterDataSource(), targetMap);
log.info("动态数据源装配完成...");
return dynamicDataSource;
}
}
动态数据源实现类
通过继承重写AbstractRoutingDataSource 数据源路由来实现数据源动态切换的功能.
public class DynamicDataSource extends AbstractRoutingDataSource {
/**
* 使⽤线程切换数据源
*/
private static ThreadLocal<String> contextHandler =new ThreadLocal<>();
/**
* 数据源key集合
*/
private static List<Object> dataSourceKeys =new ArrayList<>();
/**
* 配置数据源
*
* @param defaultDataSource 主数据源
* @param targetDataSourceMap 其他数据源集合
*/
public DynamicDataSource(DataSource defaultDataSource, Map<Object, Object> targetDataSourceMap){ super.setDefaultTargetDataSource(defaultDataSource);
super.setTargetDataSources(targetDataSourceMap);
super.afterPropertiesSet();
// 初始化所有数据源的key
addAllDataSourceKeys(targetDataSourceMap.keySet());
}
public static void setDataSourceKeys(String key){
contextHandler.set(key);
}
public static ThreadLocal<String>getDataSourceKeys(){
return contextHandler;
}
public static void removeDataSourceKeys(){
}
public static boolean containsDataSourceKeys(String key){
ains(key);
}
public static boolean addAllDataSourceKeys(Collection<?extends Object> keys){
return dataSourceKeys.addAll(keys);
}
@Override
protected Object determineCurrentLookupKey(){
();
}
}
数据源切换注解
/**
* 注解命名主要是为了好记所以直接使⽤了DataSource, 在使⽤时会发现有很
* 多类都是以DataSource命名, 使⽤时需要注意.
* @author yanzy
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String value()default"";
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论