Parcourir la source

version 2.2.0-snapshot

rayson il y a 11 mois
Parent
commit
89facad460
28 fichiers modifiés avec 173 ajouts et 1070 suppressions
  1. 42 70
      citu-dependencies/pom.xml
  2. 8 6
      citu-framework/citu-spring-boot-starter-biz-data-permission/src/main/java/com/citu/framework/datapermission/config/CituDataPermissionAutoConfiguration.java
  3. 0 641
      citu-framework/citu-spring-boot-starter-biz-data-permission/src/main/java/com/citu/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java
  4. 57 0
      citu-framework/citu-spring-boot-starter-biz-data-permission/src/main/java/com/citu/framework/datapermission/core/db/DataPermissionRuleHandler.java
  5. 0 190
      citu-framework/citu-spring-boot-starter-biz-data-permission/src/test/java/com/citu/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest.java
  6. 20 13
      citu-framework/citu-spring-boot-starter-biz-data-permission/src/test/java/com/citu/framework/datapermission/core/db/DataPermissionRuleHandlerTest.java
  7. 0 31
      citu-framework/citu-spring-boot-starter-mybatis/src/main/java/com/citu/framework/mybatis/core/type/JsonLongSetTypeHandler.java
  8. 2 2
      citu-module-bpm/citu-module-bpm-biz/src/main/java/com/citu/module/bpm/dal/dataobject/definition/BpmUserGroupDO.java
  9. 12 2
      citu-module-infra/citu-module-infra-biz/src/main/java/com/citu/module/infra/dal/dataobject/file/FileConfigDO.java
  10. 0 1
      citu-module-mall/citu-module-product-biz/src/main/java/com/citu/module/product/controller/admin/property/ProductPropertyController.java
  11. 0 1
      citu-module-mall/citu-module-product-biz/src/main/java/com/citu/module/product/controller/admin/property/ProductPropertyValueController.java
  12. 1 1
      citu-module-mall/citu-module-product-biz/src/main/java/com/citu/module/product/dal/dataobject/comment/ProductCommentDO.java
  13. 2 16
      citu-module-mall/citu-module-product-biz/src/main/java/com/citu/module/product/dal/dataobject/sku/ProductSkuDO.java
  14. 2 16
      citu-module-mall/citu-module-promotion-biz/src/main/java/com/citu/module/promotion/dal/dataobject/reward/RewardActivityDO.java
  15. 1 1
      citu-module-mall/citu-module-trade-biz/src/main/java/com/citu/module/trade/dal/dataobject/aftersale/AfterSaleDO.java
  16. 2 16
      citu-module-mall/citu-module-trade-biz/src/main/java/com/citu/module/trade/dal/dataobject/order/TradeOrderItemDO.java
  17. 2 1
      citu-module-mp/citu-module-mp-biz/src/main/java/com/citu/module/mp/controller/admin/message/vo/message/MpMessageRespVO.java
  18. 2 1
      citu-module-mp/citu-module-mp-biz/src/main/java/com/citu/module/mp/dal/dataobject/menu/MpMenuDO.java
  19. 2 1
      citu-module-mp/citu-module-mp-biz/src/main/java/com/citu/module/mp/dal/dataobject/message/MpAutoReplyDO.java
  20. 2 15
      citu-module-mp/citu-module-mp-biz/src/main/java/com/citu/module/mp/dal/dataobject/message/MpMessageDO.java
  21. 2 2
      citu-module-report/citu-module-report-biz/pom.xml
  22. 2 2
      citu-module-system/citu-module-system-biz/src/main/java/com/citu/module/system/dal/dataobject/permission/RoleDO.java
  23. 2 2
      citu-module-system/citu-module-system-biz/src/main/java/com/citu/module/system/dal/dataobject/tenant/TenantPackageDO.java
  24. 2 2
      citu-module-system/citu-module-system-biz/src/main/java/com/citu/module/system/dal/dataobject/user/AdminUserDO.java
  25. 1 1
      citu-module-system/citu-module-system-biz/src/main/java/com/citu/module/system/framework/sms/core/client/impl/TencentSmsClient.java
  26. 3 14
      citu-module-system/citu-module-system-biz/src/test/java/com/citu/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java
  27. 2 20
      citu-module-system/citu-module-system-biz/src/test/java/com/citu/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java
  28. 2 2
      pom.xml

+ 42 - 70
citu-dependencies/pom.xml

@@ -14,32 +14,32 @@
     <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
 
     <properties>
-        <revision>2.1.0-snapshot</revision>
-        <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
+        <revision>2.2.0-snapshot</revision>
+        <flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
         <!-- 统一依赖管理 -->
         <spring.boot.version>2.7.18</spring.boot.version>
-        <spring.cloud.version>2021.0.5</spring.cloud.version>
-        <spring.cloud.alibaba.version>2021.0.4.0</spring.cloud.alibaba.version>
+        <spring.cloud.version>2021.0.9</spring.cloud.version>
+        <spring.cloud.alibaba.version>2021.0.6.1</spring.cloud.alibaba.version>
         <!-- Web 相关 -->
         <servlet.versoin>2.5</servlet.versoin>
-        <springdoc.version>1.6.15</springdoc.version>
-        <knife4j.version>4.3.0</knife4j.version>
+        <springdoc.version>1.7.0</springdoc.version>
+        <knife4j.version>4.5.0</knife4j.version>
         <!-- DB 相关 -->
-        <druid.version>1.2.21</druid.version>
-        <mybatis-plus.version>3.5.5</mybatis-plus.version>
-        <mybatis-plus-generator.version>3.5.5</mybatis-plus-generator.version>
-        <dynamic-datasource.version>4.3.0</dynamic-datasource.version>
-        <mybatis-plus-join.version>1.4.10</mybatis-plus-join.version>
-        <easy-trans.version>2.2.11</easy-trans.version>
-        <redisson.version>3.18.0</redisson.version> <!-- Spring Boot 2.X 最多使用 3.18.0 版本,否则会报 Tuple NoClassDefFoundError -->
+        <druid.version>1.2.23</druid.version>
+        <mybatis.version>3.5.16</mybatis.version>
+        <mybatis-plus.version>3.5.7</mybatis-plus.version>
+        <mybatis-plus-generator.version>3.5.7</mybatis-plus-generator.version>
+        <dynamic-datasource.version>4.3.1</dynamic-datasource.version>
+        <mybatis-plus-join.version>1.4.13</mybatis-plus-join.version>
+        <easy-trans.version>3.0.5</easy-trans.version>
+        <redisson.version>3.32.0</redisson.version>
         <dm8.jdbc.version>8.1.3.62</dm8.jdbc.version>
         <!-- 消息队列 -->
-        <rocketmq-spring.version>2.2.3</rocketmq-spring.version>
+        <rocketmq-spring.version>2.3.0</rocketmq-spring.version>
         <!-- RPC 相关 -->
         <!-- Config 配置中心相关 -->
-        <apollo.version>1.9.2</apollo.version>
         <!-- Job 定时任务相关 -->
-        <xxl-job.version>2.3.1</xxl-job.version>
+        <xxl-job.version>2.4.0</xxl-job.version>
         <!-- 服务保障相关 -->
         <lock4j.version>2.2.7</lock4j.version>
         <!-- 监控相关 -->
@@ -48,26 +48,25 @@
         <opentracing.version>0.33.0</opentracing.version>
         <!-- Test 测试相关 -->
         <podam.version>7.2.11.RELEASE</podam.version> <!-- Spring Boot 2.X 最多使用 7.2.11 版本 -->
-        <jedis-mock.version>1.0.13</jedis-mock.version>
+        <jedis-mock.version>1.1.2</jedis-mock.version>
         <mockito-inline.version>4.11.0</mockito-inline.version>
         <!-- Bpm 工作流相关 -->
         <flowable.version>6.8.0</flowable.version>
         <!-- 工具类相关 -->
         <captcha-plus.version>1.0.8</captcha-plus.version>
-        <jsoup.version>1.17.2</jsoup.version>
-        <lombok.version>1.18.30</lombok.version>
+        <jsoup.version>1.18.1</jsoup.version>
+        <lombok.version>1.18.34</lombok.version>
         <mapstruct.version>1.5.5.Final</mapstruct.version>
-        <hutool.version>5.8.25</hutool.version>
-        <easyexcel.verion>3.3.3</easyexcel.verion>
+        <hutool.version>5.8.29</hutool.version>
+        <easyexcel.verion>3.3.4</easyexcel.verion>
         <velocity.version>2.3</velocity.version>
         <screw.version>1.0.5</screw.version>
         <fastjson.version>1.2.83</fastjson.version>
-        <guava.version>33.0.0-jre</guava.version>
-        <guice.version>5.1.0</guice.version>
+        <guava.version>33.2.1-jre</guava.version>
         <transmittable-thread-local.version>2.14.5</transmittable-thread-local.version>
