diff --git a/pom.xml b/pom.xml index e5986837e..7e7fd216c 100644 --- a/pom.xml +++ b/pom.xml @@ -32,8 +32,8 @@ 3.0.0-M5 3.8.0 - 1.18.20 - 1.4.1.Final + 1.18.24 + 1.5.3.Final UTF-8 diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 3bf41dcc8..12528e327 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -16,19 +16,19 @@ 1.6.2-snapshot - 2.6.9 + 2.6.13 2021.0.1 2021.0.1.0 3.0.3 - 1.6.6 + 1.6.7 2.5 - 1.2.11 - 3.4.3.4 + 1.2.14 + 3.5.2 3.5.2 - 3.5.0 - 3.17.3 + 3.5.2 + 3.17.7 2.7.15 @@ -36,37 +36,38 @@ 2.3.1 - 2.2.0 + 2.2.2 1.7.1 - 8.7.0 - 2.6.7 - 0.31.0 + 8.12.0 + 2.6.9 + 0.33.0 - 7.2.6.RELEASE - 0.1.16 - 4.0.0 + 7.2.9.RELEASE + 1.0.4 + 4.8.0 6.7.2 3.0.4 - 1.18.20 - 1.4.1.Final - 5.8.5 - 2.2.7 + 1.18.24 + 1.5.3.Final + 5.8.9 + 3.1.2 2.3 1.0.5 - 2.0.5 + 1.2.83 30.1.1-jre 5.1.0 - 2.12.2 + 2.14.0 3.8.0 0.1.55 - 2.4.1 + 2.5.0 1.3.0 + 4.1.82.Final 8.2.2 - 4.6.0 + 4.6.2 2.2.1 3.1.561 1.2.7 @@ -563,6 +564,12 @@ ${jsch.version} + + io.netty + netty-all + ${netty-all.version} + + cn.iocoder.cloud diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml index dc0c7459b..23ce31370 100644 --- a/yudao-framework/yudao-common/pom.xml +++ b/yudao-framework/yudao-common/pom.xml @@ -105,6 +105,11 @@ jackson-core provided + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + provided + org.slf4j diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DocumentEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DocumentEnum.java index b304462e5..0d2c64c8b 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DocumentEnum.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DocumentEnum.java @@ -12,8 +12,9 @@ import lombok.Getter; @AllArgsConstructor public enum DocumentEnum { - REDIS_INSTALL("https://gitee.com/zhijiantianya/ruoyi-vue-pro/issues/I4VCSJ", "Redis 安装文档"); - + REDIS_INSTALL("https://gitee.com/zhijiantianya/ruoyi-vue-pro/issues/I4VCSJ", "Redis 安装文档"), + TENANT("https://doc.iocoder.cn", "SaaS 多租户文档"); + private final String url; private final String memo; diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java index 97fe67f61..a1d96464b 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java @@ -1,8 +1,9 @@ package cn.iocoder.yudao.framework.common.util.date; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; -import java.time.Duration; +import java.time.*; import java.util.Calendar; import java.util.Date; @@ -25,6 +26,34 @@ public class DateUtils { public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss"; + /** + * 将 LocalDateTime 转换成 Date + * + * @param date LocalDateTime + * @return LocalDateTime + */ + public static Date of(LocalDateTime date) { + // 将此日期时间与时区相结合以创建 ZonedDateTime + ZonedDateTime zonedDateTime = date.atZone(ZoneId.systemDefault()); + // 本地时间线 LocalDateTime 到即时时间线 Instant 时间戳 + Instant instant = zonedDateTime.toInstant(); + // UTC时间(世界协调时间,UTC + 00:00)转北京(北京,UTC + 8:00)时间 + return Date.from(instant); + } + + /** + * 将 Date 转换成 LocalDateTime + * + * @param date Date + * @return LocalDateTime + */ + public static LocalDateTime of(Date date) { + // 转为时间戳 + Instant instant = date.toInstant(); + // UTC时间(世界协调时间,UTC + 00:00)转北京(北京,UTC + 8:00)时间 + return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + } + public static Date addTime(Duration duration) { return new Date(System.currentTimeMillis() + duration.toMillis()); } @@ -33,6 +62,11 @@ public class DateUtils { return System.currentTimeMillis() > time.getTime(); } + public static boolean isExpired(LocalDateTime time) { + LocalDateTime now = LocalDateTime.now(); + return now.isAfter(time); + } + public static long diff(Date endTime, Date startTime) { return endTime.getTime() - startTime.getTime(); } @@ -40,24 +74,28 @@ public class DateUtils { /** * 创建指定时间 * - * @param year 年 - * @param mouth 月 - * @param day 日 + * @param year 年 + * @param mouth 月 + * @param day 日 * @return 指定时间 */ public static Date buildTime(int year, int mouth, int day) { return buildTime(year, mouth, day, 0, 0, 0); } + public static LocalDateTime buildLocalDateTime(int year, int mouth, int day) { + return LocalDateTime.of(year, mouth, day, 0, 0, 0); + } + /** * 创建指定时间 * - * @param year 年 - * @param mouth 月 - * @param day 日 - * @param hour 小时 - * @param minute 分钟 - * @param second 秒 + * @param year 年 + * @param mouth 月 + * @param day 日 + * @param hour 小时 + * @param minute 分钟 + * @param second 秒 * @return 指定时间 */ public static Date buildTime(int year, int mouth, int day, @@ -83,6 +121,16 @@ public class DateUtils { return a.compareTo(b) > 0 ? a : b; } + public static LocalDateTime max(LocalDateTime a, LocalDateTime b) { + if (a == null) { + return b; + } + if (b == null) { + return a; + } + return a.isAfter(b) ? a : b; + } + public static boolean beforeNow(Date date) { return date.getTime() < System.currentTimeMillis(); } @@ -91,6 +139,10 @@ public class DateUtils { return date.getTime() >= System.currentTimeMillis(); } + public static boolean afterNow(LocalDateTime localDateTime) { + return localDateTime.isAfter(LocalDateTime.now()); + } + /** * 计算当期时间相差的日期 * @@ -135,4 +187,14 @@ public class DateUtils { return DateUtil.isSameDay(date, new Date()); } + /** + * 是否今天 + * + * @param date 日期 + * @return 是否 + */ + public static boolean isToday(LocalDateTime date) { + return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now()); + } + } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java index 0be190942..86d220638 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; @@ -28,6 +29,7 @@ public class JsonUtils { static { objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化 } /** diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java index a9a4d24d4..5fc4e55d0 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java @@ -18,7 +18,6 @@ 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.expression.operators.relational.ItemsList; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.delete.Delete; import net.sf.jsqlparser.statement.select.*; @@ -37,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap; /** * 数据权限拦截器,通过 {@link DataPermissionRule} 数据权限规则,重写 SQL 的方式来实现 - * 主要的 SQL 重写方法,可见 {@link #builderExpression(Expression, Table)} 方法 + * 主要的 SQL 重写方法,可见 {@link #builderExpression(Expression, List)} 方法 * * 整体的代码实现上,参考 {@link com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor} 实现。 * 所以每次 MyBatis Plus 升级时,需要 Review 下其具体的实现是否有变更! @@ -53,8 +52,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme private final MappedStatementCache mappedStatementCache = new MappedStatementCache(); @Override // SELECT 场景 - public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, - RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { + public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { // 获得 Mapper 对应的数据权限的规则 List rules = ruleFactory.getDataPermissionRule(ms.getId()); if (mappedStatementCache.noRewritable(ms, rules)) { // 如果无需重写,则跳过 @@ -68,12 +66,14 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme // 处理 SQL mpBs.sql(parserSingle(mpBs.sql(), null)); } finally { + // 添加是否需要重写的缓存 addMappedStatementCache(ms); + // 清空上下文 ContextHolder.clear(); } } - @Override // 只处理 UPDATE / DELETE 场景,不处理 INSERT 场景 + @Override // 只处理 UPDATE / DELETE 场景,不处理 INSERT 场景(因为 INSERT 不需要数据权限) public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) { PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh); MappedStatement ms = mpSh.mappedStatement(); @@ -92,7 +92,9 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme // 处理 SQL mpBs.sql(parserMulti(mpBs.sql(), null)); } finally { + // 添加是否需要重写的缓存 addMappedStatementCache(ms); + // 清空上下文 ContextHolder.clear(); } } @@ -107,24 +109,6 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme } } - 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 selectBodys = operationList.getSelects(); - if (CollectionUtils.isNotEmpty(selectBodys)) { - selectBodys.forEach(this::processSelectBody); - } - } - } - /** * update 语句处理 */ @@ -142,28 +126,77 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme 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 selectBodyList = operationList.getSelects(); + if (CollectionUtils.isNotEmpty(selectBodyList)) { + selectBodyList.forEach(this::processSelectBody); + } + } + } + /** * 处理 PlainSelect */ protected void processPlainSelect(PlainSelect plainSelect) { - FromItem fromItem = plainSelect.getFromItem(); - Expression where = plainSelect.getWhere(); - processWhereSubSelect(where); - if (fromItem instanceof Table) { - Table fromTable = (Table) fromItem; - plainSelect.setWhere(builderExpression(where, fromTable)); - } else { - processFromItem(fromItem); - } //#3087 github List selectItems = plainSelect.getSelectItems(); if (CollectionUtils.isNotEmpty(selectItems)) { selectItems.forEach(this::processSelectItem); } + + // 处理 where 中的子查询 + Expression where = plainSelect.getWhere(); + processWhereSubSelect(where); + + // 处理 fromItem + FromItem fromItem = plainSelect.getFromItem(); + List list = processFromItem(fromItem); + List
mainTables = new ArrayList<>(list); + + // 处理 join List joins = plainSelect.getJoins(); if (CollectionUtils.isNotEmpty(joins)) { - processJoins(joins); + mainTables = processJoins(mainTables, joins); } + + // 当有 mainTable 时,进行 where 条件追加 + if (CollectionUtils.isNotEmpty(mainTables)) { + plainSelect.setWhere(builderExpression(where, mainTables)); + } + } + + private List
processFromItem(FromItem fromItem) { + // 处理括号括起来的表达式 + while (fromItem instanceof ParenthesisFromItem) { + fromItem = ((ParenthesisFromItem) fromItem).getFromItem(); + } + + List
mainTables = new ArrayList<>(); + // 无 join 时的处理逻辑 + if (fromItem instanceof Table) { + Table fromTable = (Table) fromItem; + mainTables.add(fromTable); + } else if (fromItem instanceof SubJoin) { + // SubJoin 类型则还需要添加上 where 条件 + List
tables = processSubJoin((SubJoin) fromItem); + mainTables.addAll(tables); + } else { + // 处理下 fromItem + processOtherFromItem(fromItem); + } + return mainTables; } /** @@ -191,7 +224,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme return; } if (where instanceof FromItem) { - processFromItem((FromItem) where); + processOtherFromItem((FromItem) where); return; } if (where.toString().indexOf("SELECT") > 0) { @@ -204,9 +237,9 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme } else if (where instanceof InExpression) { // in InExpression expression = (InExpression) where; - ItemsList itemsList = expression.getRightItemsList(); - if (itemsList instanceof SubSelect) { - processSelectBody(((SubSelect) itemsList).getSelectBody()); + Expression inExpression = expression.getRightExpression(); + if (inExpression instanceof SubSelect) { + processSelectBody(((SubSelect) inExpression).getSelectBody()); } } else if (where instanceof ExistsExpression) { // exists @@ -239,7 +272,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme *

支持: 1. select fun(args..) 2. select fun1(fun2(args..),args..)

*

fixed gitee pulls/141

* - * @param function 函数 + * @param function */ protected void processFunction(Function function) { ExpressionList parameters = function.getParameters(); @@ -257,22 +290,19 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme /** * 处理子查询等 */ - protected void processFromItem(FromItem fromItem) { - if (fromItem instanceof SubJoin) { - SubJoin subJoin = (SubJoin) fromItem; - if (subJoin.getJoinList() != null) { - processJoins(subJoin.getJoinList()); - } - if (subJoin.getLeft() != null) { - processFromItem(subJoin.getLeft()); - } - } else if (fromItem instanceof SubSelect) { + 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"); + 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) { @@ -284,75 +314,176 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme } } + /** + * 处理 sub join + * + * @param subJoin subJoin + * @return Table subJoin 中的主表 + */ + private List
processSubJoin(SubJoin subJoin) { + List
mainTables = new ArrayList<>(); + if (subJoin.getJoinList() != null) { + List
list = processFromItem(subJoin.getLeft()); + mainTables.addAll(list); + mainTables = processJoins(mainTables, subJoin.getJoinList()); + } + return mainTables; + } + /** * 处理 joins * - * @param joins join 集合 + * @param mainTables 可以为 null + * @param joins join 集合 + * @return List
右连接查询的 Table 列表 */ - private void processJoins(List joins) { + private List
processJoins(List
mainTables, List 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
tables = new LinkedList<>(); + Deque> onTableDeque = new LinkedList<>(); for (Join join : joins) { // 处理 on 表达式 - FromItem fromItem = join.getRightItem(); - if (fromItem instanceof Table) { - Table fromTable = (Table) fromItem; + FromItem joinItem = join.getRightItem(); + + // 获取当前 join 的表,subJoint 可以看作是一张表 + List
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
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 originOnExpressions = join.getOnExpressions(); // 正常 join on 表达式只有一个,立刻处理 - if (originOnExpressions.size() == 1) { - processJoin(join); + if (originOnExpressions.size() == 1 && onTables != null) { + List onExpressions = new LinkedList<>(); + onExpressions.add(builderExpression(originOnExpressions.iterator().next(), onTables)); + join.setOnExpressions(onExpressions); + leftTable = joinTable; continue; } - tables.push(fromTable); + // 表名压栈,忽略的表压入 null,以便后续不处理 + onTableDeque.push(onTables); // 尾缀多个 on 表达式的时候统一处理 if (originOnExpressions.size() > 1) { Collection onExpressions = new LinkedList<>(); for (Expression originOnExpression : originOnExpressions) { - Table currentTable = tables.poll(); - onExpressions.add(builderExpression(originOnExpression, currentTable)); + List
currentTableList = onTableDeque.poll(); + if (CollectionUtils.isEmpty(currentTableList)) { + onExpressions.add(originOnExpression); + } else { + onExpressions.add(builderExpression(originOnExpression, currentTableList)); + } } join.setOnExpressions(onExpressions); } + leftTable = joinTable; } else { - // 处理右边连接的子表达式 - processFromItem(fromItem); + processOtherFromItem(joinItem); + leftTable = null; } } + + return mainTables; } + // ========== 和 TenantLineInnerInterceptor 存在差异的逻辑:关键,实现权限条件的拼接 ========== + /** - * 处理联接语句 + * 处理条件 + * + * @param currentExpression 当前 where 条件 + * @param table 单个表 */ - protected void processJoin(Join join) { - if (join.getRightItem() instanceof Table) { - Table fromTable = (Table) join.getRightItem(); - Expression originOnExpression = CollUtil.getFirst(join.getOnExpressions()); - originOnExpression = builderExpression(originOnExpression, fromTable); - join.setOnExpressions(CollUtil.newArrayList(originOnExpression)); - } + protected Expression builderExpression(Expression currentExpression, Table table) { + return this.builderExpression(currentExpression, Collections.singletonList(table)); } /** * 处理条件 + * + * @param currentExpression 当前 where 条件 + * @param tables 多个表 */ - protected Expression builderExpression(Expression currentExpression, Table table) { - // 获得 Table 对应的数据权限条件 - Expression equalsTo = buildDataPermissionExpression(table); - if (equalsTo == null) { // 如果没条件,则返回 currentExpression 默认 + protected Expression builderExpression(Expression currentExpression, List
tables) { + // 没有表需要处理直接返回 + if (CollectionUtils.isEmpty(tables)) { return currentExpression; } - // 表达式为空,则直接返回 equalsTo + // 第一步,获得 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 equalsTo; + return dataPermissionExpression; } - // 如果表达式为 Or,则需要 (currentExpression) AND equalsTo + // ① 如果表达式为 Or,则需要 (currentExpression) AND dataPermissionExpression if (currentExpression instanceof OrExpression) { - return new AndExpression(new Parenthesis(currentExpression), equalsTo); + return new AndExpression(new Parenthesis(currentExpression), dataPermissionExpression); } - // 如果表达式为 And,则直接返回 currentExpression AND equalsTo - return new AndExpression(currentExpression, equalsTo); + // ② 如果表达式为 And,则直接返回 where AND dataPermissionExpression + return new AndExpression(currentExpression, dataPermissionExpression); } /** diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java index 85067439e..0e4b91691 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRule; @@ -106,7 +105,7 @@ public class DeptDataPermissionRule implements DataPermissionRule { DeptDataPermissionRespDTO deptDataPermission = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class); // 从上下文中拿不到,则调用逻辑进行获取 if (deptDataPermission == null) { - deptDataPermission = permissionApi.getDeptDataPermission(loginUser.getId()).getData(); + deptDataPermission = permissionApi.getDeptDataPermission(loginUser.getId()).getCheckedData(); if (deptDataPermission == null) { log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser)); throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限", diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest.java index 4c1494aca..145360789 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest.java @@ -87,7 +87,7 @@ public class DataPermissionDatabaseInterceptorTest extends BaseMockitoUnitTest { interceptor.beforeQuery(null, mappedStatement, null, null, null, boundSql); // 断言 verify(mpBs, times(1)).sql( - eq("SELECT * FROM t_user WHERE id = 1 AND dept_id = 100")); + eq("SELECT * FROM t_user WHERE id = 1 AND t_user.dept_id = 100")); // 断言缓存 assertTrue(interceptor.getMappedStatementCache().getNoRewritableMappedStatements().isEmpty()); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest2.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest2.java index 8c0772f1a..6e42d52f4 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest2.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest2.java @@ -46,7 +46,7 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest @Override public Set getTableNames() { - return asSet("entity", "entity1", "entity2", "t1", "t2", // 支持 MyBatis Plus 的单元测试 + return asSet("entity", "entity1", "entity2", "entity3", "t1", "t2", "sys_dict_item", // 支持 MyBatis Plus 的单元测试 "t_user", "t_role"); // 满足自己的单元测试 } @@ -84,30 +84,30 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest @Test void delete() { assertSql("delete from entity where id = ?", - "DELETE FROM entity WHERE id = ? AND tenant_id = 1"); + "DELETE FROM entity WHERE id = ? AND entity.tenant_id = 1"); } @Test void update() { assertSql("update entity set name = ? where id = ?", - "UPDATE entity SET name = ? WHERE id = ? AND tenant_id = 1"); + "UPDATE entity SET name = ? WHERE id = ? AND entity.tenant_id = 1"); } @Test void selectSingle() { // 单表 assertSql("select * from entity where id = ?", - "SELECT * FROM entity WHERE id = ? AND tenant_id = 1"); + "SELECT * FROM entity WHERE id = ? AND entity.tenant_id = 1"); assertSql("select * from entity where id = ? or name = ?", - "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1"); + "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1"); assertSql("SELECT * FROM entity WHERE (id = ? OR name = ?)", - "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1"); + "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1"); /* not */ assertSql("SELECT * FROM entity WHERE not (id = ? OR name = ?)", - "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND tenant_id = 1"); + "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND entity.tenant_id = 1"); } @Test @@ -167,10 +167,12 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest assertSql("SELECT * FROM entity e WHERE e.id >= (select e1.id from entity1 e1 where e1.id = ?)", "SELECT * FROM entity e WHERE e.id >= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); + /* <= */ assertSql("SELECT * FROM entity e WHERE e.id <= (select e1.id from entity1 e1 where e1.id = ?)", "SELECT * FROM entity e WHERE e.id <= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); + /* <> */ assertSql("SELECT * FROM entity e WHERE e.id <> (select e1.id from entity1 e1 where e1.id = ?)", "SELECT * FROM entity e WHERE e.id <> (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); @@ -204,6 +206,14 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest "SELECT * FROM entity e " + "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); + + assertSql("SELECT * FROM entity e " + + "left join entity1 e1 on e1.id = e.id " + + "left 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 " + + "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " + + "WHERE e.tenant_id = 1"); } @Test @@ -212,17 +222,125 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest assertSql("SELECT * FROM entity e " + "right join entity1 e1 on e1.id = e.id", "SELECT * FROM entity e " + - "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE e.tenant_id = 1"); + "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " + + "WHERE e1.tenant_id = 1"); + + assertSql("SELECT * FROM with_as_1 e " + + "right join entity1 e1 on e1.id = e.id", + "SELECT * FROM with_as_1 e " + + "RIGHT JOIN entity1 e1 ON e1.id = e.id " + + "WHERE e1.tenant_id = 1"); assertSql("SELECT * FROM entity e " + "right join entity1 e1 on e1.id = e.id " + "WHERE e.id = ? OR e.name = ?", "SELECT * FROM entity e " + - "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); + "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " + + "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1"); + + assertSql("SELECT * FROM entity e " + + "right join entity1 e1 on e1.id = e.id " + + "right join entity2 e2 on e1.id = e2.id ", + "SELECT * FROM entity e " + + "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " + + "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1 " + + "WHERE e2.tenant_id = 1"); } + @Test + void selectMixJoin() { + assertSql("SELECT * FROM entity e " + + "right join entity1 e1 on e1.id = e.id " + + "left join entity2 e2 on e1.id = e2.id", + "SELECT * FROM entity e " + + "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " + + "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " + + "WHERE e1.tenant_id = 1"); + + assertSql("SELECT * FROM entity e " + + "left join entity1 e1 on e1.id = e.id " + + "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 " + + "WHERE e2.tenant_id = 1"); + + assertSql("SELECT * FROM entity e " + + "left join entity1 e1 on e1.id = e.id " + + "inner 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 " + + "INNER JOIN entity2 e2 ON e1.id = e2.id AND e.tenant_id = 1 AND e2.tenant_id = 1"); + } + + + @Test + void selectJoinSubSelect() { + assertSql("select * from (select * from entity) e1 " + + "left join entity2 e2 on e1.id = e2.id", + "SELECT * FROM (SELECT * FROM entity WHERE entity.tenant_id = 1) e1 " + + "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1"); + + assertSql("select * from entity1 e1 " + + "left join (select * from entity2) e2 " + + "on e1.id = e2.id", + "SELECT * FROM entity1 e1 " + + "LEFT JOIN (SELECT * FROM entity2 WHERE entity2.tenant_id = 1) e2 " + + "ON e1.id = e2.id " + + "WHERE e1.tenant_id = 1"); + } + + @Test + void selectSubJoin() { + + assertSql("select * FROM " + + "(entity1 e1 right JOIN entity2 e2 ON e1.id = e2.id)", + "SELECT * FROM " + + "(entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " + + "WHERE e2.tenant_id = 1"); + + assertSql("select * FROM " + + "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id)", + "SELECT * FROM " + + "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " + + "WHERE e1.tenant_id = 1"); + + + assertSql("select * FROM " + + "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id) " + + "right join entity3 e3 on e1.id = e3.id", + "SELECT * FROM " + + "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " + + "RIGHT JOIN entity3 e3 ON e1.id = e3.id AND e1.tenant_id = 1 " + + "WHERE e3.tenant_id = 1"); + + + assertSql("select * FROM entity e " + + "LEFT JOIN (entity1 e1 right join entity2 e2 ON e1.id = e2.id) " + + "on e.id = e2.id", + "SELECT * FROM entity e " + + "LEFT JOIN (entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " + + "ON e.id = e2.id AND e2.tenant_id = 1 " + + "WHERE e.tenant_id = 1"); + + assertSql("select * FROM entity e " + + "LEFT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " + + "on e.id = e2.id", + "SELECT * FROM entity e " + + "LEFT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " + + "ON e.id = e2.id AND e1.tenant_id = 1 " + + "WHERE e.tenant_id = 1"); + + assertSql("select * FROM entity e " + + "RIGHT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " + + "on e.id = e2.id", + "SELECT * FROM entity e " + + "RIGHT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " + + "ON e.id = e2.id AND e.tenant_id = 1 " + + "WHERE e1.tenant_id = 1"); + } + + @Test void selectLeftJoinMultipleTrailingOn() { // 多个 on 尾缀的 @@ -256,51 +374,97 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest "inner join entity1 e1 on e1.id = e.id " + "WHERE e.id = ? OR e.name = ?", "SELECT * FROM entity e " + - "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); + "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " + + "WHERE e.id = ? OR e.name = ?"); assertSql("SELECT * FROM entity e " + "inner join entity1 e1 on e1.id = e.id " + "WHERE (e.id = ? OR e.name = ?)", "SELECT * FROM entity e " + - "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); + "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " + + "WHERE (e.id = ? OR e.name = ?)"); + + // 隐式内连接 + 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"); + + // 隐式内连接 + assertSql("SELECT * FROM entity a, with_as_entity1 b " + + "WHERE a.id = b.id", + "SELECT * FROM entity a, with_as_entity1 b " + + "WHERE a.id = b.id AND a.tenant_id = 1"); + + assertSql("SELECT * FROM with_as_entity a, with_as_entity1 b " + + "WHERE a.id = b.id", + "SELECT * FROM with_as_entity a, with_as_entity1 b " + + "WHERE a.id = b.id"); + + // SubJoin with 隐式内连接 + 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"); + + assertSql("SELECT * FROM ((entity,entity1),entity2) " + + "WHERE entity.id = entity1.id and entity.id = entity2.id", + "SELECT * FROM ((entity, entity1), entity2) " + + "WHERE entity.id = entity1.id AND entity.id = entity2.id " + + "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1"); + + assertSql("SELECT * FROM (entity,(entity1,entity2)) " + + "WHERE entity.id = entity1.id and entity.id = entity2.id", + "SELECT * FROM (entity, (entity1, entity2)) " + + "WHERE entity.id = entity1.id AND entity.id = entity2.id " + + "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1"); + + // 沙雕的括号写法 + 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"); - // 垃圾 inner join todo -// assertSql("SELECT * FROM entity,entity1 " + -// "WHERE entity.id = entity1.id", -// "SELECT * FROM entity e " + -// "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + -// "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); } + @Test void selectWithAs() { assertSql("with with_as_A as (select * from entity) select * from with_as_A", - "WITH with_as_A AS (SELECT * FROM entity WHERE tenant_id = 1) SELECT * FROM with_as_A"); + "WITH with_as_A AS (SELECT * FROM entity WHERE entity.tenant_id = 1) SELECT * FROM with_as_A"); + } + + + @Test + void selectIgnoreTable() { + assertSql(" SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)", + "SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id AND item.tenant_id = 1 WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)"); } private void assertSql(String sql, String targetSql) { assertEquals(targetSql, interceptor.parserSingle(sql, null)); } + // ========== 额外的测试 ========== @Test public void testSelectSingle() { // 单表 assertSql("select * from t_user where id = ?", - "SELECT * FROM t_user WHERE id = ? AND tenant_id = 1 AND dept_id IN (10, 20)"); + "SELECT * FROM t_user WHERE id = ? AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)"); assertSql("select * from t_user where id = ? or name = ?", - "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND tenant_id = 1 AND dept_id IN (10, 20)"); + "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)"); assertSql("SELECT * FROM t_user WHERE (id = ? OR name = ?)", - "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND tenant_id = 1 AND dept_id IN (10, 20)"); + "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)"); /* not */ assertSql("SELECT * FROM t_user WHERE not (id = ? OR name = ?)", - "SELECT * FROM t_user WHERE NOT (id = ? OR name = ?) AND tenant_id = 1 AND dept_id IN (10, 20)"); + "SELECT * FROM t_user WHERE NOT (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)"); } @Test @@ -329,16 +493,16 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest "right join t_role e1 on e1.id = e.id " + "WHERE e.id = ? OR e.name = ?", "SELECT * FROM t_user e " + - "RIGHT JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)"); + "RIGHT JOIN t_role e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) " + + "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1"); // 条件 e.id = ? OR e.name = ? 带括号 assertSql("SELECT * FROM t_user e " + "right join t_role e1 on e1.id = e.id " + "WHERE (e.id = ? OR e.name = ?)", "SELECT * FROM t_user e " + - "RIGHT JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)"); + "RIGHT JOIN t_role e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) " + + "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1"); } @Test @@ -348,23 +512,22 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest "inner join entity1 e1 on e1.id = e.id " + "WHERE e.id = ? OR e.name = ?", "SELECT * FROM t_user e " + - "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)"); + "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) AND e1.tenant_id = 1 " + + "WHERE e.id = ? OR e.name = ?"); // 条件 e.id = ? OR e.name = ? 带括号 assertSql("SELECT * FROM t_user e " + - "inner join t_role e1 on e1.id = e.id " + + "inner join entity1 e1 on e1.id = e.id " + "WHERE (e.id = ? OR e.name = ?)", "SELECT * FROM t_user e " + - "INNER JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)"); + "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) AND e1.tenant_id = 1 " + + "WHERE (e.id = ? OR e.name = ?)"); - // 垃圾 inner join todo -// assertSql("SELECT * FROM entity,entity1 " + -// "WHERE entity.id = entity1.id", -// "SELECT * FROM entity e " + -// "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + -// "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); + // 没有 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"); } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java index bfbb5f9da..b9622fa0f 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java @@ -3,13 +3,12 @@ package cn.iocoder.yudao.framework.datapermission.core.rule.dept; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ReflectUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; -import cn.iocoder.yudao.module.system.api.permission.PermissionApi; -import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import org.junit.jupiter.api.BeforeEach; @@ -25,6 +24,7 @@ import static cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataP import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; @@ -75,6 +75,8 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest { LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L) .setUserType(UserTypeEnum.ADMIN.getValue())); securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser); + // mock 方法(permissionApi 返回 null) + when(permissionApi.getDeptDataPermission(eq(loginUser.getId()))).thenReturn(success(null)); // 调用 NullPointerException exception = assertThrows(NullPointerException.class, diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java index da8a60152..870c74f11 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java @@ -10,7 +10,7 @@ import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Scheduled; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; /** @@ -41,7 +41,7 @@ public class ErrorCodeLoaderImpl implements ErrorCodeLoader { /** * 缓存错误码的最大更新时间,用于后续的增量轮询,判断是否有更新 */ - private Date maxUpdateTime; + private LocalDateTime maxUpdateTime; @EventListener(ApplicationReadyEvent.class) public void loadErrorCodes() { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java index d3b94d25a..75819cbe1 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.operatelog.core.aop; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; @@ -32,6 +33,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.annotation.Annotation; import java.lang.reflect.Array; +import java.time.LocalDateTime; import java.util.*; import java.util.function.Predicate; import java.util.stream.IntStream; @@ -94,7 +96,7 @@ public class OperateLogAspect { } // 记录开始时间 - Date startTime = new Date(); + LocalDateTime startTime = LocalDateTime.now(); try { // 执行原有方法 Object result = joinPoint.proceed(); @@ -128,7 +130,7 @@ public class OperateLogAspect { private void log(ProceedingJoinPoint joinPoint, cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog, ApiOperation apiOperation, - Date startTime, Object result, Throwable exception) { + LocalDateTime startTime, Object result, Throwable exception) { try { // 判断不记录的情况 if (!isLogEnable(joinPoint, operateLog)) { @@ -145,7 +147,7 @@ public class OperateLogAspect { private void log0(ProceedingJoinPoint joinPoint, cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog, ApiOperation apiOperation, - Date startTime, Object result, Throwable exception) { + LocalDateTime startTime, Object result, Throwable exception) { OperateLog operateLogObj = new OperateLog(); // 补全通用字段 operateLogObj.setTraceId(TracerUtils.getTraceId()); @@ -226,7 +228,7 @@ public class OperateLogAspect { private static void fillMethodFields(OperateLog operateLogObj, ProceedingJoinPoint joinPoint, cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog, - Date startTime, Object result, Throwable exception) { + LocalDateTime startTime, Object result, Throwable exception) { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); operateLogObj.setJavaMethod(methodSignature.toString()); if (operateLog == null || operateLog.logArgs()) { @@ -235,7 +237,7 @@ public class OperateLogAspect { if (operateLog == null || operateLog.logResultData()) { operateLogObj.setResultData(obtainResultData(result)); } - operateLogObj.setDuration((int) (System.currentTimeMillis() - startTime.getTime())); + operateLogObj.setDuration((int) (LocalDateTimeUtil.between(startTime, LocalDateTime.now()).toMillis())); // (正常)处理 resultCode 和 resultMsg 字段 if (result instanceof CommonResult) { CommonResult commonResult = (CommonResult) result; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLog.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLog.java index 7bce1c6bd..1e3b8c8a8 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLog.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLog.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.framework.operatelog.core.service; import lombok.Data; -import java.util.Date; +import java.time.LocalDateTime; import java.util.Map; /** @@ -85,7 +85,7 @@ public class OperateLog { /** * 开始时间 */ - private Date startTime; + private LocalDateTime startTime; /** * 执行时长,单位:毫秒 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderNotifyRespDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderNotifyRespDTO.java index a5c24c24e..91f3b2a37 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderNotifyRespDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderNotifyRespDTO.java @@ -5,7 +5,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import java.util.Date; +import java.time.LocalDateTime; /** * 支付通知 Response DTO @@ -33,7 +33,7 @@ public class PayOrderNotifyRespDTO { /** * 支付成功时间 */ - private Date successTime; + private LocalDateTime successTime; /** * 通知的原始数据 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java index 6f99bb80d..ea3628931 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java @@ -7,7 +7,7 @@ import org.hibernate.validator.constraints.URL; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; import java.util.Map; /** @@ -68,7 +68,7 @@ public class PayOrderUnifiedReqDTO { * 支付过期时间 */ @NotNull(message = "支付过期时间不能为空") - private Date expireTime; + private LocalDateTime expireTime; // ========== 拓展参数 ========== /** diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundNotifyDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundNotifyDTO.java index 05fcff3c1..edb593d82 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundNotifyDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundNotifyDTO.java @@ -5,7 +5,7 @@ import lombok.Builder; import lombok.Data; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; /** * 从渠道返回数据中解析得到的支付退款通知的Notify DTO @@ -57,7 +57,7 @@ public class PayRefundNotifyDTO { /** * 退款成功时间 */ - private Date refundSuccessTime; + private LocalDateTime refundSuccessTime; } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedRespDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedRespDTO.java index d2e280ae5..cedf0020d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedRespDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedRespDTO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.framework.pay.core.client.dto; -import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRefundRespEnum; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java index aefb3ba3b..421dbfe7d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; +import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPcPayClient; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayQrPayClient; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayWapPayClient; import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXLitePayClient; @@ -69,7 +70,7 @@ public class PayClientFactoryImpl implements PayClientFactory { case ALIPAY_WAP: return (AbstractPayClient) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config); case ALIPAY_QR: return (AbstractPayClient) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config); case ALIPAY_APP: return (AbstractPayClient) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config); - case ALIPAY_PC: return (AbstractPayClient) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config); + case ALIPAY_PC: return (AbstractPayClient) new AlipayPcPayClient(channelId, (AlipayPayClientConfig) config); } // 创建失败,错误日志 + 抛出异常 log.error("[createPayClient][配置({}) 找不到合适的客户端实现]", config); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClient.java index 41c473be7..680d80d77 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClient.java @@ -1,8 +1,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.date.DateUtil; -import cn.hutool.http.HttpUtil; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping; import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; import cn.iocoder.yudao.framework.pay.core.client.dto.*; @@ -61,7 +60,7 @@ public abstract class AbstractAlipayClient extends AbstractPayClient doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { + // 构建 AlipayTradePagePayModel 请求 + AlipayTradePagePayModel model = new AlipayTradePagePayModel(); + // 构建 AlipayTradePagePayRequest + AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); + request.setBizModel(model); + JSONObject bizContent = new JSONObject(); + // 参数说明可查看: https://opendocs.alipay.com/open/028r8t?scene=22 + bizContent.put("out_trade_no", reqDTO.getMerchantOrderId()); + bizContent.put("total_amount", calculateAmount(reqDTO.getAmount())); + bizContent.put("subject", reqDTO.getSubject()); + bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY"); + // PC扫码支付的方式:支持前置模式和跳转模式。4: 订单码-可定义宽度的嵌入式二维码 + bizContent.put("qr_pay_mode", "4"); + // 自定义二维码宽度 + bizContent.put("qrcode_width", "150"); + request.setBizContent(bizContent.toJSONString()); + request.setNotifyUrl(reqDTO.getNotifyUrl()); + request.setReturnUrl(""); + // 执行请求 + AlipayTradePagePayResponse response; + try { + response = client.pageExecute(request); + } catch (AlipayApiException e) { + log.error("[unifiedOrder][request({}) 发起支付失败]", JsonUtils.toJsonString(reqDTO), e); + return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping); + } + // 响应为表单格式,前端可嵌入响应的页面或关闭当前支付窗口 + return PayCommonResult.build(StrUtil.blankToDefault(response.getCode(),"10000") ,response.getMsg(), response, codeMapping); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXLitePayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXLitePayClient.java index c9b81ace0..52bdde62d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXLitePayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXLitePayClient.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.wx; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; @@ -167,7 +168,7 @@ public class WXLitePayClient extends AbstractPayClient { .builder() .orderExtensionNo(result.getOutTradeNo()) .channelOrderNo(result.getTradeState()) - .successTime(DateUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) + .successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) .data(data.getBody()) .build(); } @@ -181,7 +182,7 @@ public class WXLitePayClient extends AbstractPayClient { .orderExtensionNo(notifyResult.getOutTradeNo()) .channelOrderNo(notifyResult.getTransactionId()) .channelUserId(notifyResult.getOpenid()) - .successTime(DateUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) + .successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) .data(data.getBody()) .build(); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXNativePayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXNativePayClient.java index 20ad91c82..f9ccd4629 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXNativePayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXNativePayClient.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.wx; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.io.FileUtils; @@ -150,7 +151,7 @@ public class WXNativePayClient extends AbstractPayClient { .builder() .orderExtensionNo(result.getOutTradeNo()) .channelOrderNo(result.getTradeState()) - .successTime(DateUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) + .successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) .data(data.getBody()) .build(); } @@ -164,7 +165,7 @@ public class WXNativePayClient extends AbstractPayClient { .orderExtensionNo(notifyResult.getOutTradeNo()) .channelOrderNo(notifyResult.getTransactionId()) .channelUserId(notifyResult.getOpenid()) - .successTime(DateUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) + .successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) .data(data.getBody()) .build(); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java index 238344759..84e3064c3 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.wx; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; @@ -161,7 +162,7 @@ public class WXPubPayClient extends AbstractPayClient { .builder() .orderExtensionNo(result.getOutTradeNo()) .channelOrderNo(result.getTradeState()) - .successTime(DateUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) + .successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) .data(data.getBody()) .build(); } @@ -175,7 +176,7 @@ public class WXPubPayClient extends AbstractPayClient { .orderExtensionNo(notifyResult.getOutTradeNo()) .channelOrderNo(notifyResult.getTransactionId()) .channelUserId(notifyResult.getOpenid()) - .successTime(DateUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) + .successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) .data(data.getBody()) .build(); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsReceiveRespDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsReceiveRespDTO.java index 8c841ebea..4def4a25c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsReceiveRespDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsReceiveRespDTO.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.framework.sms.core.client.dto; import lombok.Data; -import java.util.Date; +import java.time.LocalDateTime; /** * 消息接收 Response DTO @@ -32,7 +32,7 @@ public class SmsReceiveRespDTO { /** * 用户接收时间 */ - private Date receiveTime; + private LocalDateTime receiveTime; /** * 短信 API 发送返回的序号 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java index ae93a88b6..59723c4c9 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java @@ -4,6 +4,8 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; @@ -11,8 +13,6 @@ import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import com.aliyuncs.AcsRequest; import com.aliyuncs.AcsResponse; import com.aliyuncs.DefaultAcsClient; @@ -28,7 +28,7 @@ import com.google.common.annotations.VisibleForTesting; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; import java.util.Objects; import java.util.function.Function; @@ -166,13 +166,13 @@ public class AliyunSmsClient extends AbstractSmsClient { */ @JsonProperty("send_time") @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private Date sendTime; + private LocalDateTime sendTime; /** * 状态报告时间 */ @JsonProperty("report_time") @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private Date reportTime; + private LocalDateTime reportTime; /** * 是否接收成功 */ diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java index 23bb01a02..743c1aed8 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java @@ -22,7 +22,7 @@ import com.tencentcloudapi.sms.v20210111.SmsClient; import com.tencentcloudapi.sms.v20210111.models.*; import lombok.Data; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; import java.util.function.Function; import java.util.function.Supplier; @@ -240,7 +240,7 @@ public class TencentSmsClient extends AbstractSmsClient { */ @JsonProperty("user_receive_time") @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private Date receiveTime; + private LocalDateTime receiveTime; /** * 国家(或地区)码 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java index 12cb6635c..c5d1f88d0 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java @@ -5,6 +5,7 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.URLUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; @@ -12,7 +13,6 @@ import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.annotations.VisibleForTesting; @@ -23,6 +23,7 @@ import com.yunpian.sdk.model.Template; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import java.time.LocalDateTime; import java.util.*; import java.util.function.Function; import java.util.function.Supplier; @@ -198,7 +199,7 @@ public class YunpianSmsClient extends AbstractSmsClient { */ @JsonProperty("user_receive_time") @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private Date userReceiveTime; + private LocalDateTime userReceiveTime; } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java index e65e23db7..4b02c5121 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java @@ -11,7 +11,6 @@ import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; import com.aliyuncs.AcsRequest; import com.aliyuncs.IAcsClient; @@ -27,6 +26,7 @@ import org.mockito.ArgumentMatcher; import org.mockito.InjectMocks; import org.mockito.Mock; +import java.time.LocalDateTime; import java.util.List; import java.util.function.Function; @@ -125,7 +125,7 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { assertEquals("DELIVERED", statuses.get(0).getErrorCode()); assertEquals("用户接收成功", statuses.get(0).getErrorMsg()); assertEquals("13900000001", statuses.get(0).getMobile()); - assertEquals(DateUtils.buildTime(2017, 2, 2, 22, 23, 24), statuses.get(0).getReceiveTime()); + assertEquals(LocalDateTime.of(2017, 2, 2, 22, 23, 24), statuses.get(0).getReceiveTime()); assertEquals("12345", statuses.get(0).getSerialNo()); assertEquals(67890L, statuses.get(0).getLogId()); } @@ -181,7 +181,7 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { when(client.getAcsResponse(any(AcsRequest.class))).thenThrow(ex); // 调用,并断言异常 - SmsCommonResult result = smsClient.invoke(request,null); + SmsCommonResult result = smsClient.invoke(request, null); // 断言 assertEquals(ex.getErrCode(), result.getApiCode()); assertEquals(ex.getErrMsg(), result.getApiMsg()); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java index 64305c7a0..9269de724 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; @@ -25,6 +24,7 @@ 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; @@ -146,7 +146,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { assertEquals("DELIVRD", statuses.get(0).getErrorCode()); assertEquals("用户短信送达成功", statuses.get(0).getErrorMsg()); assertEquals("13900000001", statuses.get(0).getMobile()); - assertEquals(DateUtils.buildTime(2015, 10, 17, 8, 3, 4), statuses.get(0).getReceiveTime()); + assertEquals(LocalDateTime.of(2015, 10, 17, 8, 3, 4), statuses.get(0).getReceiveTime()); assertEquals("12345", statuses.get(0).getSerialNo()); assertEquals(67890L, statuses.get(0).getLogId()); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java index 8271c0d7b..a28745e6c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java @@ -10,7 +10,6 @@ import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; import com.google.common.collect.Lists; import com.yunpian.sdk.YunpianClient; import com.yunpian.sdk.api.SmsApi; @@ -23,6 +22,7 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -115,7 +115,7 @@ public class YunpianSmsClientTest extends BaseMockitoUnitTest { assertEquals("", statuses.get(0).getErrorCode()); assertNull(statuses.get(0).getErrorMsg()); assertEquals("15205201314", statuses.get(0).getMobile()); - assertEquals(DateUtils.buildTime(2014, 3, 17, 22, 55, 21), statuses.get(0).getReceiveTime()); + assertEquals(LocalDateTime.of(2014, 3, 17, 22, 55, 21), statuses.get(0).getReceiveTime()); assertEquals("9527", statuses.get(0).getSerialNo()); assertEquals(1024L, statuses.get(0).getLogId()); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java index e338e2c73..e9ec9772c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor; import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect; import cn.iocoder.yudao.framework.tenant.core.mq.TenantChannelInterceptor; import cn.iocoder.yudao.framework.tenant.core.mq.TenantFunctionAroundWrapper; +import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager; import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter; import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkServiceImpl; @@ -25,8 +26,16 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.cloud.function.context.catalog.FunctionAroundWrapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.integration.config.GlobalChannelInterceptor; +import java.util.Objects; + @Configuration @ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true) // 允许使用 yudao.tenant.enable=false 禁用多租户 @EnableConfigurationProperties(TenantProperties.class) @@ -122,4 +131,17 @@ public class YudaoTenantAutoConfiguration { return new TenantJobAspect(tenantFrameworkService); } + // ========== Redis ========== + + @Bean + @Primary // 引入租户时,tenantRedisCacheManager 为主 Bean + public RedisCacheManager tenantRedisCacheManager(RedisTemplate redisTemplate, + RedisCacheConfiguration redisCacheConfiguration) { + // 创建 RedisCacheWriter 对象 + RedisConnectionFactory connectionFactory = Objects.requireNonNull(redisTemplate.getConnectionFactory()); + RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); + // 创建 TenantRedisCacheManager 对象 + return new TenantRedisCacheManager(cacheWriter, redisCacheConfiguration); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java index a42acc41c..3b15398d6 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.tenant.core.context; +import cn.iocoder.yudao.framework.common.enums.DocumentEnum; import com.alibaba.ttl.TransmittableThreadLocal; /** @@ -36,7 +37,8 @@ public class TenantContextHolder { public static Long getRequiredTenantId() { Long tenantId = getTenantId(); if (tenantId == null) { - throw new NullPointerException("TenantContextHolder 不存在租户编号"); // TODO 芋艿:增加文档链接 + throw new NullPointerException("TenantContextHolder 不存在租户编号!可参考文档:" + + DocumentEnum.TENANT.getUrl()); } return tenantId; } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java new file mode 100644 index 000000000..8058b2f54 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.tenant.core.redis; + +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.Cache; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; + +/** + * 多租户的 {@link RedisCacheManager} 实现类 + * + * 操作指定 name 的 {@link Cache} 时,自动拼接租户后缀,格式为 name + ":" + tenantId + 后缀 + * + * @author airhead + */ +@Slf4j +public class TenantRedisCacheManager extends RedisCacheManager { + + public TenantRedisCacheManager(RedisCacheWriter cacheWriter, + RedisCacheConfiguration defaultCacheConfiguration) { + super(cacheWriter, defaultCacheConfiguration); + } + + @Override + public Cache getCache(String name) { + // 如果开启多租户,则 name 拼接租户后缀 + if (!TenantContextHolder.isIgnore() + && TenantContextHolder.getTenantId() != null) { + name = name + ":" + TenantContextHolder.getTenantId(); + } + + // 继续基于父方法 + return super.getCache(name); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java index 7e1f1dc5a..803e541c5 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.util.AntPathMatcher; @@ -65,6 +66,7 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { Long tenantId = TenantContextHolder.getTenantId(); + boolean isRpcRequest = !WebFrameworkUtils.isRpcRequest(request); // 1. 登陆的用户,校验是否有权限访问该租户,避免越权问题。 LoginUser user = SecurityFrameworkUtils.getLoginUser(); if (user != null) { @@ -73,7 +75,8 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { tenantId = user.getTenantId(); TenantContextHolder.setTenantId(tenantId); // 如果传递了租户编号,则进行比对租户编号,避免越权问题 - } else if (!Objects.equals(user.getTenantId(), TenantContextHolder.getTenantId())) { + } else if (!Objects.equals(user.getTenantId(), TenantContextHolder.getTenantId()) + && !isRpcRequest) { // Cloud 特殊逻辑:如果是 RPC 请求,就不校验了。主要考虑,一些场景下,会调用 TenantUtils 去切换租户 log.error("[doFilterInternal][租户({}) User({}/{}) 越权访问租户({}) URL({}/{})]", user.getTenantId(), user.getId(), user.getUserType(), TenantContextHolder.getTenantId(), request.getRequestURI(), request.getMethod()); diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java index 7698cf4a6..182c83a72 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java @@ -5,8 +5,9 @@ import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import lombok.extern.slf4j.Slf4j; @@ -29,11 +30,11 @@ public class DictConvert implements Converter { } @Override - public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Object convertToJavaData(ReadCellData readCellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { // 使用字典解析 String type = getType(contentProperty); - String label = cellData.getStringValue(); + String label = readCellData.getStringValue(); String value = DictFrameworkUtils.parseDictDataValue(type, label); if (value == null) { log.error("[convertToJavaData][type({}) 解析不掉 label({})]", type, label); @@ -45,11 +46,11 @@ public class DictConvert implements Converter { } @Override - public CellData convertToExcelData(Object object, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { + public WriteCellData convertToExcelData(Object object, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { // 空时,返回空 if (object == null) { - return new CellData<>(""); + return new WriteCellData<>(""); } // 使用字典格式化 @@ -58,10 +59,10 @@ public class DictConvert implements Converter { String label = DictFrameworkUtils.getDictDataLabel(type, value); if (label == null) { log.error("[convertToExcelData][type({}) 转换不了 label({})]", type, value); - return new CellData<>(""); + return new WriteCellData<>(""); } // 生成 Excel 小表格 - return new CellData<>(label); + return new WriteCellData<>(label); } private static String getType(ExcelContentProperty contentProperty) { diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java index f0a577c0a..0d4794e5f 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.excel.core.convert; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -25,15 +25,10 @@ public class JsonConvert implements Converter { } @Override - public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - throw new UnsupportedOperationException("暂不支持,也不需要"); - } - - @Override - public CellData convertToExcelData(Object value, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { + public WriteCellData convertToExcelData(Object value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { // 生成 Excel 小表格 - return new CellData<>(JsonUtils.toJsonString(value)); + return new WriteCellData<>(JsonUtils.toJsonString(value)); } } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java index 7bb555450..19abaa6fe 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java @@ -7,7 +7,7 @@ import lombok.Data; import org.apache.ibatis.type.JdbcType; import java.io.Serializable; -import java.util.Date; +import java.time.LocalDateTime; /** * 基础实体对象 @@ -21,12 +21,12 @@ public abstract class BaseDO implements Serializable { * 创建时间 */ @TableField(fill = FieldFill.INSERT) - private Date createTime; + private LocalDateTime createTime; /** * 最后更新时间 */ @TableField(fill = FieldFill.INSERT_UPDATE) - private Date updateTime; + private LocalDateTime updateTime; /** * 创建者,目前使用 SysUser 的 id 编号 * diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java index 65910b16e..94dada129 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; -import java.util.Date; +import java.time.LocalDateTime; import java.util.Objects; /** @@ -22,7 +22,7 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) { BaseDO baseDO = (BaseDO) metaObject.getOriginalObject(); - Date current = new Date(); + LocalDateTime current = LocalDateTime.now(); // 创建时间为空,则以当前时间为插入时间 if (Objects.isNull(baseDO.getCreateTime())) { baseDO.setCreateTime(current); @@ -49,7 +49,7 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { // 更新时间为空,则以当前时间为更新时间 Object modifyTime = getFieldValByName("updateTime", metaObject); if (Objects.isNull(modifyTime)) { - setFieldValByName("updateTime", new Date(), metaObject); + setFieldValByName("updateTime", LocalDateTime.now(), metaObject); } // 当前登录用户不为空,更新人为空,则当前登录用户为更新人 diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java index 16d3b29b1..b9574dc23 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.SortingField; import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -33,7 +34,7 @@ public class MyBatisUtils { // 排序字段 if (!CollectionUtil.isEmpty(sortingFields)) { page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(sortingField.getOrder()) ? - OrderItem.asc(sortingField.getField()) : OrderItem.desc(sortingField.getField())) + OrderItem.asc(sortingField.getField()) : OrderItem.desc(sortingField.getField())) .collect(Collectors.toList())); } return page; @@ -78,7 +79,10 @@ public class MyBatisUtils { * @return Column 对象 */ public static Column buildColumn(String tableName, Alias tableAlias, String column) { - return new Column(tableAlias != null ? tableAlias.getName() + "." + column : column); + if (tableAlias != null) { + tableName = tableAlias.getName(); + } + return new Column(tableName + StringPool.DOT + column); } } diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/DefaultLockFailureStrategy.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/DefaultLockFailureStrategy.java index 3af543530..2cea08bf8 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/DefaultLockFailureStrategy.java +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/DefaultLockFailureStrategy.java @@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstant import com.baomidou.lock.LockFailureStrategy; import lombok.extern.slf4j.Slf4j; +import java.lang.reflect.Method; + /** * 自定义获取锁失败策略,抛出 {@link ServiceException} 异常 */ @@ -12,9 +14,8 @@ import lombok.extern.slf4j.Slf4j; public class DefaultLockFailureStrategy implements LockFailureStrategy { @Override - public void onLockFailure(String key, long acquireTimeout, int acquireCount) { - log.debug("[onLockFailure][线程:{} 获取锁失败,key:{} 获取超时时长:{} ms]", Thread.currentThread().getName(), key, acquireTimeout); + public void onLockFailure(String key, Method method, Object[] arguments) { + log.debug("[onLockFailure][线程:{} 获取锁失败,key:{} 获取失败:{} ]", Thread.currentThread().getName(), key, arguments); throw new ServiceException(GlobalErrorCodeConstants.LOCKED); } - } diff --git a/yudao-framework/yudao-spring-boot-starter-redis/pom.xml b/yudao-framework/yudao-spring-boot-starter-redis/pom.xml index f1d66e776..4b11789b4 100644 --- a/yudao-framework/yudao-spring-boot-starter-redis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-redis/pom.xml @@ -32,6 +32,10 @@ spring-boot-starter-cache + + io.netty + netty-all + diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java index e8c716203..6a8f92efc 100644 --- a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.redis.config; import org.springframework.boot.autoconfigure.cache.CacheProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -13,6 +14,7 @@ import org.springframework.data.redis.serializer.RedisSerializer; * Cache 配置类,基于 Redis 实现 */ @Configuration +@EnableConfigurationProperties({CacheProperties.class}) @EnableCaching public class YudaoCacheAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java index 917697b3f..7c50bbafa 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java @@ -127,7 +127,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap .antMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll() // 基于 yudao.security.permit-all-urls 无需认证 .antMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll() - .antMatchers("/captcha/get", "/captcha/check").permitAll() // 设置 App API 无需认证 .antMatchers(buildAppApi("/**")).permitAll() // ②:每个项目的自定义规则 diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java index d41c3951e..8664dae42 100644 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.test.core.util; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; @@ -8,6 +9,7 @@ import uk.co.jemos.podam.api.PodamFactory; import uk.co.jemos.podam.api.PodamFactoryImpl; import java.lang.reflect.Type; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -76,6 +78,10 @@ public class RandomUtils { return RandomUtil.randomDay(0, RANDOM_DATE_MAX); } + public static LocalDateTime randomLocalDateTime() { + return LocalDateTimeUtil.of(randomDate()); + } + public static Short randomShort() { return (short) RandomUtil.randomInt(0, Short.MAX_VALUE); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java index 6417189b0..3a2ab6bd4 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.apilog.core.filter; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.extra.servlet.ServletUtil; @@ -7,7 +8,6 @@ import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLog; import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.config.WebProperties; @@ -20,7 +20,8 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.Date; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.Map; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; @@ -47,7 +48,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 获得开始时间 - Date beginTim = new Date(); + LocalDateTime beginTime = LocalDateTime.now(); // 提前获得参数,避免 XssFilter 过滤处理 Map queryString = ServletUtil.getParamMap(request); String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtil.getBody(request) : null; @@ -56,15 +57,15 @@ public class ApiAccessLogFilter extends ApiRequestFilter { // 继续过滤器 filterChain.doFilter(request, response); // 正常执行,记录日志 - createApiAccessLog(request, beginTim, queryString, requestBody, null); + createApiAccessLog(request, beginTime, queryString, requestBody, null); } catch (Exception ex) { // 异常执行,记录日志 - createApiAccessLog(request, beginTim, queryString, requestBody, ex); + createApiAccessLog(request, beginTime, queryString, requestBody, ex); throw ex; } } - private void createApiAccessLog(HttpServletRequest request, Date beginTime, + private void createApiAccessLog(HttpServletRequest request, LocalDateTime beginTime, Map queryString, String requestBody, Exception ex) { ApiAccessLog accessLog = new ApiAccessLog(); try { @@ -75,7 +76,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter { } } - private void buildApiAccessLogDTO(ApiAccessLog accessLog, HttpServletRequest request, Date beginTime, + private void buildApiAccessLogDTO(ApiAccessLog accessLog, HttpServletRequest request, LocalDateTime beginTime, Map queryString, String requestBody, Exception ex) { // 处理用户信息 accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); @@ -103,8 +104,8 @@ public class ApiAccessLogFilter extends ApiRequestFilter { accessLog.setUserIp(ServletUtil.getClientIP(request)); // 持续时间 accessLog.setBeginTime(beginTime); - accessLog.setEndTime(new Date()); - accessLog.setDuration((int) DateUtils.diff(accessLog.getEndTime(), accessLog.getBeginTime())); + accessLog.setEndTime(LocalDateTime.now()); + accessLog.setDuration((int) LocalDateTimeUtil.between(accessLog.getBeginTime(), accessLog.getEndTime(), ChronoUnit.SECONDS)); } } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLog.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLog.java index a92b06c26..7799c42f6 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLog.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLog.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.apilog.core.service; import lombok.Data; import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; /** * API 访问日志 @@ -61,12 +61,12 @@ public class ApiAccessLog { * 开始请求时间 */ @NotNull(message = "开始请求时间不能为空") - private Date beginTime; + private LocalDateTime beginTime; /** * 结束请求时间 */ @NotNull(message = "结束请求时间不能为空") - private Date endTime; + private LocalDateTime endTime; /** * 执行时长,单位:毫秒 */ diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java index 3f5d539cb..087dd5d08 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.apilog.core.service; import lombok.Data; import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; /** * API 错误日志 @@ -61,7 +61,7 @@ public class ApiErrorLog { * 异常时间 */ @NotNull(message = "异常时间不能为空") - private Date exceptionTime; + private LocalDateTime exceptionTime; /** * 异常名 */ diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index fdf77de96..a9e231285 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -30,7 +30,8 @@ import javax.servlet.http.HttpServletRequest; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import javax.validation.ValidationException; -import java.util.Date; +import java.time.LocalDateTime; +import java.time.LocalDateTime; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*; @@ -267,7 +268,7 @@ public class GlobalExceptionHandler { errorLog.setRequestMethod(request.getMethod()); errorLog.setUserAgent(ServletUtils.getUserAgent(request)); errorLog.setUserIp(ServletUtil.getClientIP(request)); - errorLog.setExceptionTime(new Date()); + errorLog.setExceptionTime(LocalDateTime.now()); } } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java index e11a3236a..d2b70e946 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.web.core.util; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.RpcConstants; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.web.config.WebProperties; @@ -124,4 +125,14 @@ public class WebFrameworkUtils { return servletRequestAttributes.getRequest(); } + /** + * 判断是否为 RPC 请求 + * + * @param request 请求 + * @return 是否为 RPC 请求 + */ + public static boolean isRpcRequest(HttpServletRequest request) { + return request.getRequestURI().startsWith(RpcConstants.RPC_API_PREFIX); + } + } diff --git a/yudao-gateway/pom.xml b/yudao-gateway/pom.xml index 3c4776c19..7c16b6658 100644 --- a/yudao-gateway/pom.xml +++ b/yudao-gateway/pom.xml @@ -39,6 +39,20 @@ spring-cloud-starter-gateway + + javax.servlet + javax.servlet-api + + + + com.github.xiaoymin + knife4j-spring-boot-starter + + + io.swagger + swagger-annotations + + org.springframework.cloud @@ -63,19 +77,6 @@ yudao-spring-boot-starter-monitor - - com.github.xiaoymin - knife4j-spring-boot-starter - - - io.swagger - swagger-annotations - - - io.springfox - springfox-boot-starter - 3.0.0 - @@ -87,7 +88,7 @@ org.springframework.boot spring-boot-maven-plugin - 2.6.7 + 2.6.13 true diff --git a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/GatewayServerApplication.java b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/GatewayServerApplication.java index c738b0273..99984699f 100644 --- a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/GatewayServerApplication.java +++ b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/GatewayServerApplication.java @@ -2,58 +2,10 @@ package cn.iocoder.yudao.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.core.env.Environment; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.web.cors.reactive.CorsUtils; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; -import org.springframework.web.server.WebFilterChain; -import reactor.core.publisher.Mono; @SpringBootApplication public class GatewayServerApplication { - // ----------------------------- 解决跨域 Begin ----------------------------- - - private static final String ALL = "*"; - private static final String MAX_AGE = "3600L"; - - - @Bean - public WebFilter corsFilter() { - return (ServerWebExchange ctx, WebFilterChain chain) -> { - ServerHttpRequest request = ctx.getRequest(); - if (!CorsUtils.isCorsRequest(request)) { - return chain.filter(ctx); - } - HttpHeaders requestHeaders = request.getHeaders(); - ServerHttpResponse response = ctx.getResponse(); - HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod(); - HttpHeaders headers = response.getHeaders(); - headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin()); - headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders()); - if (requestMethod != null) { - headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name()); - } - headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); - headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL); - headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE); - if (request.getMethod() == HttpMethod.OPTIONS) { - response.setStatusCode(HttpStatus.OK); - return Mono.empty(); - } - return chain.filter(ctx); - }; - } - - // ----------------------------- 解决跨域 End ----------------------------- - public static void main(String[] args) { // 启动 Spring Boot 应用 SpringApplication.run(GatewayServerApplication.class, args); diff --git a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/cors/CorsFilter.java b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/cors/CorsFilter.java new file mode 100644 index 000000000..16432ee0e --- /dev/null +++ b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/cors/CorsFilter.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.gateway.filter.cors; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.cors.reactive.CorsUtils; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; + +/** + * 跨域 Filter + * + * @author 芋道源码 + */ +@Component +public class CorsFilter implements WebFilter { + + private static final String ALL = "*"; + private static final String MAX_AGE = "3600L"; + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + // 非跨域请求,直接放行 + ServerHttpRequest request = exchange.getRequest(); + if (!CorsUtils.isCorsRequest(request)) { + return chain.filter(exchange); + } + + // 设置跨域响应头 + ServerHttpResponse response = exchange.getResponse(); + HttpHeaders headers = response.getHeaders(); + headers.add("Access-Control-Allow-Origin", ALL); + headers.add("Access-Control-Allow-Methods", ALL); + headers.add("Access-Control-Allow-Headers", ALL); + headers.add("Access-Control-Max-Age", MAX_AGE); + if (request.getMethod() == HttpMethod.OPTIONS) { + response.setStatusCode(HttpStatus.OK); + return Mono.empty(); + } + return chain.filter(exchange); + } + +} diff --git a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/logging/AccessLog.java b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/logging/AccessLog.java index dd2bc24b0..52b46fc23 100644 --- a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/logging/AccessLog.java +++ b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/logging/AccessLog.java @@ -5,8 +5,7 @@ import org.springframework.cloud.gateway.route.Route; import org.springframework.http.HttpStatus; import org.springframework.util.MultiValueMap; -import java.util.Date; -import java.util.Map; +import java.time.LocalDateTime; /** * 网关的访问日志 @@ -80,11 +79,11 @@ public class AccessLog { /** * 开始请求时间 */ - private Date startTime; + private LocalDateTime startTime; /** * 结束请求时间 */ - private Date endTime; + private LocalDateTime endTime; /** * 执行时长,单位:毫秒 */ diff --git a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/logging/AccessLogFilter.java b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/logging/AccessLogFilter.java index f753ef5f1..4f9c34c53 100644 --- a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/logging/AccessLogFilter.java +++ b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/logging/AccessLogFilter.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.gateway.filter.logging; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -38,12 +39,13 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.nio.charset.StandardCharsets; -import java.util.Date; +import java.time.LocalDateTime; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import static cn.hutool.core.date.DatePattern.NORM_DATETIME_MS_FORMAT; +import static cn.hutool.core.date.DatePattern.NORM_DATETIME_MS_FORMATTER; /** * 网关的访问日志过滤器 @@ -89,8 +91,8 @@ public class AccessLogFilter implements GlobalFilter, Ordered { values.put("responseHeaders", gatewayLog.getResponseHeaders() != null ? JsonUtils.toJsonString(gatewayLog.getResponseHeaders().toSingleValueMap()) : null); values.put("httpStatus", gatewayLog.getHttpStatus()); - values.put("startTime", DateUtil.format(gatewayLog.getStartTime(), NORM_DATETIME_MS_FORMAT)); - values.put("endTime", DateUtil.format(gatewayLog.getEndTime(), NORM_DATETIME_MS_FORMAT)); + values.put("startTime", LocalDateTimeUtil.format(gatewayLog.getStartTime(), NORM_DATETIME_MS_FORMATTER)); + values.put("endTime", LocalDateTimeUtil.format(gatewayLog.getEndTime(), NORM_DATETIME_MS_FORMATTER)); values.put("duration", gatewayLog.getDuration() != null ? gatewayLog.getDuration() + " ms" : null); log.info("[writeAccessLog][网关日志:{}]", JsonUtils.toJsonPrettyString(values)); } @@ -112,7 +114,7 @@ public class AccessLogFilter implements GlobalFilter, Ordered { gatewayLog.setRequestUrl(request.getURI().getRawPath()); gatewayLog.setQueryParams(request.getQueryParams()); gatewayLog.setRequestHeaders(request.getHeaders()); - gatewayLog.setStartTime(new Date()); + gatewayLog.setStartTime(LocalDateTime.now()); gatewayLog.setUserIp(WebFrameworkUtils.getClientIP(exchange)); // 继续 filter 过滤 @@ -179,8 +181,9 @@ public class AccessLogFilter implements GlobalFilter, Ordered { if (body instanceof Flux) { DataBufferFactory bufferFactory = response.bufferFactory(); // 计算执行时间 - gatewayLog.setEndTime(new Date()); - gatewayLog.setDuration((int) DateUtils.diff(gatewayLog.getEndTime(), gatewayLog.getStartTime())); + gatewayLog.setEndTime(LocalDateTime.now()); + gatewayLog.setDuration((int) (LocalDateTimeUtil.between(gatewayLog.getStartTime(), + gatewayLog.getEndTime()).toMillis())); // 设置其它字段 gatewayLog.setUserId(SecurityFrameworkUtils.getLoginUserId(exchange)); gatewayLog.setUserType(SecurityFrameworkUtils.getLoginUserType(exchange)); diff --git a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/swagger/SwaggerHandler.java b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/swagger/SwaggerHandler.java index 170b1f96a..7cae3c810 100644 --- a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/swagger/SwaggerHandler.java +++ b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/swagger/SwaggerHandler.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.gateway.swagger; -import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -9,55 +8,47 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; -import springfox.documentation.swagger.web.SecurityConfiguration; -import springfox.documentation.swagger.web.SecurityConfigurationBuilder; -import springfox.documentation.swagger.web.SwaggerResourcesProvider; -import springfox.documentation.swagger.web.UiConfiguration; -import springfox.documentation.swagger.web.UiConfigurationBuilder; +import springfox.documentation.swagger.web.*; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Optional; /** + * Swagger Controller + * * @author zxliu - * @create 2022-10-25 11:24 + * @date 2022-10-25 11:24 */ - @RestController @RequestMapping("/swagger-resources") public class SwaggerHandler { - + + @Resource + private SwaggerResourcesProvider swaggerResources; + + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // 只有 @Autowired 可以实现可选注入 @Autowired(required = false) private SecurityConfiguration securityConfiguration; - + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // 只有 @Autowired 可以实现可选注入 @Autowired(required = false) private UiConfiguration uiConfiguration; - private final SwaggerResourcesProvider swaggerResources; - - - @Autowired - public SwaggerHandler(SwaggerResourcesProvider swaggerResources) { - this.swaggerResources = swaggerResources; - } - - - @GetMapping("/configuration/security") - public Mono> securityConfiguration() { - return Mono.just(new ResponseEntity<>( - Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), - HttpStatus.OK)); - } - - - @GetMapping("/configuration/ui") - public Mono> uiConfiguration() { - return Mono.just(new ResponseEntity<>( - Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); - } - - - @SuppressWarnings("rawtypes") @GetMapping("") - public Mono swaggerResources() { + public Mono>> swaggerResources() { return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); } + @GetMapping("/configuration/security") + public Mono> securityConfiguration() { + return Mono.just(new ResponseEntity<>(Optional.ofNullable(securityConfiguration) + .orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK)); + } + + @GetMapping("/configuration/ui") + public Mono> uiConfiguration() { + return Mono.just(new ResponseEntity<>(Optional.ofNullable(uiConfiguration) + .orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); + } + } diff --git a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/swagger/SwaggerProvider.java b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/swagger/SwaggerProvider.java index 0a1c60183..5c61f312c 100644 --- a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/swagger/SwaggerProvider.java +++ b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/swagger/SwaggerProvider.java @@ -1,48 +1,70 @@ package cn.iocoder.yudao.gateway.swagger; -import java.util.ArrayList; -import java.util.List; -import lombok.AllArgsConstructor; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.config.GatewayProperties; -import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; +import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.support.NameUtils; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.SwaggerResourcesProvider; -/** - * @author zxliu - * @create 2022-10-25 11:23 - */ +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +/** + * Swagger 资源的 Provider 实现类 + * + * @author zxliu + * @date 2022-10-25 11:23 + */ @Component @Primary -@AllArgsConstructor +@Slf4j public class SwaggerProvider implements SwaggerResourcesProvider { - private final RouteLocator routeLocator; - private final GatewayProperties gatewayProperties; - + @Resource + private GatewayProperties gatewayProperties; + /** + * 获得 SwaggerResource 列表 + * + * @return SwaggerResource 列表 + */ @Override public List get() { + // 将 RouteDefinition 转换成 SwaggerResource List resources = new ArrayList<>(); - List routes = new ArrayList<>(); - routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); - gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())) - .forEach(route -> route.getPredicates().stream() - .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())) - .forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(), - predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0") - .replace("**", "v2/api-docs")))) - ); + Set serviceNames = new HashSet<>(); // 已处理的服务名,避免重复 + gatewayProperties.getRoutes().forEach(route -> { + // 已存在的服务,直接忽略 + String serviceName = route.getUri().getHost(); + if (StrUtil.isEmpty(serviceName)) { + return; + } + if (!serviceNames.add(serviceName)) { + return; + } + // 获得 Path PredicateDefinition + String path = getRoutePath(route); + if (path == null) { + return; + } + + // 重要:构建最终的 SwaggerResource 对象 + resources.add(buildSwaggerResource(serviceName, path)); + }); return resources; } - - private SwaggerResource swaggerResource(String name, String location) { + private SwaggerResource buildSwaggerResource(String name, String location) { SwaggerResource swaggerResource = new SwaggerResource(); swaggerResource.setName(name); swaggerResource.setLocation(location); @@ -50,4 +72,31 @@ public class SwaggerProvider implements SwaggerResourcesProvider { return swaggerResource; } + /** + * 获得路由的 Path + * + * ① 输入: + * predicates: + * - Path=/admin-api/system/** + * ② 输出: + * /admin-api/system/v2/api-docs + * + * @param route 路由 + * @return 路由 + */ + private String getRoutePath(RouteDefinition route) { + PredicateDefinition pathDefinition = CollUtil.findOne(route.getPredicates(), + predicateDefinition -> predicateDefinition.getName().equals("Path")); + if (pathDefinition == null) { + log.info("[get][Route({}) 没有 Path 条件,忽略接口文档]", route.getId()); + return null; + } + String path = pathDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0"); + if (StrUtil.isEmpty(path)) { + log.info("[get][Route({}) Path 的值为空,忽略接口文档]", route.getId()); + return null; + } + return path.replace("/**", "/v2/api-docs"); + } + } diff --git a/yudao-gateway/src/main/resources/application.yaml b/yudao-gateway/src/main/resources/application.yaml index 5689d0ccc..42f9fa5e7 100644 --- a/yudao-gateway/src/main/resources/application.yaml +++ b/yudao-gateway/src/main/resources/application.yaml @@ -5,20 +5,14 @@ spring: cloud: # Spring Cloud Gateway 配置项,对应 GatewayProperties 类 gateway: - discovery: - locator: - # gateway开启服务注册和发现的功能, - enabled: true - # 将请求路径上的服务名配置为小写(因为服务注册的时候,向注册中心注册时将服务名转成大写的了) - lowerCaseServiceId: true # 路由配置项,对应 RouteDefinition 数组 routes: - id: system-admin-api # 路由的编号 uri: grayLb://system-server predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 - - Path=/admin-api/system/**,/captcha/** + - Path=/admin-api/system/** filters: - - RewritePath=/admin-api/system/v2/api-docs, /v2/api-docs + - RewritePath=/admin-api/system/v2/api-docs, /v2/api-docs # 配置,保证转发到 /v2/api-docs - id: system-app-api # 路由的编号 uri: grayLb://system-server predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 @@ -30,7 +24,7 @@ spring: predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 - Path=/admin-api/infra/** filters: - - RewritePath=/admin-api/infram/v2/api-docs, /v2/api-docs + - RewritePath=/admin-api/infra/v2/api-docs, /v2/api-docs - id: infra-app-api # 路由的编号 uri: grayLb://infra-server predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java index 76cf62046..e49f09879 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java @@ -7,7 +7,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; @ApiModel("管理后台 - 动态表单 Response VO") @@ -28,6 +28,6 @@ public class BpmFormRespVO extends BpmFormBaseVO { private List fields; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java index 2bbe95192..2608607bf 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java @@ -9,7 +9,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - 用户组分页 Request VO") @Data @@ -25,6 +25,6 @@ public class BpmUserGroupPageReqVO extends PageParam { @DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ApiModelProperty(value = "创建时间") - private Date[] createTime; + private LocalDateTime[] createTime; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java index 55018d502..f240016d6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group; import lombok.*; + +import java.time.LocalDateTime; import java.util.*; import io.swagger.annotations.*; @@ -14,6 +16,6 @@ public class BpmUserGroupRespVO extends BpmUserGroupBaseVO { private Long id; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageItemRespVO.java index 7442b5ab0..10d23892e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageItemRespVO.java @@ -6,7 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - 流程模型的分页的每一项 Response VO") @Data @@ -21,7 +21,7 @@ public class BpmModelPageItemRespVO extends BpmModelBaseVO { private String formName; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; /** * 最新部署的流程定义 @@ -39,7 +39,7 @@ public class BpmModelPageItemRespVO extends BpmModelBaseVO { private Integer version; @ApiModelProperty(value = "部署时间", required = true) - private Date deploymentTime; + private LocalDateTime deploymentTime; @ApiModelProperty(value = "中断状态", required = true, example = "1", notes = "参见 SuspensionState 枚举") private Integer suspensionState; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java index bce0f9100..571850ff0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java @@ -6,7 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - 流程模型的创建 Request VO") @Data @@ -21,6 +21,6 @@ public class BpmModelRespVO extends BpmModelBaseVO { private String bpmnXml; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java index 75990f08a..1952e95a7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java @@ -6,7 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - 流程定义的分页的每一项 Response VO") @Data @@ -18,6 +18,6 @@ public class BpmProcessDefinitionPageItemRespVO extends BpmProcessDefinitionResp private String formName; @ApiModelProperty(value = "部署时间", required = true) - private Date deploymentTime; + private LocalDateTime deploymentTime; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveBaseVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveBaseVO.java index cbc568a11..be34b428d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveBaseVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveBaseVO.java @@ -1,11 +1,12 @@ package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo; -import lombok.*; -import java.util.*; -import io.swagger.annotations.*; -import javax.validation.constraints.*; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; /** @@ -18,11 +19,11 @@ public class BpmOALeaveBaseVO { @ApiModelProperty(value = "请假的开始时间", required = true) @NotNull(message = "开始时间不能为空") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date startTime; + private LocalDateTime startTime; @ApiModelProperty(value = "请假的结束时间", required = true) @NotNull(message = "结束时间不能为空") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date endTime; + private LocalDateTime endTime; @ApiModelProperty(value = "请假类型", required = true, example = "1", notes = "参见 bpm_oa_type 枚举") private Integer type; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveCreateReqVO.java index 2ebab63e9..5230e2722 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveCreateReqVO.java @@ -15,7 +15,8 @@ public class BpmOALeaveCreateReqVO extends BpmOALeaveBaseVO { @AssertTrue(message = "结束时间,需要在开始时间之后") public boolean isEndTimeValid() { - return !getEndTime().before(getStartTime()); + return !getEndTime().isBefore(getStartTime()); } + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveRespVO.java index 908c48e06..42b3ec66c 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveRespVO.java @@ -5,7 +5,7 @@ import io.swagger.annotations.*; import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -24,7 +24,7 @@ public class BpmOALeaveRespVO extends BpmOALeaveBaseVO { @ApiModelProperty(value = "申请时间", required = true) @NotNull(message = "申请时间不能为空") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date createTime; + private LocalDateTime createTime; @ApiModelProperty(value = "流程id") private String processInstanceId; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/activity/BpmActivityRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/activity/BpmActivityRespVO.java index ef9d11ac1..7f183f50c 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/activity/BpmActivityRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/activity/BpmActivityRespVO.java @@ -4,7 +4,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - 流程活动的 Response VO") @Data @@ -16,9 +16,9 @@ public class BpmActivityRespVO { private String type; @ApiModelProperty(value = "流程活动的开始时间", required = true) - private Date startTime; + private LocalDateTime startTime; @ApiModelProperty(value = "流程活动的结束时间", required = true) - private Date endTime; + private LocalDateTime endTime; @ApiModelProperty(value = "关联的流程任务的编号", example = "2048", notes = "关联的流程任务,只有 UserTask 等类型才有") private String taskId; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceMyPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceMyPageReqVO.java index db297e268..e52d45f44 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceMyPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceMyPageReqVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -35,6 +35,6 @@ public class BpmProcessInstanceMyPageReqVO extends PageParam { @ApiModelProperty(value = "创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date[] createTime; + private LocalDateTime[] createTime; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java index 5b5d5797a..0d2534b53 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java @@ -4,7 +4,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; @ApiModel("管理后台 - 流程实例的分页 Item Response VO") @@ -30,10 +30,10 @@ public class BpmProcessInstancePageItemRespVO { private Integer result; @ApiModelProperty(value = "提交时间", required = true) - private Date createTime; + private LocalDateTime createTime; @ApiModelProperty(value = "结束时间", required = true) - private Date endTime; + private LocalDateTime endTime; /** * 当前任务 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java index a1547b175..58374dae2 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java @@ -4,7 +4,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -28,10 +28,10 @@ public class BpmProcessInstanceRespVO { private Integer result; @ApiModelProperty(value = "提交时间", required = true) - private Date createTime; + private LocalDateTime createTime; @ApiModelProperty(value = "结束时间", required = true) - private Date endTime; + private LocalDateTime endTime; @ApiModelProperty(value = "提交的表单值", required = true) private Map formVariables; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageItemRespVO.java index c5e2c23ae..a9bb93f9e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageItemRespVO.java @@ -6,7 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - 流程任务的 Done 已完成的分页项 Response VO") @Data @@ -15,7 +15,7 @@ import java.util.Date; public class BpmTaskDonePageItemRespVO extends BpmTaskTodoPageItemRespVO { @ApiModelProperty(value = "结束时间", required = true) - private Date endTime; + private LocalDateTime endTime; @ApiModelProperty(value = "持续时间", required = true, example = "1000") private Long durationInMillis; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageReqVO.java index 99145b434..a347d58fe 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageReqVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -23,10 +23,10 @@ public class BpmTaskDonePageReqVO extends PageParam { @ApiModelProperty(value = "开始的创建收间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date beginCreateTime; + private LocalDateTime beginCreateTime; @ApiModelProperty(value = "结束的创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date endCreateTime; + private LocalDateTime endCreateTime; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageItemRespVO.java index e25e3aa49..5c2cbf26a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageItemRespVO.java @@ -4,7 +4,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - 流程任务的 Running 进行中的分页项 Response VO") @Data @@ -17,10 +17,10 @@ public class BpmTaskTodoPageItemRespVO { private String name; @ApiModelProperty(value = "接收时间", required = true) - private Date claimTime; + private LocalDateTime claimTime; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; @ApiModelProperty(value = "激活状态", required = true, example = "1", notes = "参见 SuspensionState 枚举") private Integer suspensionState; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageReqVO.java index 9f248e198..9d2ad18c2 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageReqVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -23,10 +23,10 @@ public class BpmTaskTodoPageReqVO extends PageParam { @ApiModelProperty(value = "开始的创建收间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date beginCreateTime; + private LocalDateTime beginCreateTime; @ApiModelProperty(value = "结束的创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date endCreateTime; + private LocalDateTime endCreateTime; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmFormConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmFormConvert.java index 6ba757417..151b4c80b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmFormConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmFormConvert.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.bpm.convert.definition; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormSimpleRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java index 4d1b2a003..9f79032f6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.convert.definition; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; @@ -44,7 +45,7 @@ public interface BpmModelConvert { default BpmModelPageItemRespVO convert(Model model, BpmFormDO form, Deployment deployment, ProcessDefinition processDefinition) { BpmModelPageItemRespVO modelRespVO = new BpmModelPageItemRespVO(); modelRespVO.setId(model.getId()); - modelRespVO.setCreateTime(model.getCreateTime()); + modelRespVO.setCreateTime(DateUtils.of(model.getCreateTime())); // 通用 copy copyTo(model, modelRespVO); // Form @@ -57,7 +58,7 @@ public interface BpmModelConvert { if (modelRespVO.getProcessDefinition() != null) { modelRespVO.getProcessDefinition().setSuspensionState(processDefinition.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode()); - modelRespVO.getProcessDefinition().setDeploymentTime(deployment.getDeploymentTime()); + modelRespVO.getProcessDefinition().setDeploymentTime(DateUtils.of(deployment.getDeploymentTime())); } return modelRespVO; } @@ -65,7 +66,7 @@ public interface BpmModelConvert { default BpmModelRespVO convert(Model model) { BpmModelRespVO modelRespVO = new BpmModelRespVO(); modelRespVO.setId(model.getId()); - modelRespVO.setCreateTime(model.getCreateTime()); + modelRespVO.setCreateTime(DateUtils.of(model.getCreateTime())); // 通用 copy copyTo(model, modelRespVO); return modelRespVO; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java index 8f5bfcd26..ad57a55b4 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.convert.definition; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; @@ -67,7 +68,7 @@ public interface BpmProcessDefinitionConvert { BpmProcessDefinitionPageItemRespVO respVO = convert(bean); respVO.setSuspensionState(bean.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode()); if (deployment != null) { - respVO.setDeploymentTime(deployment.getDeploymentTime()); + respVO.setDeploymentTime(LocalDateTimeUtil.of(deployment.getDeploymentTime())); } if (form != null) { respVO.setFormName(form.getName()); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmUserGroupConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmUserGroupConvert.java index bbf00ba52..b5cd631f7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmUserGroupConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmUserGroupConvert.java @@ -1,17 +1,16 @@ package cn.iocoder.yudao.module.bpm.convert.definition; -import java.util.*; - +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - import org.mapstruct.Mapper; import org.mapstruct.Named; import org.mapstruct.factory.Mappers; +import java.util.List; + /** * 用户组 Convert * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/message/BpmMessageConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/message/BpmMessageConvert.java index 92683f4c9..99b7bebf2 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/message/BpmMessageConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/message/BpmMessageConvert.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.convert.message; import cn.iocoder.yudao.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.Map; @@ -11,6 +12,10 @@ public interface BpmMessageConvert { BpmMessageConvert INSTANCE = Mappers.getMapper(BpmMessageConvert.class); + @Mapping(target = "mobile", ignore = true) + @Mapping(source = "userId", target = "userId") + @Mapping(source = "templateCode", target = "templateCode") + @Mapping(source = "templateParams", target = "templateParams") SmsSendSingleToUserReqDTO convert(Long userId, String templateCode, Map templateParams); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOALeaveConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOALeaveConvert.java index f87531bfc..8c56e1dda 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOALeaveConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOALeaveConvert.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.bpm.convert.oa; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveRespVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java index 91d405925..a4ba5cc85 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.convert.task; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePageItemRespVO; @@ -151,7 +152,7 @@ public interface BpmTaskConvert { BpmTaskExtDO taskExtDO = new BpmTaskExtDO().setTaskId(task.getId()) .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setName(task.getName()) .setProcessDefinitionId(task.getProcessDefinitionId()).setProcessInstanceId(task.getProcessInstanceId()); - taskExtDO.setCreateTime(task.getCreateTime()); + taskExtDO.setCreateTime(LocalDateTimeUtil.of(task.getCreateTime())); return taskExtDO; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java index 31381a556..92c7c154c 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.oa; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import lombok.*; + +import java.time.LocalDateTime; import java.util.*; import com.baomidou.mybatisplus.annotation.*; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @@ -46,11 +48,11 @@ public class BpmOALeaveDO extends BaseDO { /** * 开始时间 */ - private Date startTime; + private LocalDateTime startTime; /** * 结束时间 */ - private Date endTime; + private LocalDateTime endTime; /** * 请假天数 */ diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java index 183a04147..190fcf5ed 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import lombok.*; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; @@ -80,14 +80,14 @@ public class BpmActivityDO { */ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private Date startTime; + private LocalDateTime startTime; /** * 任务结束时间 */ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private Date endTime; + private LocalDateTime endTime; private Integer transactionOrder; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java index b37709962..293cc2dd7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java @@ -11,7 +11,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; import java.util.Map; /** @@ -79,7 +79,7 @@ public class BpmProcessInstanceExtDO extends BaseDO { * * 冗余 HistoricProcessInstance 的 endTime 属性 */ - private Date endTime; + private LocalDateTime endTime; /** * 提交的表单值 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java index 5c6b70fc3..a79fce412 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; /** * Bpm 流程任务的拓展表 @@ -67,7 +67,7 @@ public class BpmTaskExtDO extends BaseDO { * * 冗余 HistoricTaskInstance 的 endTime 属性 */ - private Date endTime; + private LocalDateTime endTime; /** * 流程实例的编号 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java index d0aadd95e..33d178901 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.bpm.service.oa; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; @@ -46,7 +47,7 @@ public class BpmOALeaveServiceImpl implements BpmOALeaveService { @Transactional(rollbackFor = Exception.class) public Long createLeave(Long userId, BpmOALeaveCreateReqVO createReqVO) { // 插入 OA 请假单 - long day = DateUtil.betweenDay(createReqVO.getStartTime(), createReqVO.getEndTime(), false); + long day = LocalDateTimeUtil.between(createReqVO.getStartTime(), createReqVO.getEndTime()).toDays(); BpmOALeaveDO leave = BpmOALeaveConvert.INSTANCE.convert(createReqVO).setUserId(userId).setDay(day) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); leaveMapper.insert(leave); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 076ecd8fc..a7468ac4f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -1 +1 @@ -package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. * * HistoricProcessInstance & ProcessInstance 的关系: * 1. * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())).getCheckedData(); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()).getCheckedData(); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables)); return instance.getId(); } } \ No newline at end of file +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. * * HistoricProcessInstance & ProcessInstance 的关系: * 1. * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())).getCheckedData(); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()).getCheckedData(); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables)); return instance.getId(); } } \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index b2c12bd2b..28862b0d2 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; @@ -32,6 +33,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager import javax.annotation.Resource; import javax.validation.Valid; +import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -74,10 +76,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { taskQuery.taskNameLike("%" + pageVO.getName() + "%"); } if (pageVO.getBeginCreateTime() != null) { - taskQuery.taskCreatedAfter(pageVO.getBeginCreateTime()); + taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getBeginCreateTime())); } if (pageVO.getEndCreateTime() != null) { - taskQuery.taskCreatedBefore(pageVO.getEndCreateTime()); + taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getEndCreateTime())); } // 执行查询 List tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); @@ -106,10 +108,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { taskQuery.taskNameLike("%" + pageVO.getName() + "%"); } if (pageVO.getBeginCreateTime() != null) { - taskQuery.taskCreatedAfter(pageVO.getBeginCreateTime()); + taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getBeginCreateTime())); } if (pageVO.getEndCreateTime() != null) { - taskQuery.taskCreatedBefore(pageVO.getEndCreateTime()); + taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getEndCreateTime())); } // 执行查询 List tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); @@ -205,7 +207,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { // 更新任务拓展表为不通过 taskExtMapper.updateByTaskId( new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult()) - .setEndTime(new Date()).setReason(reqVO.getReason())); + .setEndTime(LocalDateTime.now()).setReason(reqVO.getReason())); } @Override @@ -249,7 +251,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { public void updateTaskExtComplete(Task task) { BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()) // 不设置也问题不大,因为 Complete 一般是审核通过,已经设置 - .setEndTime(new Date()); + .setEndTime(LocalDateTime.now()); taskExtMapper.updateByTaskId(taskExtDO); } @@ -280,7 +282,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { // 更新任务 taskExtMapper.updateById(new BpmTaskExtDO().setId(taskExt.getId()).setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()) - .setEndTime(new Date()).setReason(BpmProcessInstanceDeleteReasonEnum.translateReason(task.getDeleteReason()))); + .setEndTime(LocalDateTime.now()).setReason(BpmProcessInstanceDeleteReasonEnum.translateReason(task.getDeleteReason()))); } }); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml index f629bed50..677656171 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml @@ -16,7 +16,7 @@ spring: # Jackson 配置项 jackson: serialization: - write-dates-as-timestamps: true # 设置 Date 的格式,使用时间戳 + write-dates-as-timestamps: true # 设置 LocalDateTime 的格式,使用时间戳 write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401 write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 fail-on-empty-beans: false # 允许序列化无属性的 Bean diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java index 886677771..9e266ebdd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java @@ -41,6 +41,8 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { // mock 方法(startUser) AdminUserRespDTO startUser = randomPojo(AdminUserRespDTO.class, o -> o.setDeptId(10L)); when(adminUserApi.getUser(eq(1L))).thenReturn(success(startUser)); + // mock 方法(getStartUserDept)没有部门 + when(deptApi.getDept(eq(10L))).thenReturn(success(null)); // 调用 Set result = script.calculateTaskCandidateUsers(execution); @@ -57,7 +59,9 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { when(adminUserApi.getUser(eq(1L))).thenReturn(success(startUser)); DeptRespDTO startUserDept = randomPojo(DeptRespDTO.class, o -> o.setId(10L).setParentId(100L) .setLeaderUserId(20L)); + // mock 方法(getDept) when(deptApi.getDept(eq(10L))).thenReturn(success(startUserDept)); + when(deptApi.getDept(eq(100L))).thenReturn(success(null)); // 调用 Set result = script.calculateTaskCandidateUsers(execution); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java index 1053c95e1..6fb9d91a1 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java @@ -17,8 +17,9 @@ import org.springframework.context.annotation.Import; import javax.annotation.Resource; -import java.util.Date; +import java.time.LocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.USER_GROUP_NOT_EXISTS; @@ -106,7 +107,7 @@ public class BpmUserGroupServiceTest extends BaseDbUnitTest { BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class, o -> { // 等会查询到 o.setName("芋道源码"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(DateUtils.buildTime(2021, 11, 11)); + o.setCreateTime(buildLocalDateTime(2021, 11, 11)); }); userGroupMapper.insert(dbUserGroup); // 测试 name 不匹配 @@ -114,12 +115,13 @@ public class BpmUserGroupServiceTest extends BaseDbUnitTest { // 测试 status 不匹配 userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 createTime 不匹配 - userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setCreateTime(DateUtils.buildTime(2021, 12, 12)))); + userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setCreateTime(buildLocalDateTime(2021, 12, 12)))); // 准备参数 BpmUserGroupPageReqVO reqVO = new BpmUserGroupPageReqVO(); reqVO.setName("源码"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new Date[]{buildTime(2021, 11, 10),buildTime(2021, 11, 12)})); + reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 10), + buildLocalDateTime(2021, 11, 12)})); // 调用 PageResult pageResult = userGroupService.getUserGroupPage(reqVO); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml b/yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml index 25bfe0a62..e7dcccdab 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml @@ -23,6 +23,9 @@ spring: mybatis-plus: lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + global-config: + db-config: + id-type: AUTO # H2 主键递增 --- #################### 定时任务相关配置 #################### diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiAccessLogCreateReqDTO.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiAccessLogCreateReqDTO.java index eac503b22..f4e8e6495 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiAccessLogCreateReqDTO.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiAccessLogCreateReqDTO.java @@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("RPC 服务 - API 访问日志创建 Request DTO") @Data @@ -40,10 +40,10 @@ public class ApiAccessLogCreateReqDTO { @ApiModelProperty(value = "开始时间", required = true) @NotNull(message = "开始请求时间不能为空") - private Date beginTime; + private LocalDateTime beginTime; @ApiModelProperty(value = "结束时间", required = true) @NotNull(message = "结束请求时间不能为空") - private Date endTime; + private LocalDateTime endTime; @ApiModelProperty(value = "执行时长,单位:毫秒", required = true) @NotNull(message = "执行时长不能为空") private Integer duration; diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiErrorLogCreateReqDTO.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiErrorLogCreateReqDTO.java index 2da5046c2..06aab01b5 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiErrorLogCreateReqDTO.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiErrorLogCreateReqDTO.java @@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("RPC 服务 - API 错误日志创建 Request DTO") @Data @@ -40,7 +40,7 @@ public class ApiErrorLogCreateReqDTO { @ApiModelProperty(value = "异常时间", required = true) @NotNull(message = "异常时间不能为空") - private Date exceptionTime; + private LocalDateTime exceptionTime; @ApiModelProperty(value = "异常名", required = true) @NotNull(message = "异常名不能为空") private String exceptionName; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnRespVO.java index 36dd3a05c..125b71801 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnRespVO.java @@ -6,7 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - 代码生成字段定义 Response VO") @Data @@ -18,6 +18,6 @@ public class CodegenColumnRespVO extends CodegenColumnBaseVO { private Long id; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java index adff119b0..bf940c995 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -26,6 +26,6 @@ public class CodegenTablePageReqVO extends PageParam { @ApiModelProperty(value = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date[] createTime; + private LocalDateTime[] createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableRespVO.java index bd1004bc7..7ef96b9a8 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableRespVO.java @@ -6,7 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - 代码生成表定义 Response VO") @Data @@ -21,9 +21,9 @@ public class CodegenTableRespVO extends CodegenTableBaseVO { private Integer dataSourceConfigId; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; @ApiModelProperty(value = "更新时间", required = true) - private Date updateTime; + private LocalDateTime updateTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java index af63aa0dd..134b2b2f1 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.db.vo; import lombok.*; + +import java.time.LocalDateTime; import java.util.*; import io.swagger.annotations.*; @@ -14,6 +16,6 @@ public class DataSourceConfigRespVO extends DataSourceConfigBaseVO { private Integer id; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java index 3752b37c5..f8ea275f3 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -26,6 +26,6 @@ public class FileConfigPageReqVO extends PageParam { @ApiModelProperty(value = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date[] createTime; + private LocalDateTime[] createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java index 74291925b..c2341e486 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - 文件配置 Response VO") @Data @@ -31,6 +31,6 @@ public class FileConfigRespVO extends FileConfigBaseVO { private FileClientConfig config; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java index 0ae43bbe0..774ed4f39 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -26,6 +26,6 @@ public class FilePageReqVO extends PageParam { @ApiModelProperty(value = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date[] createTime; + private LocalDateTime[] createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java index 8e39a7520..ff51725bf 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java @@ -4,7 +4,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel(value = "管理后台 - 文件 Response VO", description = "不返回 content 字段,太大") @Data @@ -26,6 +26,6 @@ public class FileRespVO { private Integer size; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java index 619dea65a..077f26133 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java @@ -5,7 +5,7 @@ import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -54,12 +54,12 @@ public class ApiAccessLogBaseVO { @ApiModelProperty(value = "开始请求时间", required = true) @NotNull(message = "开始请求时间不能为空") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date beginTime; + private LocalDateTime beginTime; @ApiModelProperty(value = "结束请求时间", required = true) @NotNull(message = "结束请求时间不能为空") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date endTime; + private LocalDateTime endTime; @ApiModelProperty(value = "执行时长", required = true, example = "100") @NotNull(message = "执行时长不能为空") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExcelVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExcelVO.java index 5c1995c6a..21447743d 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExcelVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExcelVO.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; -import java.util.Date; +import java.time.LocalDateTime; /** * API 访问日志 Excel VO @@ -48,10 +48,10 @@ public class ApiAccessLogExcelVO { private String userAgent; @ExcelProperty("开始请求时间") - private Date beginTime; + private LocalDateTime beginTime; @ExcelProperty("结束请求时间") - private Date endTime; + private LocalDateTime endTime; @ExcelProperty("执行时长") private Integer duration; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java index dc2ef8714..406446d98 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java @@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -27,7 +27,7 @@ public class ApiAccessLogExportReqVO { @ApiModelProperty(value = "开始时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date[] beginTime; + private LocalDateTime[] beginTime; @ApiModelProperty(value = "执行时长", example = "100", notes = "大于等于,单位:毫秒") private Integer duration; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java index 97ff8e949..a141a758b 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -32,7 +32,7 @@ public class ApiAccessLogPageReqVO extends PageParam { @ApiModelProperty(value = "开始时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date[] beginTime; + private LocalDateTime[] beginTime; @ApiModelProperty(value = "执行时长", example = "100", notes = "大于等于,单位:毫秒") private Integer duration; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java index 0458affb0..2a6125d38 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java @@ -6,7 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - API 访问日志 Response VO") @Data @@ -18,6 +18,6 @@ public class ApiAccessLogRespVO extends ApiAccessLogBaseVO { private Long id; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogBaseVO.java index 08fbdace8..ad0b44368 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogBaseVO.java @@ -5,7 +5,7 @@ import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -55,7 +55,7 @@ public class ApiErrorLogBaseVO { @ApiModelProperty(value = "异常发生时间", required = true) @NotNull(message = "异常发生时间不能为空") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date exceptionTime; + private LocalDateTime exceptionTime; @ApiModelProperty(value = "异常名", required = true) @NotNull(message = "异常名不能为空") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExcelVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExcelVO.java index 7e1e2ef0c..08f10894f 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExcelVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExcelVO.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; -import java.util.Date; +import java.time.LocalDateTime; /** * API 错误日志 Excel VO @@ -48,7 +48,7 @@ public class ApiErrorLogExcelVO { private String userAgent; @ExcelProperty("异常发生时间") - private Date exceptionTime; + private LocalDateTime exceptionTime; @ExcelProperty("异常名") private String exceptionName; @@ -75,14 +75,14 @@ public class ApiErrorLogExcelVO { private Integer exceptionLineNumber; @ExcelProperty("创建时间") - private Date createTime; + private LocalDateTime createTime; @ExcelProperty(value = "处理状态", converter = DictConvert.class) @DictFormat(DictTypeConstants.API_ERROR_LOG_PROCESS_STATUS) private Integer processStatus; @ExcelProperty("处理时间") - private Date processTime; + private LocalDateTime processTime; @ExcelProperty("处理用户编号") private Integer processUserId; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java index d8e121e0b..e2c241138 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java @@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -27,7 +27,7 @@ public class ApiErrorLogExportReqVO { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ApiModelProperty(value = "异常发生时间") - private Date[] exceptionTime; + private LocalDateTime[] exceptionTime; @ApiModelProperty(value = "处理状态", example = "0") private Integer processStatus; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java index fda23ba14..56496325d 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -32,7 +32,7 @@ public class ApiErrorLogPageReqVO extends PageParam { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ApiModelProperty(value = "异常发生时间") - private Date[] exceptionTime; + private LocalDateTime[] exceptionTime; @ApiModelProperty(value = "处理状态", example = "0") private Integer processStatus; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java index 0f0c2724d..c108b548c 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java @@ -6,7 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.Date; +import java.time.LocalDateTime; @ApiModel("管理后台 - API 错误日志 Response VO") @Data @@ -18,10 +18,10 @@ public class ApiErrorLogRespVO extends ApiErrorLogBaseVO { private Integer id; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; @ApiModelProperty(value = "处理时间", required = true) - private Date processTime; + private LocalDateTime processTime; @ApiModelProperty(value = "处理用户编号", example = "233") private Integer processUserId; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExcelVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExcelVO.java index e87d89586..d255c86d5 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExcelVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExcelVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.test.vo; import lombok.*; + +import java.time.LocalDateTime; import java.util.*; import io.swagger.annotations.*; @@ -33,6 +35,6 @@ public class TestDemoExcelVO { private String remark; @ExcelProperty("创建时间") - private Date createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java index 8836919a6..c685bffa7 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java @@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -30,6 +30,6 @@ public class TestDemoExportReqVO { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ApiModelProperty(value = "创建时间") - private Date[] createTime; + private LocalDateTime[] createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoPageReqVO.java index 0ee9e060c..be68e57a6 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoPageReqVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -35,6 +35,6 @@ public class TestDemoPageReqVO extends PageParam { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ApiModelProperty(value = "创建时间") - private Date[] createTime; + private LocalDateTime[] createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoRespVO.java index 56d6b0a11..93f5aecca 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoRespVO.java @@ -1,8 +1,12 @@ package cn.iocoder.yudao.module.infra.controller.admin.test.vo; -import lombok.*; -import java.util.*; -import io.swagger.annotations.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; @ApiModel("管理后台 - 字典类型 Response VO") @Data @@ -14,6 +18,6 @@ public class TestDemoRespVO extends TestDemoBaseVO { private Long id; @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java index 03a433f96..ab4292bf9 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java @@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; -import java.util.Date; +import java.time.LocalDateTime; /** * API 访问日志 @@ -84,11 +84,11 @@ public class ApiAccessLogDO extends BaseDO { /** * 开始请求时间 */ - private Date beginTime; + private LocalDateTime beginTime; /** * 结束请求时间 */ - private Date endTime; + private LocalDateTime endTime; /** * 执行时长,单位:毫秒 */ diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiErrorLogDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiErrorLogDO.java index 524e8a2eb..7dc040981 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiErrorLogDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiErrorLogDO.java @@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; -import java.util.Date; +import java.time.LocalDateTime; /** * API 异常数据 @@ -84,7 +84,7 @@ public class ApiErrorLogDO extends BaseDO { /** * 异常发生时间 */ - private Date exceptionTime; + private LocalDateTime exceptionTime; /** * 异常名 * @@ -145,7 +145,7 @@ public class ApiErrorLogDO extends BaseDO { /** * 处理时间 */ - private Date processTime; + private LocalDateTime processTime; /** * 处理用户编号 * diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileConfigMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileConfigMapper.java index 69a1e1cd7..e770dcafd 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileConfigMapper.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileConfigMapper.java @@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; -import java.util.Date; +import java.time.LocalDateTime; /** * 文件配置 Mapper @@ -27,6 +27,6 @@ public interface FileConfigMapper extends BaseMapperX { } @Select("SELECT COUNT(*) FROM infra_file_config WHERE update_time > #{maxUpdateTime}") - Long selectCountByUpdateTimeGt(Date maxUpdateTime); + Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java index 9eb0a3a93..52014d514 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java @@ -53,7 +53,7 @@ public class DatabaseTableServiceImpl implements DatabaseTableService { if (StrUtil.isNotEmpty(name)) { strategyConfig.addInclude(name); } - GlobalConfig globalConfig = new GlobalConfig.Builder().dateType(DateType.ONLY_DATE).build(); // 只使用 Date 类型,不使用 LocalDate + GlobalConfig globalConfig = new GlobalConfig.Builder().dateType(DateType.ONLY_DATE).build(); // 只使用 LocalDateTime 类型,不使用 LocalDate ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, strategyConfig.build(), null, globalConfig, null); // 按照名字排序 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java index ea82c61b3..129889ef0 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java @@ -32,7 +32,7 @@ import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.validation.Validator; import java.util.Collection; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -60,7 +60,7 @@ public class FileConfigServiceImpl implements FileConfigService { * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 */ @Getter - private volatile Date maxUpdateTime; + private volatile LocalDateTime maxUpdateTime; @Resource private FileClientFactory fileClientFactory; @@ -118,7 +118,7 @@ public class FileConfigServiceImpl implements FileConfigService { * @param maxUpdateTime 当前文件配置的最大更新时间 * @return 文件配置列表 */ - private List loadFileConfigIfUpdate(Date maxUpdateTime) { + private List loadFileConfigIfUpdate(LocalDateTime maxUpdateTime) { // 第一步,判断是否要更新。 if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 log.info("[loadFileConfigIfUpdate][首次加载全量文件配置]"); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java index 7e0cc3d85..6d79f8754 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java @@ -16,7 +16,7 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; /** @@ -59,7 +59,7 @@ public class ApiErrorLogServiceImpl implements ApiErrorLogService { } // 标记处理 apiErrorLogMapper.updateById(ApiErrorLogDO.builder().id(id).processStatus(processStatus) - .processUserId(processUserId).processTime(new Date()).build()); + .processUserId(processUserId).processTime(LocalDateTime.now()).build()); } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml index b23c5710b..37977e898 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml @@ -16,7 +16,7 @@ spring: # Jackson 配置项 jackson: serialization: - write-dates-as-timestamps: true # 设置 Date 的格式,使用时间戳 + write-dates-as-timestamps: true # 设置 LocalDateTime 的格式,使用时间戳 write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401 write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 fail-on-empty-beans: false # 允许序列化无属性的 Bean diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/_column.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/_column.vm index 2e2222509..69477d433 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/_column.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/_column.vm @@ -7,7 +7,7 @@ @NotNull(message = "${column.columnComment}不能为空") #end #end -#if (${column.javaType} == "Date")## 时间类型 +#if (${column.javaType} == "LocalDateTime")## 时间类型 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) #end private ${column.javaType} ${column.javaField}; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/baseVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/baseVO.vm index 8b9fbaac2..a0ad48d60 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/baseVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/baseVO.vm @@ -5,7 +5,9 @@ import java.util.*; #foreach ($column in $columns) #if (${column.javaType} == "BigDecimal") import java.math.BigDecimal; -#break +#end +#if (${column.javaType} == "LocalDateTime") +import java.time.LocalDateTime; #end #end import io.swagger.annotations.*; @@ -13,7 +15,7 @@ import javax.validation.constraints.*; ## 处理 Date 字段的引入 #foreach ($column in $columns) #if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult} - && ${column.javaType} == "Date")## 时间类型 + && ${column.javaType} == "LocalDateTime")## 时间类型 import org.springframework.format.annotation.DateTimeFormat; import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm index ca13efac5..dc6cee6b6 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm @@ -7,7 +7,7 @@ import javax.validation.constraints.*; ## 处理 Date 字段的引入 #foreach ($column in $columns) #if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult}) - && ${column.javaType} == "Date")## 时间类型 + && ${column.javaType} == "LocalDateTime")## 时间类型 import org.springframework.format.annotation.DateTimeFormat; import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/excelVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/excelVO.vm index 6b3ea2467..8bfd92b69 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/excelVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/excelVO.vm @@ -5,7 +5,9 @@ import java.util.*; #foreach ($column in $columns) #if (${column.javaType} == "BigDecimal") import java.math.BigDecimal; -#break +#end +#if (${column.javaType} == "LocalDateTime") +import java.time.LocalDateTime; #end #end import io.swagger.annotations.*; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/exportReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/exportReqVO.vm index afd583c28..cd68dd82e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/exportReqVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/exportReqVO.vm @@ -6,7 +6,8 @@ import io.swagger.annotations.*; import ${PageParamClassName}; ## 处理 Date 字段的引入 #foreach ($column in $columns) -#if (${column.listOperation} && ${column.javaType} == "Date")## 时间类型 +#if (${column.listOperation} && ${column.javaType} == "LocalDateTime")## 时间类型 +import java.time.LocalDateTime; import org.springframework.format.annotation.DateTimeFormat; import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/pageReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/pageReqVO.vm index df2be7036..f2664390a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/pageReqVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/pageReqVO.vm @@ -6,8 +6,9 @@ import io.swagger.annotations.*; import ${PageParamClassName}; ## 处理 Date 字段的引入 #foreach ($column in $columns) -#if (${column.listOperation} && ${column.javaType} == "Date")## 时间类型 +#if (${column.listOperation} && ${column.javaType} == "LocalDateTime")## 时间类型 import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; #break diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/updateReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/updateReqVO.vm index c6057d55a..636991508 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/updateReqVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/updateReqVO.vm @@ -7,9 +7,9 @@ import javax.validation.constraints.*; ## 处理 Date 字段的引入 #foreach ($column in $columns) #if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult}) - && ${column.javaType} == "Date")## 时间类型 + && ${column.javaType} == "LocalDateTime")## 时间类型 import org.springframework.format.annotation.DateTimeFormat; - +import java.time.LocalDateTime; import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; #break #end diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do.vm index 4abae1591..d551d4b30 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do.vm @@ -5,7 +5,9 @@ import java.util.*; #foreach ($column in $columns) #if (${column.javaType} == "BigDecimal") import java.math.BigDecimal; -#break +#end +#if (${column.javaType} == "LocalDateTime") +import java.time.LocalDateTime; #end #end import com.baomidou.mybatisplus.annotation.*; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm index 1b5c60a3f..e97fbb275 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm @@ -16,6 +16,7 @@ import ${PageResultClassName}; import javax.annotation.Resource; import org.springframework.context.annotation.Import; import java.util.*; +import java.time.LocalDateTime; import static cn.hutool.core.util.RandomUtil.*; import static ${basePackage}.module.${table.moduleName}.enums.ErrorCodeConstants.*; @@ -51,7 +52,7 @@ import static org.mockito.Mockito.*; #if (${column.listOperation}) #set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写 #if (${column.listOperationCondition} == "BETWEEN")## BETWEEN 的情况 - reqVO.set${JavaField}((new Date[]{})); + reqVO.set${JavaField}((new LocalDateTime[]{})); #else reqVO.set$JavaField(null); #end diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm index c84a510ac..7a6add604 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm @@ -65,15 +65,15 @@ #set ($javaField = $column.javaField) #set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($comment=$column.columnComment) -#if ($column.javaType == "Date")## 时间类型 +#if ($column.javaType == "LocalDateTime")## 时间类型 -