springboot druid 读写分离
一、修改yml文件
spring:
datasource:
druid:
master:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://${MASTER_DB_HOST}:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false
username: ${MASTER_DB_USER}
password: ${MASTER_DB_PWD}
initial-size: 10
max-active: 100
min-idle: 10
slave:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://${SLAVE_DB_HOST}:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false
username: ${SLAVE_DB_USER}
password: ${SLAVE_DB_PWD}
initial-size: 10
max-active: 100
min-idle: 10
二、DynamicDataSource 动态数据源
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>();
@Override
protected Object determineCurrentLookupKey() {
Object lookupKey = contextHolder.get();
return lookupKey;
}
public static void master() {
contextHolder.set(DatabaseType.Master);
}
public static void slave() {
contextHolder.set(DatabaseType.Slave);
}
public static void clear() {
contextHolder.remove();
}
public static DatabaseType getType() {
return contextHolder.get();
}
public enum DatabaseType {
Master, Slave
}
}
三、DatabaseConfiguration配置
@Component
public class DatabaseConfiguration {
@Primary
@Bean
@ConfigurationProperties("spring.datasource.druid.master")
public DataSource masterDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.druid.slave")
public DataSource slaveDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
public DynamicDataSource dynamicDataSource(DataSource masterDataSource, @Qualifier("slaveDataSource") DataSource slaveDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>(2);
targetDataSources.put(DynamicDataSource.DatabaseType.Master, masterDataSource);
targetDataSources.put(DynamicDataSource.DatabaseType.Slave, slaveDataSource);
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources);
dataSource.setDefaultTargetDataSource(masterDataSource);
dataSource.afterPropertiesSet();
return dataSource;
}
}
四、DataSourceInterceptor拦截器配置
@Slf4j
@Aspect
@Order(Ordered.LOWEST_PRECEDENCE - 1)
@Component
public class DataSourceInterceptor {
private boolean isDebug = log.isDebugEnabled();
@Before("execution(* *..service.*.select*(..))|| execution(* *..service.*.get*(..))")
public void setReadDataSourceType() {
DynamicDataSource.slave();
if (isDebug) {
log.info("dataSource切换到:slave");
}
}
@Before("execution(* *..service.*.insert*(..)) || execution(* *..service.*.update*(..)) || execution(* *..service.*.delete*(..)) || execution(* *..service.*.add*(..)) || execution(* *..service.*.save*(..))")
public void setWriteDataSourceType() {
DynamicDataSource.master();
if (isDebug) {
log.info("dataSource切换到:master");
}
}
@AfterReturning("execution(* *..service.*.*(..))")
public void clearDataSourceType() {
DynamicDataSource.clear();
}
}