-        <commons-net.version>3.10.0</commons-net.version>
+        <commons-net.version>3.11.1</commons-net.version>
         <jsch.version>0.1.55</jsch.version>
-        <tika-core.version>2.9.1</tika-core.version>
+        <tika-core.version>2.9.2</tika-core.version>
         <ip2region.version>2.7.0</ip2region.version>
         <bizlog-sdk.version>3.0.6</bizlog-sdk.version>
         <reflections.version>0.10.2</reflections.version>
@@ -77,7 +76,7 @@
         <commons-io.version>2.15.1</commons-io.version>
         <minio.version>8.5.7</minio.version>
         <justauth.version>1.0.8</justauth.version>
-        <jimureport.version>1.6.6</jimureport.version>
+        <jimureport.version>1.7.8</jimureport.version>
         <xercesImpl.version>2.12.2</xercesImpl.version>
         <weixin-java.version>4.6.0</weixin-java.version>
         <!-- 规则引擎 -->
@@ -203,6 +202,11 @@
                 <artifactId>druid-spring-boot-starter</artifactId>
                 <version>${druid.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.mybatis</groupId>
+                <artifactId>mybatis</artifactId>
+                <version>${mybatis.version}</version>
+            </dependency>
             <dependency>
                 <groupId>com.baomidou</groupId>
                 <artifactId>mybatis-plus-boot-starter</artifactId>
@@ -260,6 +264,18 @@
                 <groupId>org.redisson</groupId>
                 <artifactId>redisson-spring-boot-starter</artifactId>
                 <version>${redisson.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.redisson</groupId>
+                        <!-- 使用 redisson-spring-data-27 替代,解决 Tuple NoClassDefFoundError 报错 -->
+                        <artifactId>redisson-spring-data-33</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>org.redisson</groupId>
+                <artifactId>redisson-spring-data-27</artifactId>
+                <version>${redisson.version}</version>
             </dependency>
 
             <dependency>
@@ -524,22 +540,6 @@
                 </exclusions>
             </dependency>
 
-            <dependency>
-                <groupId>cn.smallbun.screw</groupId>
-                <artifactId>screw-core</artifactId> <!-- 实现数据库文档 -->
-                <version>${screw.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>org.freemarker</groupId>
-                        <artifactId>freemarker</artifactId> <!-- 移除 Freemarker 依赖,采用 Velocity 作为模板引擎 -->
-                    </exclusion>
-                    <exclusion>
-                        <groupId>com.alibaba</groupId>
-                        <artifactId>fastjson</artifactId> <!-- 最新版screw-core1.0.5依赖fastjson1.2.73存在漏洞,移除。 -->
-                    </exclusion>
-                </exclusions>
-            </dependency>
-
             <dependency>
                 <groupId>com.google.guava</groupId>
                 <artifactId>guava</artifactId>
@@ -626,34 +626,6 @@
                 <version>${weixin-java.version}</version>
             </dependency>
 
-            <!-- SMS SDK begin -->
-            <dependency>
-                <groupId>com.aliyun</groupId>
-                <artifactId>aliyun-java-sdk-core</artifactId>
-                <version>${aliyun-java-sdk-core.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <artifactId>opentracing-api</artifactId>
-                        <groupId>io.opentracing</groupId>
-                    </exclusion>
-                    <exclusion>
-                        <artifactId>opentracing-util</artifactId>
-                        <groupId>io.opentracing</groupId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>com.aliyun</groupId>
-                <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
-                <version>${aliyun-java-sdk-dysmsapi.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.tencentcloudapi</groupId>
-                <artifactId>tencentcloud-sdk-java-sms</artifactId>
-                <version>${tencentcloud-sdk-java.version}</version>
-            </dependency>
-            <!-- SMS SDK end -->
-
             <dependency>
                 <groupId>com.xingyuv</groupId>
                 <artifactId>spring-boot-starter-justauth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->

+ 8 - 6
citu-framework/citu-spring-boot-starter-biz-data-permission/src/main/java/com/citu/framework/datapermission/config/CituDataPermissionAutoConfiguration.java

@@ -1,7 +1,8 @@
 package com.citu.framework.datapermission.config;
 
+import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
 import com.citu.framework.datapermission.core.aop.DataPermissionAnnotationAdvisor;
-import com.citu.framework.datapermission.core.db.DataPermissionDatabaseInterceptor;
+import com.citu.framework.datapermission.core.db.DataPermissionRuleHandler;
 import com.citu.framework.datapermission.core.rule.DataPermissionRule;
 import com.citu.framework.datapermission.core.rule.DataPermissionRuleFactory;
 import com.citu.framework.datapermission.core.rule.DataPermissionRuleFactoryImpl;
@@ -26,14 +27,15 @@ public class CituDataPermissionAutoConfiguration {
     }
 
     @Bean
-    public DataPermissionDatabaseInterceptor dataPermissionDatabaseInterceptor(MybatisPlusInterceptor interceptor,
-                                                                               DataPermissionRuleFactory ruleFactory) {
-        // 创建 DataPermissionDatabaseInterceptor 拦截器
-        DataPermissionDatabaseInterceptor inner = new DataPermissionDatabaseInterceptor(ruleFactory);
+    public DataPermissionRuleHandler dataPermissionRuleHandler(MybatisPlusInterceptor interceptor,
+                                                               DataPermissionRuleFactory ruleFactory) {
+        // 创建 DataPermissionInterceptor 拦截器
+        DataPermissionRuleHandler handler = new DataPermissionRuleHandler(ruleFactory);
+        DataPermissionInterceptor inner = new DataPermissionInterceptor(handler);
         // 添加到 interceptor 中
         // 需要加在首个,主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
         MyBatisUtils.addInterceptor(interceptor, inner, 0);
-        return inner;
+        return handler;
     }
 
     @Bean

+ 0 - 641
citu-framework/citu-spring-boot-starter-biz-data-permission/src/main/java/com/citu/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java

@@ -1,641 +0,0 @@
-package com.citu.framework.datapermission.core.db;
-
-import cn.hutool.core.collection.CollUtil;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
-import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
-import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
-import com.citu.framework.common.util.collection.SetUtils;
-import com.citu.framework.datapermission.core.rule.DataPermissionRule;
-import com.citu.framework.datapermission.core.rule.DataPermissionRuleFactory;
-import com.citu.framework.mybatis.core.util.MyBatisUtils;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import net.sf.jsqlparser.expression.*;
-import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
-import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
-import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
-import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
-import net.sf.jsqlparser.expression.operators.relational.InExpression;
-import net.sf.jsqlparser.schema.Table;
-import net.sf.jsqlparser.statement.delete.Delete;
-import net.sf.jsqlparser.statement.select.*;
-import net.sf.jsqlparser.statement.update.Update;
-import org.apache.ibatis.executor.Executor;
-import org.apache.ibatis.executor.statement.StatementHandler;
-import org.apache.ibatis.mapping.BoundSql;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.mapping.SqlCommandType;
-import org.apache.ibatis.session.ResultHandler;
-import org.apache.ibatis.session.RowBounds;
-
-import java.sql.Connection;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * 数据权限拦截器,通过 {@link DataPermissionRule} 数据权限规则,重写 SQL 的方式来实现
- * 主要的 SQL 重写方法,可见 {@link #builderExpression(Expression, List)} 方法
- * <p>
- * 整体的代码实现上,参考 {@link com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor} 实现。
- * 所以每次 MyBatis Plus 升级时,需要 Review 下其具体的实现是否有变更!
- *
- * @author Rayson
- */
-@RequiredArgsConstructor
-public class DataPermissionDatabaseInterceptor extends JsqlParserSupport implements InnerInterceptor {
-
-    private final DataPermissionRuleFactory ruleFactory;
-
-    @Getter
-    private final MappedStatementCache mappedStatementCache = new MappedStatementCache();
-
-    @Override // SELECT 场景
-    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
-        // 获得 Mapper 对应的数据权限的规则
-        List<DataPermissionRule> rules = ruleFactory.getDataPermissionRule(ms.getId());
-        if (mappedStatementCache.noRewritable(ms, rules)) { // 如果无需重写,则跳过
-            return;
-        }
-
-        PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
-        try {
-            // 初始化上下文
-            ContextHolder.init(rules);
-            // 处理 SQL
-            mpBs.sql(parserSingle(mpBs.sql(), null));
-        } finally {
-            // 添加是否需要重写的缓存
-            addMappedStatementCache(ms);
-            // 清空上下文
-            ContextHolder.clear();
-        }
-    }
-
-    @Override // 只处理 UPDATE / DELETE 场景,不处理 INSERT 场景(因为 INSERT 不需要数据权限)
-    public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
-        PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
-        MappedStatement ms = mpSh.mappedStatement();
-        SqlCommandType sct = ms.getSqlCommandType();
-        if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
-            // 获得 Mapper 对应的数据权限的规则
-            List<DataPermissionRule> rules = ruleFactory.getDataPermissionRule(ms.getId());
-            if (mappedStatementCache.noRewritable(ms, rules)) { // 如果无需重写,则跳过
-                return;
-            }
-
-            PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
-            try {
-                // 初始化上下文
-                ContextHolder.init(rules);
-                // 处理 SQL
-                mpBs.sql(parserMulti(mpBs.sql(), null));
-            } finally {
-                // 添加是否需要重写的缓存
-                addMappedStatementCache(ms);
-                // 清空上下文
-                ContextHolder.clear();
-            }
-        }
-    }
-
-    @Override
-    protected void processSelect(Select select, int index, String sql, Object obj) {
-        processSelectBody(select.getSelectBody());
-        List<WithItem> withItemsList = select.getWithItemsList();
-        if (!CollectionUtils.isEmpty(withItemsList)) {
-            withItemsList.forEach(this::processSelectBody);
-        }
-    }
-
-    /**
-     * update 语句处理
-     */
-    @Override
-    protected void processUpdate(Update update, int index, String sql, Object obj) {
-        final Table table = update.getTable();
-        update.setWhere(this.builderExpression(update.getWhere(), table));
-    }
-
-    /**
-     * delete 语句处理
-     */
-    @Override
-    protected void processDelete(Delete delete, int index, String sql, Object obj) {
-        delete.setWhere(this.builderExpression(delete.getWhere(), delete.getTable()));
-    }
-
-    // ========== 和 TenantLineInnerInterceptor 一致的逻辑 ==========
-
-    protected void processSelectBody(SelectBody selectBody) {
-        if (selectBody == null) {
-            return;
-        }
-        if (selectBody instanceof PlainSelect) {
-            processPlainSelect((PlainSelect) selectBody);
-        } else if (selectBody instanceof WithItem) {
-            WithItem withItem = (WithItem) selectBody;
-            processSelectBody(withItem.getSubSelect().getSelectBody());
-        } else {
-            SetOperationList operationList = (SetOperationList) selectBody;
-            List<SelectBody> selectBodyList = operationList.getSelects();
-            if (CollectionUtils.isNotEmpty(selectBodyList)) {
-                selectBodyList.forEach(this::processSelectBody);
-            }
-        }
-    }
-
-    /**
-     * 处理 PlainSelect
-     */
-    protected void processPlainSelect(PlainSelect plainSelect) {
-        //#3087 github
-        List<SelectItem> selectItems = plainSelect.getSelectItems();
-        if (CollectionUtils.isNotEmpty(selectItems)) {
-            selectItems.forEach(this::processSelectItem);
-        }
-
-        // 处理 where 中的子查询
-        Expression where = plainSelect.getWhere();
-        processWhereSubSelect(where);
-
-        // 处理 fromItem
-        FromItem fromItem = plainSelect.getFromItem();
-        List<Table> list = processFromItem(fromItem);
-        List<Table> mainTables = new ArrayList<>(list);
-
-        // 处理 join
-        List<Join> joins = plainSelect.getJoins();
-        if (CollectionUtils.isNotEmpty(joins)) {
-            mainTables = processJoins(mainTables, joins);
-        }
-
-        // 当有 mainTable 时,进行 where 条件追加
-        if (CollectionUtils.isNotEmpty(mainTables)) {
-            plainSelect.setWhere(builderExpression(where, mainTables));
-        }
-    }
-
-    private List<Table> processFromItem(FromItem fromItem) {
-        // 处理括号括起来的表达式
-        while (fromItem instanceof ParenthesisFromItem) {
-            fromItem = ((ParenthesisFromItem) fromItem).getFromItem();
-        }
-
-        List<Table> mainTables = new ArrayList<>();
-        // 无 join 时的处理逻辑
-        if (fromItem instanceof Table) {
-            Table fromTable = (Table) fromItem;
-            mainTables.add(fromTable);
-        } else if (fromItem instanceof SubJoin) {
-            // SubJoin 类型则还需要添加上 where 条件
-            List<Table> tables = processSubJoin((SubJoin) fromItem);
-            mainTables.addAll(tables);
-        } else {
-            // 处理下 fromItem
-            processOtherFromItem(fromItem);
-        }
-        return mainTables;
-    }
-
-    /**
-     * 处理where条件内的子查询
-     * <p>
-     * 支持如下:
-     * 1. in
-     * 2. =
-     * 3. >
-     * 4. <
-     * 5. >=
-     * 6. <=
-     * 7. <>
-     * 8. EXISTS
-     * 9. NOT EXISTS
-     * <p>
-     * 前提条件:
-     * 1. 子查询必须放在小括号中
-     * 2. 子查询一般放在比较操作符的右边
-     *
-     * @param where where 条件
-     */
-    protected void processWhereSubSelect(Expression where) {
-        if (where == null) {
-            return;
-        }
-        if (where instanceof FromItem) {
-            processOtherFromItem((FromItem) where);
-            return;
-        }
-        if (where.toString().indexOf("SELECT") > 0) {
-            // 有子查询
-            if (where instanceof BinaryExpression) {
-                // 比较符号 , and , or , 等等
-                BinaryExpression expression = (BinaryExpression) where;
-                processWhereSubSelect(expression.getLeftExpression());
-                processWhereSubSelect(expression.getRightExpression());
-            } else if (where instanceof InExpression) {
-                // in
-                InExpression expression = (InExpression) where;
-                Expression inExpression = expression.getRightExpression();
-                if (inExpression instanceof SubSelect) {
-                    processSelectBody(((SubSelect) inExpression).getSelectBody());
-                }
-            } else if (where instanceof ExistsExpression) {
-                // exists
-                ExistsExpression expression = (ExistsExpression) where;
-                processWhereSubSelect(expression.getRightExpression());
-            } else if (where instanceof NotExpression) {
-                // not exists
-                NotExpression expression = (NotExpression) where;
-                processWhereSubSelect(expression.getExpression());
-            } else if (where instanceof Parenthesis) {
-                Parenthesis expression = (Parenthesis) where;
-                processWhereSubSelect(expression.getExpression());
-            }
-        }
-    }
-
-    protected void processSelectItem(SelectItem selectItem) {
-        if (selectItem instanceof SelectExpressionItem) {
-            SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
-            if (selectExpressionItem.getExpression() instanceof SubSelect) {
-                processSelectBody(((SubSelect) selectExpressionItem.getExpression()).getSelectBody());
-            } else if (selectExpressionItem.getExpression() instanceof Function) {
-                processFunction((Function) selectExpressionItem.getExpression());
-            }
-        }
-    }
-
-    /**
-     * 处理函数
-     * <p>支持: 1. select fun(args..) 2. select fun1(fun2(args..),args..)<p>
-     * <p> fixed gitee pulls/141</p>
-     *
-     * @param function
-     */
-    protected void processFunction(Function function) {
-        ExpressionList parameters = function.getParameters();
-        if (parameters != null) {
-            parameters.getExpressions().forEach(expression -> {
-                if (expression instanceof SubSelect) {
-                    processSelectBody(((SubSelect) expression).getSelectBody());
-                } else if (expression instanceof Function) {
-                    processFunction((Function) expression);
-                }
-            });
-        }
-    }
-
-    /**
-     * 处理子查询等
-     */
-    protected void processOtherFromItem(FromItem fromItem) {
-        // 去除括号
-        while (fromItem instanceof ParenthesisFromItem) {
-            fromItem = ((ParenthesisFromItem) fromItem).getFromItem();
-        }
-
-        if (fromItem instanceof SubSelect) {
-            SubSelect subSelect = (SubSelect) fromItem;
-            if (subSelect.getSelectBody() != null) {
-                processSelectBody(subSelect.getSelectBody());
-            }
-        } else if (fromItem instanceof ValuesList) {
-            logger.debug("Perform a subQuery, if you do not give us feedback");
-        } else if (fromItem instanceof LateralSubSelect) {
-            LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem;
-            if (lateralSubSelect.getSubSelect() != null) {
-                SubSelect subSelect = lateralSubSelect.getSubSelect();
-                if (subSelect.getSelectBody() != null) {
-                    processSelectBody(subSelect.getSelectBody());
-                }
-            }
-        }
-    }
-
-    /**
-     * 处理 sub join
-     *
-     * @param subJoin subJoin
-     * @return Table subJoin 中的主表
-     */
-    private List<Table> processSubJoin(SubJoin subJoin) {
-        List<Table> mainTables = new ArrayList<>();
-        if (subJoin.getJoinList() != null) {
-            List<Table> list = processFromItem(subJoin.getLeft());
-            mainTables.addAll(list);
-            mainTables = processJoins(mainTables, subJoin.getJoinList());
-        }
-        return mainTables;
-    }
-
-    /**
-     * 处理 joins
-     *
-     * @param mainTables 可以为 null
-     * @param joins      join 集合
-     * @return List<Table> 右连接查询的 Table 列表
-     */
-    private List<Table> processJoins(List<Table> mainTables, List<Join> joins) {
-        // join 表达式中最终的主表
-        Table mainTable = null;
-        // 当前 join 的左表
-        Table leftTable = null;
-
-        if (mainTables == null) {
-            mainTables = new ArrayList<>();
-        } else if (mainTables.size() == 1) {
-            mainTable = mainTables.get(0);
-            leftTable = mainTable;
-        }
-
-        //对于 on 表达式写在最后的 join,需要记录下前面多个 on 的表名
-        Deque<List<Table>> onTableDeque = new LinkedList<>();
-        for (Join join : joins) {
-            // 处理 on 表达式
-            FromItem joinItem = join.getRightItem();
-
-            // 获取当前 join 的表,subJoint 可以看作是一张表
-            List<Table> joinTables = null;
-            if (joinItem instanceof Table) {
-                joinTables = new ArrayList<>();
-                joinTables.add((Table) joinItem);
-            } else if (joinItem instanceof SubJoin) {
-                joinTables = processSubJoin((SubJoin) joinItem);
-            }
-
-            if (joinTables != null) {
-
-                // 如果是隐式内连接
-                if (join.isSimple()) {
-                    mainTables.addAll(joinTables);
-                    continue;
-                }
-
-                // 当前表是否忽略
-                Table joinTable = joinTables.get(0);
-
-                List<Table> onTables = null;
-                // 如果不要忽略,且是右连接,则记录下当前表
-                if (join.isRight()) {
-                    mainTable = joinTable;
-                    if (leftTable != null) {
-                        onTables = Collections.singletonList(leftTable);
-                    }
-                } else if (join.isLeft()) {
-                    onTables = Collections.singletonList(joinTable);
-                } else if (join.isInner()) {
-                    if (mainTable == null) {
-                        onTables = Collections.singletonList(joinTable);
-                    } else {
-                        onTables = Arrays.asList(mainTable, joinTable);
-                    }
-                    mainTable = null;
-                }
-
-                mainTables = new ArrayList<>();
-                if (mainTable != null) {
-                    mainTables.add(mainTable);
-                }
-
-                // 获取 join 尾缀的 on 表达式列表
-                Collection<Expression> originOnExpressions = join.getOnExpressions();
-                // 正常 join on 表达式只有一个,立刻处理
-                if (originOnExpressions.size() == 1 && onTables != null) {
-                    List<Expression> onExpressions = new LinkedList<>();
-                    onExpressions.add(builderExpression(originOnExpressions.iterator().next(), onTables));
-                    join.setOnExpressions(onExpressions);
-                    leftTable = joinTable;
-                    continue;
-                }
-                // 表名压栈,忽略的表压入 null,以便后续不处理
-                onTableDeque.push(onTables);
-                // 尾缀多个 on 表达式的时候统一处理
-                if (originOnExpressions.size() > 1) {
-                    Collection<Expression> onExpressions = new LinkedList<>();
-                    for (Expression originOnExpression : originOnExpressions) {
-                        List<Table> currentTableList = onTableDeque.poll();
-                        if (CollectionUtils.isEmpty(currentTableList)) {
-                            onExpressions.add(originOnExpression);
-                        } else {
-                            onExpressions.add(builderExpression(originOnExpression, currentTableList));
-                        }
-                    }
-                    join.setOnExpressions(onExpressions);
-                }
-                leftTable = joinTable;
-            } else {
-                processOtherFromItem(joinItem);
-                leftTable = null;
-            }
-        }
-
-        return mainTables;
-    }
-
-    // ========== 和 TenantLineInnerInterceptor 存在差异的逻辑:关键,实现权限条件的拼接 ==========
-
-    /**
-     * 处理条件
-     *
-     * @param currentExpression 当前 where 条件
-     * @param table             单个表
-     */
-    protected Expression builderExpression(Expression currentExpression, Table table) {
-        return this.builderExpression(currentExpression, Collections.singletonList(table));
-    }
-
-    /**
-     * 处理条件
-     *
-     * @param currentExpression 当前 where 条件
-     * @param tables            多个表
-     */
-    protected Expression builderExpression(Expression currentExpression, List<Table> tables) {
-        // 没有表需要处理直接返回
-        if (CollectionUtils.isEmpty(tables)) {
-            return currentExpression;
-        }
-
-        // 第一步,获得 Table 对应的数据权限条件
-        Expression dataPermissionExpression = null;
-        for (Table table : tables) {
-            // 构建每个表的权限 Expression 条件
-            Expression expression = buildDataPermissionExpression(table);
-            if (expression == null) {
-                continue;
-            }
-            // 合并到 dataPermissionExpression 中
-            dataPermissionExpression = dataPermissionExpression == null ? expression
-                    : new AndExpression(dataPermissionExpression, expression);
-        }
-
-        // 第二步,合并多个 Expression 条件
-        if (dataPermissionExpression == null) {
-            return currentExpression;
-        }
-        if (currentExpression == null) {
-            return dataPermissionExpression;
-        }
-        // ① 如果表达式为 Or,则需要 (currentExpression) AND dataPermissionExpression
-        if (currentExpression instanceof OrExpression) {
-            return new AndExpression(new Parenthesis(currentExpression), dataPermissionExpression);
-        }
-        // ② 如果表达式为 And,则直接返回 where AND dataPermissionExpression
-        return new AndExpression(currentExpression, dataPermissionExpression);
-    }
-
-    /**
-     * 构建指定表的数据权限的 Expression 过滤条件
-     *
-     * @param table 表
-     * @return Expression 过滤条件
-     */
-    private Expression buildDataPermissionExpression(Table table) {
-        // 生成条件
-        Expression allExpression = null;
-        for (DataPermissionRule rule : ContextHolder.getRules()) {
-            // 判断表名是否匹配
-            String tableName = MyBatisUtils.getTableName(table);
-            if (!rule.getTableNames().contains(tableName)) {
-                continue;
-            }
-            // 如果有匹配的规则,说明可重写。
-            // 为什么不是有 allExpression 非空才重写呢?在生成 column = value 过滤条件时,会因为 value 不存在,导致未重写。
-            // 这样导致第一次无 value,被标记成无需重写;但是第二次有 value,此时会需要重写。
-            ContextHolder.setRewrite(true);
-
-            // 单条规则的条件
-            Expression oneExpress = rule.getExpression(tableName, table.getAlias());
-            if (oneExpress == null) {
-                continue;
-            }
-            // 拼接到 allExpression 中
-            allExpression = allExpression == null ? oneExpress
-                    : new AndExpression(allExpression, oneExpress);
-        }
-
-        return allExpression;
-    }
-
-    /**
-     * 判断 SQL 是否重写。如果没有重写,则添加到 {@link MappedStatementCache} 中
-     *
-     * @param ms MappedStatement
-     */
-    private void addMappedStatementCache(MappedStatement ms) {
-        if (ContextHolder.getRewrite()) {
-            return;
-        }
-        // 无重写,进行添加
-        mappedStatementCache.addNoRewritable(ms, ContextHolder.getRules());
-    }
-
-    /**
-     * SQL 解析上下文,方便透传 {@link DataPermissionRule} 规则
-     *
-     * @author Rayson
-     */
-    static final class ContextHolder {
-
-        /**
-         * 该 {@link MappedStatement} 对应的规则
-         */
-        private static final ThreadLocal<List<DataPermissionRule>> RULES = ThreadLocal.withInitial(Collections::emptyList);
-        /**
-         * SQL 是否进行重写
-         */
-        private static final ThreadLocal<Boolean> REWRITE = ThreadLocal.withInitial(() -> Boolean.FALSE);
-
-        public static void init(List<DataPermissionRule> rules) {
-            RULES.set(rules);
-            REWRITE.set(false);
-        }
-
-        public static void clear() {
-            RULES.remove();
-            REWRITE.remove();
-        }
-
-        public static boolean getRewrite() {
-            return REWRITE.get();
-        }
-
-        public static void setRewrite(boolean rewrite) {
-            REWRITE.set(rewrite);
-        }
-
-        public static List<DataPermissionRule> getRules() {
-            return RULES.get();
-        }
-
-    }
-
-    /**
-     * {@link MappedStatement} 缓存
-     * 目前主要用于,记录 {@link DataPermissionRule} 是否对指定 {@link MappedStatement} 无效
-     * 如果无效,则可以避免 SQL 的解析,加快速度
-     *
-     * @author Rayson
-     */
-    static final class MappedStatementCache {
-
-        /**
-         * 指定数据权限规则,对指定 MappedStatement 无需重写(不生效)的缓存
-         * <p>
-         * value:{@link MappedStatement#getId()} 编号
-         */
-        @Getter
-        private final Map<Class<? extends DataPermissionRule>, Set<String>> noRewritableMappedStatements = new ConcurrentHashMap<>();
-
-        /**
-         * 判断是否无需重写
-         * ps:虽然有点中文式英语,但是容易读懂即可
-         *
-         * @param ms    MappedStatement
-         * @param rules 数据权限规则数组
-         * @return 是否无需重写
-         */
-        public boolean noRewritable(MappedStatement ms, List<DataPermissionRule> rules) {
-            // 如果规则为空,说明无需重写
-            if (CollUtil.isEmpty(rules)) {
-                return true;
-            }
-            // 任一规则不在 noRewritableMap 中,则说明可能需要重写
-            for (DataPermissionRule rule : rules) {
-                Set<String> mappedStatementIds = noRewritableMappedStatements.get(rule.getClass());
-                if (!CollUtil.contains(mappedStatementIds, ms.getId())) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        /**
-         * 添加无需重写的 MappedStatement
-         *
-         * @param ms    MappedStatement
-         * @param rules 数据权限规则数组
-         */
-        public void addNoRewritable(MappedStatement ms, List<DataPermissionRule> rules) {
-            for (DataPermissionRule rule : rules) {
-                Set<String> mappedStatementIds = noRewritableMappedStatements.get(rule.getClass());
-                if (CollUtil.isNotEmpty(mappedStatementIds)) {
-                    mappedStatementIds.add(ms.getId());
-                } else {
-                    noRewritableMappedStatements.put(rule.getClass(), SetUtils.asSet(ms.getId()));
-                }
-            }
-        }
-
-        /**
-         * 清空缓存
-         * 目前主要提供给单元测试
-         */
-        public void clear() {
-            noRewritableMappedStatements.clear();
-        }
-
-    }
-
-}

+ 57 - 0
citu-framework/citu-spring-boot-starter-biz-data-permission/src/main/java/com/citu/framework/datapermission/core/db/DataPermissionRuleHandler.java

@@ -0,0 +1,57 @@
+package com.citu.framework.datapermission.core.db;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
+import com.citu.framework.datapermission.core.rule.DataPermissionRule;
+import com.citu.framework.datapermission.core.rule.DataPermissionRuleFactory;
+import com.citu.framework.mybatis.core.util.MyBatisUtils;
+import lombok.RequiredArgsConstructor;
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
+import net.sf.jsqlparser.schema.Table;
+
+import java.util.List;
+
+/**
+ * 基于 {@link DataPermissionRule} 的数据权限处理器
+ * <p>
+ * 它的底层,是基于 MyBatis Plus 的 <a href="https://baomidou.com/plugins/data-permission/">数据权限插件</a>
+ * 核心原理:它会在 SQL 执行前拦截 SQL 语句,并根据用户权限动态添加权限相关的 SQL 片段。这样,只有用户有权限访问的数据才会被查询出来
+ *
+ * @author 芋道源码
+ */
+@RequiredArgsConstructor
+public class DataPermissionRuleHandler implements MultiDataPermissionHandler {
+
+    private final DataPermissionRuleFactory ruleFactory;
+
+    @Override
+    public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
+        // 获得 Mapper 对应的数据权限的规则
+        List<DataPermissionRule> rules = ruleFactory.getDataPermissionRule(mappedStatementId);
+        if (CollUtil.isEmpty(rules)) {
+            return null;
+        }
+
+        // 生成条件
+        Expression allExpression = null;
+        for (DataPermissionRule rule : rules) {
+            // 判断表名是否匹配
+            String tableName = MyBatisUtils.getTableName(table);
+            if (!rule.getTableNames().contains(tableName)) {
+                continue;
+            }
+
+            // 单条规则的条件
+            Expression oneExpress = rule.getExpression(tableName, table.getAlias());
+            if (oneExpress == null) {
+                continue;
+            }
+            // 拼接到 allExpression 中
+            allExpression = allExpression == null ? oneExpress
+                    : new AndExpression(allExpression, oneExpress);
+        }
+        return allExpression;
+    }
+
+}

+ 0 - 190
citu-framework/citu-spring-boot-starter-biz-data-permission/src/test/java/com/citu/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest.java

@@ -1,190 +0,0 @@
-package com.citu.framework.datapermission.core.db;
-
-import com.citu.framework.common.util.collection.SetUtils;
-import com.citu.framework.datapermission.core.rule.DataPermissionRule;
-import com.citu.framework.datapermission.core.rule.DataPermissionRuleFactory;
-import com.citu.framework.mybatis.core.util.MyBatisUtils;
-import com.citu.framework.test.core.ut.BaseMockitoUnitTest;
-import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
-import net.sf.jsqlparser.expression.Alias;
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.expression.LongValue;
-import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
-import net.sf.jsqlparser.schema.Column;
-import org.apache.ibatis.executor.Executor;
-import org.apache.ibatis.executor.statement.StatementHandler;
-import org.apache.ibatis.mapping.BoundSql;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockedStatic;
-
-import java.sql.Connection;
-import java.util.*;
-
-import static java.util.Collections.singletonList;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-/**
- * {@link DataPermissionDatabaseInterceptor} 的单元测试
- * 主要测试 {@link DataPermissionDatabaseInterceptor#beforePrepare(StatementHandler, Connection, Integer)}
- * 和 {@link DataPermissionDatabaseInterceptor#beforeUpdate(Executor, MappedStatement, Object)}
- * 以及在这个过程中,ContextHolder 和 MappedStatementCache
- *
- * @author Rayson
- */
-public class DataPermissionDatabaseInterceptorTest extends BaseMockitoUnitTest {
-
-    @InjectMocks
-    private DataPermissionDatabaseInterceptor interceptor;
-
-    @Mock
-    private DataPermissionRuleFactory ruleFactory;
-
-    @BeforeEach
-    public void setUp() {
-        // 清理上下文
-        DataPermissionDatabaseInterceptor.ContextHolder.clear();
-        // 清空缓存
-        interceptor.getMappedStatementCache().clear();
-    }
-
-    @Test // 不存在规则,且不匹配
-    public void testBeforeQuery_withoutRule() {
-        try (MockedStatic<PluginUtils> pluginUtilsMock = mockStatic(PluginUtils.class)) {
-            // 准备参数
-            MappedStatement mappedStatement = mock(MappedStatement.class);
-            BoundSql boundSql = mock(BoundSql.class);
-
-            // 调用
-            interceptor.beforeQuery(null, mappedStatement, null, null, null, boundSql);
-            // 断言
-            pluginUtilsMock.verify(() -> PluginUtils.mpBoundSql(boundSql), never());
-        }
-    }
-
-    @Test // 存在规则,且不匹配
-    public void testBeforeQuery_withMatchRule() {
-        try (MockedStatic<PluginUtils> pluginUtilsMock = mockStatic(PluginUtils.class)) {
-            // 准备参数
-            MappedStatement mappedStatement = mock(MappedStatement.class);
-            BoundSql boundSql = mock(BoundSql.class);
-            // mock 方法(数据权限)
-            when(ruleFactory.getDataPermissionRule(same(mappedStatement.getId())))
-                    .thenReturn(singletonList(new DeptDataPermissionRule()));
-            // mock 方法(MPBoundSql)
-            PluginUtils.MPBoundSql mpBs = mock(PluginUtils.MPBoundSql.class);
-            pluginUtilsMock.when(() -> PluginUtils.mpBoundSql(same(boundSql))).thenReturn(mpBs);
-            // mock 方法(SQL)
-            String sql = "select * from t_user where id = 1";
-            when(mpBs.sql()).thenReturn(sql);
-            // 针对 ContextHolder 和 MappedStatementCache 暂时不 mock,主要想校验过程中,数据是否正确
-
-            // 调用
-            interceptor.beforeQuery(null, mappedStatement, null, null, null, boundSql);
-            // 断言
-            verify(mpBs, times(1)).sql(
-                    eq("SELECT * FROM t_user WHERE id = 1 AND t_user.dept_id = 100"));
-            // 断言缓存
-            assertTrue(interceptor.getMappedStatementCache().getNoRewritableMappedStatements().isEmpty());
-        }
-    }
-
-    @Test // 存在规则,但不匹配
-    public void testBeforeQuery_withoutMatchRule() {
-        try (MockedStatic<PluginUtils> pluginUtilsMock = mockStatic(PluginUtils.class)) {
-            // 准备参数
-            MappedStatement mappedStatement = mock(MappedStatement.class);
-            BoundSql boundSql = mock(BoundSql.class);
-            // mock 方法(数据权限)
-            when(ruleFactory.getDataPermissionRule(same(mappedStatement.getId())))
-                    .thenReturn(singletonList(new DeptDataPermissionRule()));
-            // mock 方法(MPBoundSql)
-            PluginUtils.MPBoundSql mpBs = mock(PluginUtils.MPBoundSql.class);
-            pluginUtilsMock.when(() -> PluginUtils.mpBoundSql(same(boundSql))).thenReturn(mpBs);
-            // mock 方法(SQL)
-            String sql = "select * from t_role where id = 1";
-            when(mpBs.sql()).thenReturn(sql);
-            // 针对 ContextHolder 和 MappedStatementCache 暂时不 mock,主要想校验过程中,数据是否正确
-
-            // 调用
-            interceptor.beforeQuery(null, mappedStatement, null, null, null, boundSql);
-            // 断言
-            verify(mpBs, times(1)).sql(
-                    eq("SELECT * FROM t_role WHERE id = 1"));
-            // 断言缓存
-            assertFalse(interceptor.getMappedStatementCache().getNoRewritableMappedStatements().isEmpty());
-        }
-    }
-
-    @Test
-    public void testAddNoRewritable() {
-        // 准备参数
-        MappedStatement ms = mock(MappedStatement.class);
-        List<DataPermissionRule> rules = singletonList(new DeptDataPermissionRule());
-        // mock 方法
-        when(ms.getId()).thenReturn("selectById");
-
-        // 调用
-        interceptor.getMappedStatementCache().addNoRewritable(ms, rules);
-        // 断言
-        Map<Class<? extends DataPermissionRule>, Set<String>> noRewritableMappedStatements =
-                interceptor.getMappedStatementCache().getNoRewritableMappedStatements();
-        assertEquals(1, noRewritableMappedStatements.size());
-        assertEquals(SetUtils.asSet("selectById"), noRewritableMappedStatements.get(DeptDataPermissionRule.class));
-    }
-
-    @Test
-    public void testNoRewritable() {
-        // 准备参数
-        MappedStatement ms = mock(MappedStatement.class);
-        // mock 方法
-        when(ms.getId()).thenReturn("selectById");
-        // mock 数据
-        List<DataPermissionRule> rules = singletonList(new DeptDataPermissionRule());
-        interceptor.getMappedStatementCache().addNoRewritable(ms, rules);
-
-        // 场景一,rules 为空
-        assertTrue(interceptor.getMappedStatementCache().noRewritable(ms, null));
-        // 场景二,rules 非空,可重写
-        assertFalse(interceptor.getMappedStatementCache().noRewritable(ms, singletonList(new EmptyDataPermissionRule())));
-        // 场景三,rule 非空,不可重写
-        assertTrue(interceptor.getMappedStatementCache().noRewritable(ms, rules));
-    }
-
-    private static class DeptDataPermissionRule implements DataPermissionRule {
-
-        private static final String COLUMN = "dept_id";
-
-        @Override
-        public Set<String> getTableNames() {
-            return SetUtils.asSet("t_user");
-        }
-
-        @Override
-        public Expression getExpression(String tableName, Alias tableAlias) {
-            Column column = MyBatisUtils.buildColumn(tableName, tableAlias, COLUMN);
-            LongValue value = new LongValue(100L);
-            return new EqualsTo(column, value);
-        }
-
-    }
-
-    private static class EmptyDataPermissionRule implements DataPermissionRule {
-
-        @Override
-        public Set<String> getTableNames() {
-            return Collections.emptySet();
-        }
-
-        @Override
-        public Expression getExpression(String tableName, Alias tableAlias) {
-            return null;
-        }
-
-    }
-
-}

+ 20 - 13
citu-framework/citu-spring-boot-starter-biz-data-permission/src/test/java/com/citu/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest2.java → citu-framework/citu-spring-boot-starter-biz-data-permission/src/test/java/com/citu/framework/datapermission/core/db/DataPermissionRuleHandlerTest.java

@@ -1,5 +1,6 @@
 package com.citu.framework.datapermission.core.db;
 
+import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
 import com.citu.framework.datapermission.core.rule.DataPermissionRule;
 import com.citu.framework.datapermission.core.rule.DataPermissionRuleFactory;
 import com.citu.framework.mybatis.core.util.MyBatisUtils;
@@ -7,6 +8,7 @@ import com.citu.framework.test.core.ut.BaseMockitoUnitTest;
 import net.sf.jsqlparser.expression.Alias;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.LongValue;
+import net.sf.jsqlparser.expression.Parenthesis;
 import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
 import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
 import net.sf.jsqlparser.expression.operators.relational.InExpression;
@@ -21,24 +23,30 @@ import java.util.Set;
 
 import static com.citu.framework.common.util.collection.SetUtils.asSet;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.when;
 
 /**
- * {@link DataPermissionDatabaseInterceptor} 的单元测试
+ * {@link DataPermissionRuleHandler} 的单元测试
  * 主要复用了 MyBatis Plus 的 TenantLineInnerInterceptorTest 的单元测试
  * 不过它的单元测试不是很规范,考虑到是复用的,所以暂时不进行修改~
  *
- * @author Rayson
+ * @author 芋道源码
  */
-public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest {
+public class DataPermissionRuleHandlerTest extends BaseMockitoUnitTest {
 
     @InjectMocks
-    private DataPermissionDatabaseInterceptor interceptor;
+    private DataPermissionRuleHandler handler;
 
     @Mock
     private DataPermissionRuleFactory ruleFactory;
 
+    private DataPermissionInterceptor interceptor;
+
     @BeforeEach
     public void setUp() {
+        interceptor = new DataPermissionInterceptor(handler);
+
         // 租户的数据权限规则
         DataPermissionRule tenantRule = new DataPermissionRule() {
 
@@ -71,14 +79,14 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
             @Override
             public Expression getExpression(String tableName, Alias tableAlias) {
                 Column column = MyBatisUtils.buildColumn(tableName, tableAlias, COLUMN);
-                ExpressionList values = new ExpressionList(new LongValue(10L),
+                ExpressionList<LongValue> values = new ExpressionList<>(new LongValue(10L),
                         new LongValue(20L));
-                return new InExpression(column, values);
+                return new InExpression(column, new Parenthesis((values)));
             }
 
         };
-        // 设置到上下文,保证
-        DataPermissionDatabaseInterceptor.ContextHolder.init(Arrays.asList(tenantRule, deptRule));
+        // 设置到上下文
+        when(ruleFactory.getDataPermissionRule(any())).thenReturn(Arrays.asList(tenantRule, deptRule));
     }
 
     @Test
@@ -262,7 +270,7 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
                         "right join entity2 e2 on e1.id = e2.id",
                 "SELECT * FROM entity e " +
                         "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                        "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1 " +
+                        "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e.tenant_id = 1 " +
                         "WHERE e2.tenant_id = 1");
 
         assertSql("SELECT * FROM entity e " +
@@ -447,7 +455,6 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
         assertEquals(targetSql, interceptor.parserSingle(sql, null));
     }
 
-
     // ========== 额外的测试 ==========
 
     @Test
@@ -525,9 +532,9 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
 
         // 没有 On 的 inner join
         assertSql("SELECT * FROM entity,entity1 " +
-                "WHERE entity.id = entity1.id",
-            "SELECT * FROM entity, entity1 " +
-                    "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
+                        "WHERE entity.id = entity1.id",
+                "SELECT * FROM entity, entity1 " +
+                        "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
     }
 
 }

+ 0 - 31
citu-framework/citu-spring-boot-starter-mybatis/src/main/java/com/citu/framework/mybatis/core/type/JsonLongSetTypeHandler.java

@@ -1,31 +0,0 @@
-package com.citu.framework.mybatis.core.type;
-
-import com.citu.framework.common.util.json.JsonUtils;
-import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
-import com.fasterxml.jackson.core.type.TypeReference;
-
-import java.util.Set;
-
-/**
- * 参考 {@link com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler} 实现
- * 在我们将字符串反序列化为 Set 并且泛型为 Long 时,如果每个元素的数值太小,会被处理成 Integer 类型,导致可能存在隐性的 BUG。
- *
- * 例如说哦,SysUserDO 的 postIds 属性
- *
- * @author Rayson
- */
-public class JsonLongSetTypeHandler extends AbstractJsonTypeHandler<Object> {
-
-    private static final TypeReference<Set<Long>> TYPE_REFERENCE = new TypeReference<Set<Long>>(){};
-
-    @Override
-    protected Object parse(String json) {
-        return JsonUtils.parseObject(json, TYPE_REFERENCE);
-    }
-
-    @Override
-    protected String toJson(Object obj) {
-        return JsonUtils.toJsonString(obj);
-    }
-
-}

+ 2 - 2
citu-module-bpm/citu-module-bpm-biz/src/main/java/com/citu/module/bpm/dal/dataobject/definition/BpmUserGroupDO.java

@@ -1,8 +1,8 @@
 package com.citu.module.bpm.dal.dataobject.definition;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.framework.common.enums.CommonStatusEnum;
 import com.citu.framework.mybatis.core.dataobject.BaseDO;
-import com.citu.framework.mybatis.core.type.JsonLongSetTypeHandler;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -47,7 +47,7 @@ public class BpmUserGroupDO extends BaseDO {
     /**
      * 成员用户编号数组
      */
-    @TableField(typeHandler = JsonLongSetTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private Set<Long> userIds;
 
 }

+ 12 - 2
citu-module-infra/citu-module-infra-biz/src/main/java/com/citu/module/infra/dal/dataobject/file/FileConfigDO.java

@@ -17,6 +17,8 @@ import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
 import com.fasterxml.jackson.core.type.TypeReference;
 import lombok.*;
 
+import java.lang.reflect.Field;
+
 /**
  * 文件配置表
  *
@@ -65,8 +67,16 @@ public class FileConfigDO extends BaseDO {
 
     public static class FileClientConfigTypeHandler extends AbstractJsonTypeHandler<Object> {
 
+        public FileClientConfigTypeHandler(Class<?> type) {
+            super(type);
+        }
+
+        public FileClientConfigTypeHandler(Class<?> type, Field field) {
+            super(type, field);
+        }
+
         @Override
-        protected Object parse(String json) {
+        public Object parse(String json) {
             FileClientConfig config = JsonUtils.parseObjectQuietly(json, new TypeReference<FileClientConfig>() {});
             if (config != null) {
                 return config;
@@ -92,7 +102,7 @@ public class FileConfigDO extends BaseDO {
         }
 
         @Override
-        protected String toJson(Object obj) {
+        public String toJson(Object obj) {
             return JsonUtils.toJsonString(obj);
         }
 

+ 0 - 1
citu-module-mall/citu-module-product-biz/src/main/java/com/citu/module/product/controller/admin/property/ProductPropertyController.java

@@ -17,7 +17,6 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
-
 import java.util.List;
 
 import static com.citu.framework.common.pojo.CommonResult.success;

+ 0 - 1
citu-module-mall/citu-module-product-biz/src/main/java/com/citu/module/product/controller/admin/property/ProductPropertyValueController.java

@@ -17,7 +17,6 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
-
 import java.util.List;
 
 import static com.citu.framework.common.pojo.CommonResult.success;

+ 1 - 1
citu-module-mall/citu-module-product-biz/src/main/java/com/citu/module/product/dal/dataobject/comment/ProductCommentDO.java

@@ -100,7 +100,7 @@ public class ProductCommentDO extends BaseDO {
      *
      * 关联 {@link ProductSkuDO#getProperties()}
      */
-    @TableField(typeHandler = ProductSkuDO.PropertyTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private List<ProductSkuDO.Property> skuProperties;
 
     /**

+ 2 - 16
citu-module-mall/citu-module-product-biz/src/main/java/com/citu/module/product/dal/dataobject/sku/ProductSkuDO.java

@@ -1,5 +1,6 @@
 package com.citu.module.product.dal.dataobject.sku;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.framework.common.util.json.JsonUtils;
 import com.citu.framework.mybatis.core.dataobject.BaseDO;
 import com.citu.module.product.dal.dataobject.property.ProductPropertyDO;
@@ -43,7 +44,7 @@ public class ProductSkuDO extends BaseDO {
     /**
      * 属性数组,JSON 格式
      */
-    @TableField(typeHandler = PropertyTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private List<Property> properties;
     /**
      * 商品价格,单位:分
@@ -131,21 +132,6 @@ public class ProductSkuDO extends BaseDO {
 
     }
 
-    // TODO @芋艿:可以找一些新的思路
-    public static class PropertyTypeHandler extends AbstractJsonTypeHandler<Object> {
-
-        @Override
-        protected Object parse(String json) {
-            return JsonUtils.parseArray(json, Property.class);
-        }
-
-        @Override
-        protected String toJson(Object obj) {
-            return JsonUtils.toJsonString(obj);
-        }
-
-    }
-
     // TODO 芋艿:integral from y
     // TODO 芋艿:pinkPrice from y
     // TODO 芋艿:seckillPrice from y

+ 2 - 16
citu-module-mall/citu-module-promotion-biz/src/main/java/com/citu/module/promotion/dal/dataobject/reward/RewardActivityDO.java

@@ -1,5 +1,6 @@
 package com.citu.module.promotion.dal.dataobject.reward;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.framework.common.util.json.JsonUtils;
 import com.citu.framework.mybatis.core.dataobject.BaseDO;
 import com.citu.framework.mybatis.core.type.LongListTypeHandler;
@@ -76,7 +77,7 @@ public class RewardActivityDO extends BaseDO {
     /**
      * 优惠规则的数组
      */
-    @TableField(typeHandler = RuleTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private List<Rule> rules;
 
     /**
@@ -115,19 +116,4 @@ public class RewardActivityDO extends BaseDO {
 
     }
 
-    // TODO @芋艿:可以找一些新的思路
-    public static class RuleTypeHandler extends AbstractJsonTypeHandler<List<Rule>> {
-
-        @Override
-        protected List<Rule> parse(String json) {
-            return JsonUtils.parseArray(json, Rule.class);
-        }
-
-        @Override
-        protected String toJson(List<Rule> obj) {
-            return JsonUtils.toJsonString(obj);
-        }
-
-    }
-
 }

+ 1 - 1
citu-module-mall/citu-module-trade-biz/src/main/java/com/citu/module/trade/dal/dataobject/aftersale/AfterSaleDO.java

@@ -124,7 +124,7 @@ public class AfterSaleDO extends BaseDO {
      *
      * 冗余 {@link TradeOrderItemDO#getProperties()}
      */
-    @TableField(typeHandler = TradeOrderItemDO.PropertyTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private List<TradeOrderItemDO.Property> properties;
     /**
      * 商品图片

+ 2 - 16
citu-module-mall/citu-module-trade-biz/src/main/java/com/citu/module/trade/dal/dataobject/order/TradeOrderItemDO.java

@@ -1,5 +1,6 @@
 package com.citu.module.trade.dal.dataobject.order;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.framework.common.util.json.JsonUtils;
 import com.citu.framework.mybatis.core.dataobject.BaseDO;
 import com.citu.module.trade.dal.dataobject.aftersale.AfterSaleDO;
@@ -74,7 +75,7 @@ public class TradeOrderItemDO extends BaseDO {
      *
      * 冗余 ProductSkuDO 的 properties 字段
      */
-    @TableField(typeHandler = PropertyTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private List<Property> properties;
     /**
      * 商品图片
@@ -210,20 +211,5 @@ public class TradeOrderItemDO extends BaseDO {
 
     }
 
-    // TODO @芋艿:可以找一些新的思路
-    public static class PropertyTypeHandler extends AbstractJsonTypeHandler<List<Property>> {
-
-        @Override
-        protected List<Property> parse(String json) {
-            return JsonUtils.parseArray(json, Property.class);
-        }
-
-        @Override
-        protected String toJson(List<Property> obj) {
-            return JsonUtils.toJsonString(obj);
-        }
-
-    }
-
 }
 

+ 2 - 1
citu-module-mp/citu-module-mp-biz/src/main/java/com/citu/module/mp/controller/admin/message/vo/message/MpMessageRespVO.java

@@ -1,5 +1,6 @@
 package com.citu.module.mp.controller.admin.message.vo.message;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.module.mp.dal.dataobject.message.MpMessageDO;
 import com.baomidou.mybatisplus.annotation.TableField;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -81,7 +82,7 @@ public class MpMessageRespVO {
      *
      * 消息类型为 {@link WxConsts.XmlMsgType} 的 NEWS
      */
-    @TableField(typeHandler = MpMessageDO.ArticleTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private List<MpMessageDO.Article> articles;
 
     @Schema(description = "音乐链接 消息类型为 music 时,才有值", example = "https://www.iocoder.cn/xxx.mp3")

+ 2 - 1
citu-module-mp/citu-module-mp-biz/src/main/java/com/citu/module/mp/dal/dataobject/menu/MpMenuDO.java

@@ -1,5 +1,6 @@
 package com.citu.module.mp.dal.dataobject.menu;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.framework.mybatis.core.dataobject.BaseDO;
 import com.citu.module.mp.dal.dataobject.account.MpAccountDO;
 import com.citu.module.mp.dal.dataobject.message.MpMessageDO;
@@ -163,7 +164,7 @@ public class MpMenuDO extends BaseDO {
      *
      * 消息类型为 {@link WxConsts.XmlMsgType} 的 NEWS
      */
-    @TableField(typeHandler = MpMessageDO.ArticleTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private List<MpMessageDO.Article> replyArticles;
 
     /**

+ 2 - 1
citu-module-mp/citu-module-mp-biz/src/main/java/com/citu/module/mp/dal/dataobject/message/MpAutoReplyDO.java

@@ -1,5 +1,6 @@
 package com.citu.module.mp.dal.dataobject.message;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.framework.common.util.collection.SetUtils;
 import com.citu.framework.mybatis.core.dataobject.BaseDO;
 import com.citu.module.mp.dal.dataobject.account.MpAccountDO;
@@ -143,7 +144,7 @@ public class MpAutoReplyDO extends BaseDO {
      *
      * 消息类型为 {@link WxConsts.XmlMsgType} 的 NEWS
      */
-    @TableField(typeHandler = MpMessageDO.ArticleTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private List<MpMessageDO.Article> responseArticles;
 
     /**

+ 2 - 15
citu-module-mp/citu-module-mp-biz/src/main/java/com/citu/module/mp/dal/dataobject/message/MpMessageDO.java

@@ -1,5 +1,6 @@
 package com.citu.module.mp.dal.dataobject.message;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.framework.common.util.json.JsonUtils;
 import com.citu.framework.mybatis.core.dataobject.BaseDO;
 import com.citu.module.mp.dal.dataobject.account.MpAccountDO;
@@ -173,7 +174,7 @@ public class MpMessageDO extends BaseDO {
      *
      * 消息类型为 {@link WxConsts.XmlMsgType} 的 NEWS
      */
-    @TableField(typeHandler = ArticleTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private List<Article> articles;
 
     /**
@@ -238,18 +239,4 @@ public class MpMessageDO extends BaseDO {
 
     }
 
-    // TODO @芋艿:可以找一些新的思路
-    public static class ArticleTypeHandler extends AbstractJsonTypeHandler<List<Article>> {
-
-        @Override
-        protected List<Article> parse(String json) {
-            return JsonUtils.parseArray(json, Article.class);
-        }
-
-        @Override
-        protected String toJson(List<Article> obj) {
-            return JsonUtils.toJsonString(obj);
-        }
-
-    }
 }

+ 2 - 2
citu-module-report/citu-module-report-biz/pom.xml

@@ -20,8 +20,8 @@
     <dependencies>
         <!-- Spring Cloud 基础 -->
         <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-bootstrap</artifactId>
+            <groupId>com.citu</groupId>
+            <artifactId>citu-spring-boot-starter-env</artifactId>
         </dependency>
 
         <!-- 依赖服务 -->

+ 2 - 2
citu-module-system/citu-module-system-biz/src/main/java/com/citu/module/system/dal/dataobject/permission/RoleDO.java

@@ -1,7 +1,7 @@
 package com.citu.module.system.dal.dataobject.permission;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.framework.common.enums.CommonStatusEnum;
-import com.citu.framework.mybatis.core.type.JsonLongSetTypeHandler;
 import com.citu.module.system.enums.permission.DataScopeEnum;
 import com.citu.framework.tenant.core.db.TenantBaseDO;
 import com.citu.module.system.enums.permission.RoleTypeEnum;
@@ -72,7 +72,7 @@ public class RoleDO extends TenantBaseDO {
      *
      * 适用于 {@link #dataScope} 的值为 {@link DataScopeEnum#DEPT_CUSTOM} 时
      */
-    @TableField(typeHandler = JsonLongSetTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private Set<Long> dataScopeDeptIds;
 
 }

+ 2 - 2
citu-module-system/citu-module-system-biz/src/main/java/com/citu/module/system/dal/dataobject/tenant/TenantPackageDO.java

@@ -1,8 +1,8 @@
 package com.citu.module.system.dal.dataobject.tenant;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.framework.common.enums.CommonStatusEnum;
 import com.citu.framework.mybatis.core.dataobject.BaseDO;
-import com.citu.framework.mybatis.core.type.JsonLongSetTypeHandler;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -46,7 +46,7 @@ public class TenantPackageDO extends BaseDO {
     /**
      * 关联的菜单编号
      */
-    @TableField(typeHandler = JsonLongSetTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private Set<Long> menuIds;
 
 }

+ 2 - 2
citu-module-system/citu-module-system-biz/src/main/java/com/citu/module/system/dal/dataobject/user/AdminUserDO.java

@@ -1,7 +1,7 @@
 package com.citu.module.system.dal.dataobject.user;
 
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.citu.framework.common.enums.CommonStatusEnum;
-import com.citu.framework.mybatis.core.type.JsonLongSetTypeHandler;
 import com.citu.framework.tenant.core.db.TenantBaseDO;
 import com.citu.module.system.enums.common.SexEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
@@ -58,7 +58,7 @@ public class AdminUserDO extends TenantBaseDO {
     /**
      * 岗位编号数组
      */
-    @TableField(typeHandler = JsonLongSetTypeHandler.class)
+    @TableField(typeHandler = JacksonTypeHandler.class)
     private Set<Long> postIds;
     /**
      * 用户邮箱

+ 1 - 1
citu-module-system/citu-module-system-biz/src/main/java/com/citu/module/system/framework/sms/core/client/impl/TencentSmsClient.java

@@ -18,11 +18,11 @@ import com.citu.module.system.framework.sms.core.property.SmsChannelProperties;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.annotations.VisibleForTesting;
-import com.tencentcloudapi.common.DatatypeConverter;
 import lombok.Data;
 
 import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
+import javax.xml.bind.DatatypeConverter;
 import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;

+ 3 - 14
citu-module-system/citu-module-system-biz/src/test/java/com/citu/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java

@@ -1,38 +1,27 @@
 package com.citu.module.system.framework.sms.core.client.impl;
 
-import cn.hutool.core.util.ReflectUtil;
 import com.citu.framework.common.core.KeyValue;
-import com.citu.framework.common.util.collection.MapUtils;
 import com.citu.framework.common.util.http.HttpUtils;
 import com.citu.framework.test.core.ut.BaseMockitoUnitTest;
 import com.citu.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
 import com.citu.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
 import com.citu.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
-import com.citu.module.system.framework.sms.core.client.impl.AliyunSmsClient;
 import com.citu.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
 import com.citu.module.system.framework.sms.core.property.SmsChannelProperties;
-import com.aliyuncs.IAcsClient;
-import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
 import com.google.common.collect.Lists;
 import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentMatcher;
 import org.mockito.InjectMocks;
-import org.mockito.Mock;
 import org.mockito.MockedStatic;
 
 import java.time.LocalDateTime;
 import java.util.List;
 
-import static com.citu.framework.common.util.json.JsonUtils.toJsonString;
-import static com.citu.framework.test.core.util.RandomUtils.*;
+import static com.citu.framework.test.core.util.RandomUtils.randomLongId;
+import static com.citu.framework.test.core.util.RandomUtils.randomString;
 import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.ArgumentMatchers.anyMap;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.when;
 
 /**
  * {@link AliyunSmsClient} 的单元测试

+ 2 - 20
citu-module-system/citu-module-system-biz/src/test/java/com/citu/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java

@@ -1,41 +1,23 @@
 package com.citu.module.system.framework.sms.core.client.impl;
 
 import cn.hutool.core.util.ReflectUtil;
-import com.citu.framework.common.core.KeyValue;
-import com.citu.framework.common.util.collection.ArrayUtils;
-import com.citu.framework.common.util.collection.MapUtils;
-import com.citu.framework.common.util.json.JsonUtils;
 import com.citu.framework.test.core.ut.BaseMockitoUnitTest;
+import com.citu.module.system.framework.sms.core.client.SmsClient;
 import com.citu.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
-import com.citu.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
-import com.citu.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
 import com.citu.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
 import com.citu.module.system.framework.sms.core.property.SmsChannelProperties;
-import com.google.common.collect.Lists;
-import com.tencentcloudapi.common.AbstractModel;
-import com.tencentcloudapi.common.Credential;
-import com.tencentcloudapi.common.exception.TencentCloudSDKException;
-import com.tencentcloudapi.common.profile.ClientProfile;
-import com.tencentcloudapi.common.profile.HttpProfile;
-import com.tencentcloudapi.sms.v20210111.SmsClient;
-import com.tencentcloudapi.sms.v20210111.models.*;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
 import java.time.LocalDateTime;
-import java.util.ArrayList;
 import java.util.List;
 
-import static cn.hutool.core.util.RandomUtil.randomLong;
-import static com.citu.framework.common.util.json.JsonUtils.toJsonString;
-import static com.citu.framework.test.core.util.RandomUtils.*;
 import static com.citu.framework.test.core.util.RandomUtils.randomString;
 import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.Mockito.when;
 
 // TODO @芋艿:补全单测
+
 /**
  * {@link TencentSmsClient} 的单元测试
  *

+ 2 - 2
pom.xml

@@ -30,9 +30,9 @@
     <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
 
     <properties>
-        <revision>2.1.0-snapshot</revision>
+        <revision>2.2.0-snapshot</revision>
         <!-- Maven 相关 -->
-        <java.version>1.8</java.version>
+        <java.version>11</java.version>
         <maven.compiler.source>${java.version}</maven.compiler.source>
         <maven.compiler.target>${java.version}</maven.compiler.target>
         <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>