From 5a16b39164ab85a2ae56825df5be5c0cec615bab Mon Sep 17 00:00:00 2001
From: Dftre <3066417822@qq.com>
Date: Mon, 1 Jul 2024 03:49:00 +0800
Subject: [PATCH] =?UTF-8?q?1.=20=E5=85=A8=E5=B1=80=E5=BC=82=E5=B8=B8?=
=?UTF-8?q?=E6=8D=95=E8=8E=B7=E9=94=99=E8=AF=AF=E9=97=AE=E9=A2=98=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8D=202.=20=E5=A4=9A=E6=95=B0=E6=8D=AE=E6=BA=90=E5=85=81?=
=?UTF-8?q?=E8=AE=B8=E4=BB=85=E4=BF=AE=E6=94=B9=E9=85=8D=E7=BD=AE=E6=96=87?=
=?UTF-8?q?=E4=BB=B6=E5=8D=B3=E5=8F=AF=E8=BF=BD=E5=8A=A0=E6=9B=B4=E5=A4=9A?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=BA=90=EF=BC=8C=E4=B8=94=E4=B8=8Edynamic-d?=
=?UTF-8?q?atasource=E4=BD=BF=E7=94=A8=E6=96=B9=E5=BC=8F=E7=9B=B8=E4=BC=BC?=
=?UTF-8?q?=EF=BC=8C=E5=B9=B6=E8=BF=BD=E5=8A=A0=E5=AD=97=E7=AC=A6=E4=B8=B2?=
=?UTF-8?q?=E6=8C=87=E5=AE=9A=E6=95=B0=E6=8D=AE=E6=BA=90=E7=9A=84=E6=96=B9?=
=?UTF-8?q?=E5=BC=8F=203.=20=E5=A4=9A=E6=95=B0=E6=8D=AE=E6=BA=90=E5=8A=A0?=
=?UTF-8?q?=E5=88=86=E5=B8=83=E5=BC=8F=E4=BA=8B=E5=8A=A1=E6=97=B6=E4=BB=8E?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=BA=90=E6=97=A0=E6=B3=95=E8=A2=ABdruid?=
=?UTF-8?q?=E7=9B=91=E6=8E=A7=E5=88=B0=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
doc/关于多数据源与分布式事务.drawio | 149 ++++++++++++++++++
.../src/main/resources/application-druid.yml | 26 +--
.../ruoyi/common/annotation/DataSource.java | 12 +-
.../framework/aspectj/DataSourceAspect.java | 34 ++--
.../ruoyi/framework/config/DruidConfig.java | 92 +----------
.../config/DynamicDataSourceProperties.java | 134 ++++++++++++++++
.../ruoyi/framework/config/MyBatisConfig.java | 28 ----
.../config/SqlSessionFactoryConfig.java | 42 +++--
.../web/exception/GlobalExceptionHandler.java | 4 +-
9 files changed, 359 insertions(+), 162 deletions(-)
create mode 100644 doc/关于多数据源与分布式事务.drawio
create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/DynamicDataSourceProperties.java
diff --git a/doc/关于多数据源与分布式事务.drawio b/doc/关于多数据源与分布式事务.drawio
new file mode 100644
index 0000000..54ac704
--- /dev/null
+++ b/doc/关于多数据源与分布式事务.drawio
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml
index 56ce492..6c5e4ae 100644
--- a/ruoyi-admin/src/main/resources/application-druid.yml
+++ b/ruoyi-admin/src/main/resources/application-druid.yml
@@ -3,20 +3,20 @@ spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
+ dynamic:
+ primary: MASTER
+ datasource:
+ # 主库数据源
+ MASTER:
+ url: jdbc:mysql://127.0.0.1/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: 123456
+ # 从库数据源
+ # SLAVE:
+ # url: jdbc:mysql://127.0.0.1/ruoyi?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ # username: root
+ # password: 123456
druid:
- # 主库数据源
- master:
- url: jdbc:mysql://127.0.0.1/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
- username: root
- password: 123456
- # 从库数据源
- slave:
- # 从数据源开关/默认关闭
- enabled: false
- url: jdbc:mysql://127.0.0.1/ruoyi?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
- username: root
- password: 123456
-
# 初始连接数
initialSize: 5
# 最小连接池数量
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
index 79cd191..39d9d30 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
@@ -6,6 +6,7 @@ import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+
import com.ruoyi.common.enums.DataSourceType;
/**
@@ -19,10 +20,15 @@ import com.ruoyi.common.enums.DataSourceType;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
-public @interface DataSource
-{
+public @interface DataSource {
+
/**
- * 切换数据源名称
+ * 切换数据源名称 - 枚举方式
*/
public DataSourceType value() default DataSourceType.MASTER;
+
+ /**
+ * 切换数据源名称 - 字符串方式
+ */
+ public String name() default "";
}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java
index 8c2c9f4..f551e67 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java
@@ -1,6 +1,7 @@
package com.ruoyi.framework.aspectj;
import java.util.Objects;
+
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@@ -11,6 +12,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
+
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder;
@@ -23,33 +25,31 @@ import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder;
@Aspect
@Order(1)
@Component
-public class DataSourceAspect
-{
+public class DataSourceAspect {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)"
+ "|| @within(com.ruoyi.common.annotation.DataSource)")
- public void dsPointCut()
- {
+ public void dsPointCut() {
}
@Around("dsPointCut()")
- public Object around(ProceedingJoinPoint point) throws Throwable
- {
+ public Object around(ProceedingJoinPoint point) throws Throwable {
DataSource dataSource = getDataSource(point);
- if (StringUtils.isNotNull(dataSource))
- {
- DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
+ if (StringUtils.isNotNull(dataSource)) {
+ if ("".equals(dataSource.name())) {
+ DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
+ } else {
+ DynamicDataSourceContextHolder.setDataSourceType(dataSource.name());
+ }
+
}
- try
- {
+ try {
return point.proceed();
- }
- finally
- {
+ } finally {
// 销毁数据源 在执行方法之后
DynamicDataSourceContextHolder.clearDataSourceType();
}
@@ -58,12 +58,10 @@ public class DataSourceAspect
/**
* 获取需要切换的数据源
*/
- public DataSource getDataSource(ProceedingJoinPoint point)
- {
+ public DataSource getDataSource(ProceedingJoinPoint point) {
MethodSignature signature = (MethodSignature) point.getSignature();
DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
- if (Objects.nonNull(dataSource))
- {
+ if (Objects.nonNull(dataSource)) {
return dataSource;
}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java
index b8af262..41a79fd 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java
@@ -3,7 +3,6 @@ package com.ruoyi.framework.config;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
-import java.util.Properties;
import javax.sql.DataSource;
@@ -11,20 +10,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
-import org.springframework.core.env.Environment;
import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
-import com.atomikos.jdbc.AtomikosDataSourceBean;
-import com.ruoyi.common.enums.DataSourceType;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.framework.config.properties.DruidProperties;
import com.ruoyi.framework.datasource.DynamicDataSource;
import jakarta.servlet.Filter;
@@ -41,88 +33,20 @@ import jakarta.servlet.ServletResponse;
@Configuration
public class DruidConfig {
- Logger logger = LoggerFactory.getLogger(DruidConfig.class);
-
- public static final String MASTER = DataSourceType.MASTER.name();
-
- public static final String SLAVE = DataSourceType.SLAVE.name();
-
@Autowired
- private DruidProperties druidProperties;
+ DynamicDataSourceProperties dataSourceProperties;
- @Bean
- @Primary
- @DependsOn({ "transactionManager" })
- @ConfigurationProperties("spring.datasource.druid.master")
- public DataSource masterDataSource(Environment env) {
- String prefix = "spring.datasource.druid.master.";
- return getDataSource(env, prefix, MASTER);
- }
-
- @Bean
- @ConfigurationProperties("spring.datasource.druid.slave")
- @DependsOn({ "transactionManager" })
- @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
- public DataSource slaveDataSource(Environment env) {
- String prefix = "spring.datasource.druid.slave.";
- return getDataSource(env, prefix, SLAVE);
- }
-
- protected DataSource getDataSource(Environment env, String prefix, String dataSourceName) {
- Properties prop = build(env, prefix);
- AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
- ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
- // 添加连接池限制
- ds.setMaxPoolSize(50);
- ds.setMinPoolSize(5);
- ds.setBorrowConnectionTimeout(60);
- ds.setUniqueResourceName(dataSourceName);
- ds.setXaProperties(prop);
- return ds;
- }
-
- protected Properties build(Environment env, String prefix) {
- Properties prop = new Properties();
- prop.put("url", env.getProperty(prefix + "url"));
- prop.put("username", env.getProperty(prefix + "username"));
- prop.put("password", env.getProperty(prefix + "password"));
- prop.put("initialSize", druidProperties.getInitialSize());
- prop.put("minIdle", druidProperties.getMinIdle());
- prop.put("maxActive", druidProperties.getMaxActive());
- prop.put("maxWait", druidProperties.getMaxWait());
- prop.put("timeBetweenEvictionRunsMillis", druidProperties.getTimeBetweenEvictionRunsMillis());
- prop.put("minEvictableIdleTimeMillis", druidProperties.getMinEvictableIdleTimeMillis());
- prop.put("maxEvictableIdleTimeMillis", druidProperties.getMaxEvictableIdleTimeMillis());
- prop.put("validationQuery", druidProperties.getValidationQuery());
- prop.put("testWhileIdle", druidProperties.isTestWhileIdle());
- prop.put("testOnBorrow", druidProperties.isTestOnBorrow());
- prop.put("testOnReturn", druidProperties.isTestOnReturn());
- return prop;
- }
+ Logger logger = LoggerFactory.getLogger(DruidConfig.class);
@Bean(name = "dynamicDataSource")
@Primary
- public DynamicDataSource dataSource(DataSource masterDataSource) {
- Map