网上大多读写分离实例,都是需要手动侵入代码修改数据源,本博客主要实现,如何对现有系统,不侵入原有代码,进行读写分离配置。
Mybatis-Plus自带动态数据源配置,但是也需要对手动配置,需要的可以参考官网Mybstis-Plus官网
1、引入依赖
依赖较多,主要还有MybatisPlus单数据源配置的依赖,作者就全部贴上来了。
<!-- mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
2、配置数据源
################DataSource###############
# Druid
#spring.datasource.master
spring.datasource.master.url=jdbc:mysql://127.0.0.1:7001/wj?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.master.username=test
spring.datasource.master.password=123456
#spring.datasource.slave
spring.datasource.slave.url=jdbc:mysql://127.0.0.1:7002/wj?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.slave.username=test
spring.datasource.slave.password=123456
#driverClass
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
# 下面为连接池的补充设置,应用到上面所有数据源中
# 初始化连接数量
spring.datasource.initial-size=5
# 最小连接数量
spring.datasource.min-idle=5
# 最大同时连接数量
spring.datasource.max-active=20
# 配置获取连接等待超时的时间,单位毫秒ms
spring.datasource.max-wait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒ms
spring.datasource.time-between-eviction-runs-millis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.min-evictable-idle-time-millis=300000
# SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.如果指定,则查询必须是一个SQL SELECT并且必须返回至少一行记录
# from dual:dual是一个虚拟的表,供测试使用
spring.datasource.validation-query=SELECT 1 FROM DUAL
# 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除.
# 注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
spring.datasource.test-while-idle=true
# 指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个.
# 注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
spring.datasource.test-on-borrow=false
# 指明是否在归还到池中前进行检验
# 注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
spring.datasource.test-on-return=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.pool-prepared-statements=true
spring.datasource.max-pool-prepared-statement-per-connection-size=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
#spring.datasource.druid.filter.commons-log.connection-logger-name=stat,wall,log4j
#spring.datasource.druid.filter.stat.log-slow-sql=true
#spring.datasource.druid.filter.stat.slow-sql-millis=2000
spring.datasource.filters=stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
# 合并多个DruidDataSource的监控数据
spring.datasource.use-global-data-source-stat=true
# 配置DruidStatFilter
spring.datasource.web-stat-filter.enabled=true
spring.datasource.web-stat-filter.url-pattern=/*
spring.datasource.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
# 配置DruidStatViewServlet
spring.datasource.stat-view-servlet.url-pattern=/druid/*
# IP白名单(没有配置或者为空,则允许所有访问)
spring.datasource.stat-view-servlet.allow=127.0.0.1
# IP黑名单 (存在共同时,deny优先于allow)
spring.datasource.stat-view-servlet.deny=
# 禁用HTML页面上的“Reset All”功能
spring.datasource.stat-view-servlet.reset-enable=false
# 登录名
spring.datasource.stat-view-servlet.login-username=admin
# 密码
spring.datasource.stat-view-servlet.login-password=123456
3、读写分离配置
DynamicDataSource.java
package com.imooc.wjtest.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @program: wjtest
* @description:
* @author: ZhangKai
* @create: 2019-11-11 10:32
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDbType();
}
}
DynamicDataSourceHolder.java
package com.imooc.wjtest.config;
import lombok.extern.slf4j.Slf4j;
/**
* @program: wjtest
* @description:
* @author: ZhangKai
* @create: 2019-11-11 10:41
**/
@Slf4j
public class DynamicDataSourceHolder {
private static ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static final String DB_MASTER = "master";
public static final String DB_SLAVE = "slave";
public static String getDbType() {
String db = contextHolder.get();
if (db == null) {
db = DB_MASTER;
}
return db;
}
/**
* 设置线程的dbType
*
* @param str
*/
public static void setDbType(String str) {
log.debug("所使用的数据源为:" + str);
contextHolder.set(str);
}
/**
* 清理连接类型
*/
public static void clearDBType() {
contextHolder.remove();
}
}
DynamicDataSourceInterceptor.java
package com.imooc.wjtest.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.