前面配置了mysql数据库的主从复制模式,在数据库上实现了master-slave配置,通过这种方式可以实现一主一从,或者一主多从,从而提升系统的高可用。
这是数据库层面的实现。在数据库实现了主从模式之后,我们需要考率的问题就是,在我们的应用代码中,如何将不同的数据库操作按需要分配到不同的数据库去执行。
1.需要的依赖
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'mysql:mysql-connector-java:8.0.25'
implementation 'com.zaxxer:HikariCP:4.0.3'
2.yml配置
在application.yml文件中,数据源相关配置如下:
# 自定义的动态数据源配置
custom:
datasource:
- key: master
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.161.114:3306/gts?useSSL=false&autoReconnect=true&characterEncoding=UTF-8&serverTimezone=UTC
username: gts
password: mysql
default: true
- key: slave1
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.161.115:3306/gts?useSSL=false&autoReconnect=true&characterEncoding=UTF-8&serverTimezone=UTC
username: gts
password: mysql
- key: slave2
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.161.114:3306/gts?useSSL=false&autoReconnect=true&characterEncoding=UTF-8&serverTimezone=UTC
username: gts
password: mysql
在custom.datasource,定义了一组数据源配置。master配置到主库,slave1喝slave2分贝表示多组从库。本文用主库来表示从库。
3.动态数据源配置
数据源定义:
package com.dhb.gts.javacourse.week7.dynamic;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDataSourceType();
}
}
动态数据源切面配置:
package com.dhb.gts.javacourse.week7.dynamic;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Order(-1)// 保证该AOP在@Transactional之前执行
@Component
@Slf4j
public class DynamicDataSourceAspect {
@Before("@annotation(ds)")
public void changeDataSource(JoinPoint point, TargetDataSource ds) throws Throwable {
String dsId = ds.name();
if (!DynamicDataSourceContextHolder.containsDataSource(dsId)) {
log.error("数据源[{}]不存在,使用默认数据源 > {}", ds.name(), poi