From 39e79bb88c0b6b1cb00fa9694c0543e7da9cc619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=98=E5=9F=83=E8=90=BD=E5=AE=9A?= Date: Tue, 29 Nov 2022 05:00:27 +0000 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E4=BB=8E=E6=95=B0=E6=8D=AE=E6=BA=90=E7=9A=84=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E5=85=B6=E4=BB=96=E6=9C=8D=E5=8A=A1=E4=BC=9A?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E5=90=8E=E7=BB=AD=E6=95=B0=E6=8D=AE=E6=BA=90?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=BC=82=E5=B8=B8=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=A4=9A=E6=95=B0=E6=8D=AE=E9=9D=9EMaster=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=BA=90=E4=BD=BF=E7=94=A8=E4=B8=AD=E8=B0=83=E7=94=A8=E4=BB=BB?= =?UTF-8?q?=E4=BD=95=E5=85=B6=E4=BB=96=E6=95=B0=E6=8D=AE=E6=BA=90=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E5=90=8E=E7=BB=ADsql=E6=89=A7=E8=A1=8C=E5=9C=A8Master?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=BA=90=E7=9A=84bug=20```java=20#ServiceImp?= =?UTF-8?q?l1.java=20@Service=20@DataSource("SLAVE1")=20public=20class=20S?= =?UTF-8?q?erviceImpl1{=20=20=20=20=20public=20void=20doSomething1(){=20?= =?UTF-8?q?=20=20=20=20}=20}=20#ServiceImpl2.java=20@Service=20@DataSource?= =?UTF-8?q?("SLAVE2")=20public=20class=20ServiceImpl2{=20=20=20=20=20@Auto?= =?UTF-8?q?wired=20=20=20=20=20private=20ServiceImpl1=20service1;=20=20=20?= =?UTF-8?q?=20=20public=20void=20doSomething2(){=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20//=20SLAVE2=20=20=20=20=20=20=20=20=20log.debug("=E5=BD=93?= =?UTF-8?q?=E5=89=8D=E6=95=B0=E6=8D=AE=E6=BA=90:{}",DynamicDataSourceConte?= =?UTF-8?q?xtHolder.getDataSourceType());=20=20=20=20=20=20=20=20//?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=BA=90=E6=B3=A8=E8=A7=A3=E7=94=9F=E6=95=88?= =?UTF-8?q?=20=E5=B9=B6=E5=9C=A8=E6=96=B9=E6=B3=95=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E5=90=8E=E8=B0=83=E7=94=A8=20clearDataSourceType=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20service1.doSomething1();=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20//=E4=BF=AE=E6=94=B9=E5=89=8D=20=20=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E4=BA=86=20clearDataSourceType=E4=BC=9A=E6=B8=85=E7=90=86?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=BA=90=E7=9A=84=E6=A0=87=E8=AE=B0=20?= =?UTF-8?q?=E6=AD=A4=E5=A4=84=E4=BC=9A=E6=89=93=E5=8D=B0=20MASTER(?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC)=20=20=E5=AF=BC=E8=87=B4=E6=9C=AC?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=90=8E=E7=BB=AD=E4=BD=BF=E7=94=A8MASTER?= =?UTF-8?q?=E6=89=A7=E8=A1=8Csql=20=E8=80=8C=E4=B8=8D=E6=98=AF=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3=E4=B8=8A=E7=9A=84=20SLAVE2=20=E4=B8=8D=E7=AC=A6?= =?UTF-8?q?=E5=90=88=E9=A2=84=E6=9C=9F=20=20=20=20=20=20=20=20=20//?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=89=8D=20=20=E8=B0=83=E7=94=A8=E4=BA=86=20?= =?UTF-8?q?clearDataSourceType=E4=BB=85=E4=BC=9A=E6=B8=85=E7=90=86?= =?UTF-8?q?=E4=B8=80=E5=B1=82=E6=95=B0=E6=8D=AE=E6=BA=90=E7=BB=93=E6=9E=84?= =?UTF-8?q?=20=E6=AD=A4=E5=A4=84=E6=89=93=E5=8D=B0=E7=9A=84=E4=BE=9D?= =?UTF-8?q?=E7=84=B6=E6=98=AF=20SLAVE2=20=E5=90=8E=E7=BB=AD=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20SLAVE2=E6=95=B0=E6=8D=AE=E6=BA=90=E6=89=A7=E8=A1=8C?= =?UTF-8?q?sql=20=20=20=20=20=20=20=20=20log.debug("=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=BA=90:{}",DynamicDataSourceContextHolder.?= =?UTF-8?q?getDataSourceType());=20=20=20=20=20}=20}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` Signed-off-by: 尘埃落定 --- .../DynamicDataSourceContextHolder.java | 53 +++++++++++++++++-- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/datasource/DynamicDataSourceContextHolder.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/datasource/DynamicDataSourceContextHolder.java index 6bc9e6178..869ba98c1 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/config/datasource/DynamicDataSourceContextHolder.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/datasource/DynamicDataSourceContextHolder.java @@ -3,6 +3,8 @@ package com.ruoyi.common.config.datasource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Optional; + /** * 数据源切换处理 * @@ -16,15 +18,17 @@ public class DynamicDataSourceContextHolder * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本, * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 */ - private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); + private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); /** * 设置数据源的变量 */ public static void setDataSourceType(String dsType) { - log.info("切换到{}数据源", dsType); - CONTEXT_HOLDER.set(dsType); + DataSourceTypeStruct dataSourceTypeStruct = Optional.ofNullable(CONTEXT_HOLDER.get()).orElse(new DataSourceTypeStruct(DataSourceType.MASTER.name()));//最顶层默认为 MASTER 数据源 + dataSourceTypeStruct.setDsType(dsType); + log.info("切换到{}数据源,当前:{}", dsType,dataSourceTypeStruct); + CONTEXT_HOLDER.set(dataSourceTypeStruct); } /** @@ -32,7 +36,8 @@ public class DynamicDataSourceContextHolder */ public static String getDataSourceType() { - return CONTEXT_HOLDER.get(); + DataSourceTypeStruct dataSourceTypeStruct = Optional.ofNullable(CONTEXT_HOLDER.get()).orElse(new DataSourceTypeStruct(DataSourceType.MASTER.name()));//最顶层默认为 MASTER 数据源 + return dataSourceTypeStruct.getDsType(); } /** @@ -40,6 +45,44 @@ public class DynamicDataSourceContextHolder */ public static void clearDataSourceType() { - CONTEXT_HOLDER.remove(); + DataSourceTypeStruct dataSourceTypeStruct = Optional.ofNullable(CONTEXT_HOLDER.get()).orElse(new DataSourceTypeStruct(DataSourceType.MASTER.name())); + dataSourceTypeStruct.clearDsType(); + log.info("清理一层数据源,当前:{}", dataSourceTypeStruct); + } + /** + * 创建层级结构 保存数据源 + */ + static class DataSourceTypeStruct{ + private final String dsType; + private DataSourceTypeStruct next; + protected DataSourceTypeStruct(String dsType){ + this.dsType = dsType; + } + public String getDsType(){//获得最底层DataSourceTypeStruct的dsType + if(null!=next){ + return next.getDsType(); + } + return dsType; + } + public void setDsType(String dsType){//设置最底层DataSourceTypeStruct的dsType + if(null!=next){ + next.setDsType(dsType); + return; + } + next = new DataSourceTypeStruct(dsType); + } + public void clearDsType(){//清理最底层的DataSourceTypeStruct 层级-1 + if(null!=next){ + if(null==next.next){ + next=null; + }else{ + next.clearDsType(); + } + } + } + @Override + public String toString(){ + return dsType+(null==next?"":("->"+next)); + } } }