【在使用前需要搭建好一个springboot+plus的项目,之后全程复制即可】
yml
server:
port: 9001
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
master:
url: jdbc:mysql://127.0.0.1:3306/seata_order?useUnicode=true&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false
username: root
password: root
slave:
url: jdbc:mysql://127.0.0.1:3306/lianxi?useUnicode=true&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false
username: root
password: root
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username:
login-password:
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
POM文件
<!-- 添加父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.projectlombok.version>1.18.20</org.projectlombok.version>
</properties>
<dependencies>
<!-- 热部署配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- 加入web开发的支持 集成servlet 和tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 加入mysql的驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version> 8.0.27</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<!--控制日志信息输送的目的地是控制台、文件、GUI组件-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<scope>provided</scope> <!-- 设置为 provided,主要是 ErrorCodeProperties 使用到 -->
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<scope>provided</scope> <!-- 设置为 provided,只有工具类需要使用到 -->
</dependency>
<!-- yml设置MySQL数据源的type为:com.alibaba.druid.pool.DruidDataSource的时候需要添加这个依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
<scope>provided</scope>
<!--<optional>true</optional>-->
</dependency>
<!--类转换配置 convert -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<!--糊涂工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.9</version>
</dependency>
<!-- alibaba easyexcel依赖 开始-->
<!--读取Excel-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.jeecg</groupId>
<artifactId>easypoi-base</artifactId>
<version>2.3.1</version>
</dependency>
<!-- alibaba easyexcel依赖 结束-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
枚举
@Getter
public enum DataSourceEnum {
MASTER("master","MASTER"),SLAVE("slave","SLAVE");
private final String name;
private final String code;
DataSourceEnum(String name, String code) {
this.name = name;
this.code = code;
}
}
数据源注解
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MasterSlave {
DataSourceEnum value();
}
ThreadLocal工具类
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<String>();
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
/**
* 清除数据源
*/
public static void clearDataSource() {
log.info("删除数据源:{}", CONTEXT_HOLDER.get());
CONTEXT_HOLDER.remove();
}
/**
* 设置数据源
*
* @param dsType master/slaver
*/
public static void setDataSource(String dsType) {
log.info("切换到:{}数据源", dsType);
CONTEXT_HOLDER.set(dsType);
}
/**
* 获取数据源
*/
public static String getDataSource() {
return CONTEXT_HOLDER.get();
}
}
数据源Bean
@Configuration
@Slf4j
public class DynamicDataSourceConfig {
@Bean
@Primary
public DynamicDataSource dataSource() {
Map<Object, Object> targetDataSources = new HashMap<>(5);
targetDataSources.put(DataSourceEnum.MASTER.getCode(), this.masterDataSource());
targetDataSources.put(DataSourceEnum.SLAVE.getCode(), this.slaveDataSource());
return new DynamicDataSource(this.masterDataSource(), targetDataSources);
}
@Bean(name = "masterDataSource")
@ConfigurationProperties("spring.datasource.druid.master")
public DataSource masterDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "slaveDataSource")
@ConfigurationProperties("spring.datasource.druid.slave")
public DataSource slaveDataSource() {
return DruidDataSourceBuilder.create().build();
}
}
AOP切面
@Component
@Aspect
@Slf4j
public class DynamicDataSourceAspect {
@Around("@annotation(masterSlave)")
public Object around(ProceedingJoinPoint joinPoint, MasterSlave masterSlave) throws Throwable {
MasterSlave dataSource = this.getDataSource(joinPoint);
if (!Objects.isNull(dataSource)) {
DynamicDataSource.setDataSource(dataSource.value().getCode());
}
Object var3;
try {
var3 = joinPoint.proceed();
} finally {
DynamicDataSource.clearDataSource();
}
return var3;
}
public MasterSlave getDataSource(JoinPoint point) {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
return method.getAnnotation(MasterSlave.class);
}
}
启动类
@Slf4j
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@Import({DynamicDataSourceConfig.class})
@MapperScan("com.boot.mapper")
public class ZStartBoot {
public static void main(String[] args) {
SpringApplication.run(ZStartBoot.class, args);
log.info("项目服务器启动了");
}
}
使用
@PostMapping("/MASTER")
@MasterSlave(value = DataSourceEnum.MASTER)
public User MASTER(@RequestBody @Valid User u) {
return userService.getById(u.getId());
}
@PostMapping("/SLAVE")
@MasterSlave(value = DataSourceEnum.SLAVE)
public User SLAVE(@RequestBody @Valid User u) {
return userService.getById(u.getId());
}