ai-engineering-init 1.3.4 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/skill-forced-eval.js +2 -0
- package/.claude/settings.json +3 -3
- package/.claude/skills/add-skill/SKILL.md +79 -32
- package/.claude/skills/api-development/SKILL.md +83 -377
- package/.claude/skills/architecture-design/SKILL.md +138 -632
- package/.claude/skills/backend-annotations/SKILL.md +134 -506
- package/.claude/skills/banana-image/SKILL.md +10 -3
- package/.claude/skills/brainstorm/SKILL.md +103 -535
- package/.claude/skills/bug-detective/SKILL.md +147 -1097
- package/.claude/skills/bug-detective/references/error-patterns.md +242 -0
- package/.claude/skills/code-patterns/SKILL.md +116 -426
- package/.claude/skills/code-patterns/references/leniu-code-patterns.md +87 -0
- package/.claude/skills/crud-development/SKILL.md +64 -304
- package/.claude/skills/data-permission/SKILL.md +105 -412
- package/.claude/skills/data-permission/references/custom-data-scope.md +90 -0
- package/.claude/skills/file-oss-management/SKILL.md +106 -714
- package/.claude/skills/file-oss-management/references/entities.md +105 -0
- package/.claude/skills/file-oss-management/references/service-impl.md +104 -0
- package/.claude/skills/leniu-api-development/SKILL.md +142 -626
- package/.claude/skills/leniu-api-development/references/real-examples.md +273 -0
- package/.claude/skills/leniu-architecture-design/SKILL.md +176 -391
- package/.claude/skills/leniu-backend-annotations/SKILL.md +132 -519
- package/.claude/skills/leniu-brainstorm/SKILL.md +132 -541
- package/.claude/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
- package/.claude/skills/leniu-crud-development/SKILL.md +232 -938
- package/.claude/skills/leniu-crud-development/references/templates.md +597 -0
- package/.claude/skills/leniu-customization-location/SKILL.md +410 -0
- package/.claude/skills/leniu-data-permission/SKILL.md +70 -0
- package/.claude/skills/leniu-java-entity/SKILL.md +76 -590
- package/.claude/skills/leniu-java-entity/references/templates.md +237 -0
- package/.claude/skills/leniu-java-export/SKILL.md +94 -379
- package/.claude/skills/leniu-java-logging/SKILL.md +106 -709
- package/.claude/skills/leniu-java-logging/references/data-mask.md +46 -0
- package/.claude/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
- package/.claude/skills/leniu-java-mybatis/SKILL.md +73 -446
- package/.claude/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
- package/.claude/skills/leniu-report-customization/SKILL.md +111 -365
- package/.claude/skills/leniu-report-customization/references/table-fields.md +93 -0
- package/.claude/skills/leniu-report-standard-customization/SKILL.md +111 -334
- package/.claude/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
- package/.claude/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
- package/.claude/skills/leniu-security-guard/SKILL.md +133 -347
- package/.claude/skills/mysql-debug/SKILL.md +364 -0
- package/.claude/skills/openspec-apply-change/SKILL.md +10 -1
- package/.claude/skills/openspec-archive-change/SKILL.md +9 -1
- package/.claude/skills/openspec-bulk-archive-change/SKILL.md +9 -1
- package/.claude/skills/openspec-continue-change/SKILL.md +9 -1
- package/.claude/skills/openspec-explore/SKILL.md +10 -1
- package/.claude/skills/openspec-ff-change/SKILL.md +9 -1
- package/.claude/skills/openspec-new-change/SKILL.md +9 -1
- package/.claude/skills/openspec-onboard/SKILL.md +15 -130
- package/.claude/skills/openspec-sync-specs/SKILL.md +9 -1
- package/.claude/skills/openspec-verify-change/SKILL.md +9 -1
- package/.claude/skills/performance-doctor/SKILL.md +110 -434
- package/.claude/skills/redis-cache/SKILL.md +89 -595
- package/.claude/skills/redis-cache/references/listeners.md +23 -0
- package/.claude/skills/scheduled-jobs/SKILL.md +88 -407
- package/.claude/skills/security-guard/SKILL.md +137 -532
- package/.claude/skills/security-guard/references/encrypt-config.md +103 -0
- package/.claude/skills/security-guard/references/sensitive-strategies.md +42 -0
- package/.claude/skills/sms-mail/SKILL.md +116 -574
- package/.claude/skills/sms-mail/references/mail-config.md +88 -0
- package/.claude/skills/sms-mail/references/sms-config.md +74 -0
- package/.claude/skills/social-login/SKILL.md +112 -514
- package/.claude/skills/social-login/references/provider-configs.md +118 -0
- package/.claude/skills/tenant-management/SKILL.md +129 -444
- package/.claude/skills/tenant-management/references/tenant-scenarios.md +91 -0
- package/.claude/skills/test-development/SKILL.md +86 -540
- package/.claude/skills/test-development/references/parameterized-examples.md +119 -0
- package/.claude/skills/utils-toolkit/SKILL.md +52 -305
- package/.claude/skills/utils-toolkit/references/redis-utils-api.md +56 -0
- package/.claude/skills/websocket-sse/SKILL.md +105 -550
- package/.claude/skills/workflow-engine/SKILL.md +147 -502
- package/.codex/skills/add-skill/SKILL.md +79 -32
- package/.codex/skills/api-development/SKILL.md +172 -599
- package/.codex/skills/architecture-design/SKILL.md +138 -504
- package/.codex/skills/backend-annotations/SKILL.md +134 -496
- package/.codex/skills/banana-image/SKILL.md +10 -3
- package/.codex/skills/brainstorm/SKILL.md +103 -535
- package/.codex/skills/bug-detective/SKILL.md +147 -1097
- package/.codex/skills/bug-detective/references/error-patterns.md +242 -0
- package/.codex/skills/code-patterns/SKILL.md +120 -282
- package/.codex/skills/code-patterns/references/leniu-code-patterns.md +87 -0
- package/.codex/skills/crud-development/SKILL.md +64 -292
- package/.codex/skills/data-permission/SKILL.md +108 -407
- package/.codex/skills/data-permission/references/custom-data-scope.md +90 -0
- package/.codex/skills/database-ops/SKILL.md +8 -154
- package/.codex/skills/error-handler/SKILL.md +10 -0
- package/.codex/skills/file-oss-management/SKILL.md +106 -714
- package/.codex/skills/file-oss-management/references/entities.md +105 -0
- package/.codex/skills/file-oss-management/references/service-impl.md +104 -0
- package/.codex/skills/git-workflow/SKILL.md +27 -5
- package/.codex/skills/leniu-api-development/SKILL.md +142 -626
- package/.codex/skills/leniu-api-development/references/real-examples.md +273 -0
- package/.codex/skills/leniu-architecture-design/SKILL.md +176 -391
- package/.codex/skills/leniu-backend-annotations/SKILL.md +132 -519
- package/.codex/skills/leniu-brainstorm/SKILL.md +132 -541
- package/.codex/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
- package/.codex/skills/leniu-crud-development/SKILL.md +232 -938
- package/.codex/skills/leniu-crud-development/references/templates.md +597 -0
- package/.codex/skills/leniu-customization-location/SKILL.md +410 -0
- package/.codex/skills/leniu-data-permission/SKILL.md +70 -0
- package/.codex/skills/leniu-java-code-style/SKILL.md +510 -0
- package/.codex/skills/leniu-java-entity/SKILL.md +76 -590
- package/.codex/skills/leniu-java-entity/references/templates.md +237 -0
- package/.codex/skills/leniu-java-export/SKILL.md +94 -379
- package/.codex/skills/leniu-java-logging/SKILL.md +106 -709
- package/.codex/skills/leniu-java-logging/references/data-mask.md +46 -0
- package/.codex/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
- package/.codex/skills/leniu-java-mybatis/SKILL.md +73 -446
- package/.codex/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
- package/.codex/skills/leniu-report-customization/SKILL.md +111 -365
- package/.codex/skills/leniu-report-customization/references/table-fields.md +93 -0
- package/.codex/skills/leniu-report-standard-customization/SKILL.md +111 -334
- package/.codex/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
- package/.codex/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
- package/.codex/skills/leniu-security-guard/SKILL.md +133 -347
- package/.codex/skills/mysql-debug/SKILL.md +364 -0
- package/.codex/skills/openspec-apply-change/SKILL.md +10 -1
- package/.codex/skills/openspec-archive-change/SKILL.md +9 -1
- package/.codex/skills/openspec-bulk-archive-change/SKILL.md +9 -1
- package/.codex/skills/openspec-continue-change/SKILL.md +9 -1
- package/.codex/skills/openspec-explore/SKILL.md +10 -1
- package/.codex/skills/openspec-ff-change/SKILL.md +9 -1
- package/.codex/skills/openspec-new-change/SKILL.md +9 -1
- package/.codex/skills/openspec-onboard/SKILL.md +15 -130
- package/.codex/skills/openspec-sync-specs/SKILL.md +9 -1
- package/.codex/skills/openspec-verify-change/SKILL.md +9 -1
- package/.codex/skills/performance-doctor/SKILL.md +110 -434
- package/.codex/skills/project-navigator/SKILL.md +20 -1
- package/.codex/skills/redis-cache/SKILL.md +93 -589
- package/.codex/skills/redis-cache/references/listeners.md +23 -0
- package/.codex/skills/scheduled-jobs/SKILL.md +88 -407
- package/.codex/skills/security-guard/SKILL.md +141 -527
- package/.codex/skills/security-guard/references/encrypt-config.md +103 -0
- package/.codex/skills/security-guard/references/sensitive-strategies.md +42 -0
- package/.codex/skills/sms-mail/SKILL.md +116 -574
- package/.codex/skills/sms-mail/references/mail-config.md +88 -0
- package/.codex/skills/sms-mail/references/sms-config.md +74 -0
- package/.codex/skills/social-login/SKILL.md +112 -514
- package/.codex/skills/social-login/references/provider-configs.md +118 -0
- package/.codex/skills/store-pc/SKILL.md +258 -383
- package/.codex/skills/tenant-management/SKILL.md +129 -444
- package/.codex/skills/tenant-management/references/tenant-scenarios.md +91 -0
- package/.codex/skills/test-development/SKILL.md +86 -540
- package/.codex/skills/test-development/references/parameterized-examples.md +119 -0
- package/.codex/skills/ui-pc/SKILL.md +350 -387
- package/.codex/skills/utils-toolkit/SKILL.md +52 -283
- package/.codex/skills/utils-toolkit/references/redis-utils-api.md +56 -0
- package/.codex/skills/websocket-sse/SKILL.md +105 -550
- package/.codex/skills/workflow-engine/SKILL.md +147 -502
- package/.cursor/hooks/cursor-skill-eval.js +53 -1
- package/.cursor/hooks.json +3 -3
- package/.cursor/skills/add-skill/SKILL.md +79 -32
- package/.cursor/skills/api-development/SKILL.md +83 -377
- package/.cursor/skills/architecture-design/SKILL.md +138 -632
- package/.cursor/skills/backend-annotations/SKILL.md +134 -506
- package/.cursor/skills/banana-image/SKILL.md +10 -3
- package/.cursor/skills/brainstorm/SKILL.md +103 -535
- package/.cursor/skills/bug-detective/SKILL.md +147 -1097
- package/.cursor/skills/bug-detective/references/error-patterns.md +242 -0
- package/.cursor/skills/code-patterns/SKILL.md +116 -426
- package/.cursor/skills/code-patterns/references/leniu-code-patterns.md +87 -0
- package/.cursor/skills/crud-development/SKILL.md +64 -304
- package/.cursor/skills/data-permission/SKILL.md +105 -412
- package/.cursor/skills/data-permission/references/custom-data-scope.md +90 -0
- package/.cursor/skills/file-oss-management/SKILL.md +106 -714
- package/.cursor/skills/file-oss-management/references/entities.md +105 -0
- package/.cursor/skills/file-oss-management/references/service-impl.md +104 -0
- package/.cursor/skills/git-workflow/SKILL.md +27 -5
- package/.cursor/skills/leniu-api-development/SKILL.md +142 -626
- package/.cursor/skills/leniu-api-development/references/real-examples.md +273 -0
- package/.cursor/skills/leniu-architecture-design/SKILL.md +176 -391
- package/.cursor/skills/leniu-backend-annotations/SKILL.md +132 -519
- package/.cursor/skills/leniu-brainstorm/SKILL.md +132 -541
- package/.cursor/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
- package/.cursor/skills/leniu-crud-development/SKILL.md +232 -938
- package/.cursor/skills/leniu-crud-development/references/templates.md +597 -0
- package/.cursor/skills/leniu-customization-location/SKILL.md +410 -0
- package/.cursor/skills/leniu-data-permission/SKILL.md +70 -0
- package/.cursor/skills/leniu-java-code-style/SKILL.md +510 -0
- package/.cursor/skills/leniu-java-entity/SKILL.md +76 -590
- package/.cursor/skills/leniu-java-entity/references/templates.md +237 -0
- package/.cursor/skills/leniu-java-export/SKILL.md +94 -379
- package/.cursor/skills/leniu-java-logging/SKILL.md +106 -709
- package/.cursor/skills/leniu-java-logging/references/data-mask.md +46 -0
- package/.cursor/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
- package/.cursor/skills/leniu-java-mybatis/SKILL.md +73 -446
- package/.cursor/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
- package/.cursor/skills/leniu-report-customization/SKILL.md +111 -365
- package/.cursor/skills/leniu-report-customization/references/table-fields.md +93 -0
- package/.cursor/skills/leniu-report-standard-customization/SKILL.md +111 -334
- package/.cursor/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
- package/.cursor/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
- package/.cursor/skills/leniu-security-guard/SKILL.md +133 -347
- package/.cursor/skills/mysql-debug/SKILL.md +364 -0
- package/.cursor/skills/openspec-apply-change/SKILL.md +10 -1
- package/.cursor/skills/openspec-archive-change/SKILL.md +9 -1
- package/.cursor/skills/openspec-bulk-archive-change/SKILL.md +9 -1
- package/.cursor/skills/openspec-continue-change/SKILL.md +9 -1
- package/.cursor/skills/openspec-explore/SKILL.md +10 -1
- package/.cursor/skills/openspec-ff-change/SKILL.md +9 -1
- package/.cursor/skills/openspec-new-change/SKILL.md +9 -1
- package/.cursor/skills/openspec-onboard/SKILL.md +15 -130
- package/.cursor/skills/openspec-sync-specs/SKILL.md +9 -1
- package/.cursor/skills/openspec-verify-change/SKILL.md +9 -1
- package/.cursor/skills/performance-doctor/SKILL.md +110 -434
- package/.cursor/skills/redis-cache/SKILL.md +89 -595
- package/.cursor/skills/redis-cache/references/listeners.md +23 -0
- package/.cursor/skills/scheduled-jobs/SKILL.md +88 -407
- package/.cursor/skills/security-guard/SKILL.md +137 -532
- package/.cursor/skills/security-guard/references/encrypt-config.md +103 -0
- package/.cursor/skills/security-guard/references/sensitive-strategies.md +42 -0
- package/.cursor/skills/sms-mail/SKILL.md +116 -574
- package/.cursor/skills/sms-mail/references/mail-config.md +88 -0
- package/.cursor/skills/sms-mail/references/sms-config.md +74 -0
- package/.cursor/skills/social-login/SKILL.md +112 -514
- package/.cursor/skills/social-login/references/provider-configs.md +118 -0
- package/.cursor/skills/tenant-management/SKILL.md +129 -444
- package/.cursor/skills/tenant-management/references/tenant-scenarios.md +91 -0
- package/.cursor/skills/test-development/SKILL.md +86 -540
- package/.cursor/skills/test-development/references/parameterized-examples.md +119 -0
- package/.cursor/skills/utils-toolkit/SKILL.md +52 -305
- package/.cursor/skills/utils-toolkit/references/redis-utils-api.md +56 -0
- package/.cursor/skills/websocket-sse/SKILL.md +105 -550
- package/.cursor/skills/workflow-engine/SKILL.md +147 -502
- package/package.json +1 -1
|
@@ -5,15 +5,12 @@ description: |
|
|
|
5
5
|
|
|
6
6
|
触发场景:
|
|
7
7
|
- 对象转换(BO/VO/Entity)
|
|
8
|
-
-
|
|
9
|
-
- 集合流操作
|
|
8
|
+
- 字符串处理、集合流操作
|
|
10
9
|
- 树结构构建
|
|
11
|
-
- 日期时间处理
|
|
12
10
|
- Redis 缓存操作
|
|
13
11
|
- Excel 导入导出
|
|
14
|
-
- JSON 序列化
|
|
15
12
|
|
|
16
|
-
触发词:工具类、MapstructUtils、StringUtils、StreamUtils、TreeBuildUtils、DateUtils、RedisUtils、ExcelUtil、JsonUtils、LoginHelper、
|
|
13
|
+
触发词:工具类、MapstructUtils、StringUtils、StreamUtils、TreeBuildUtils、DateUtils、RedisUtils、ExcelUtil、JsonUtils、LoginHelper、convert、对象转换、集合操作、树结构、缓存
|
|
17
14
|
|
|
18
15
|
注意:
|
|
19
16
|
- 对象转换必须使用 MapstructUtils.convert(),禁止使用 BeanUtils。
|
|
@@ -22,8 +19,6 @@ description: |
|
|
|
22
19
|
|
|
23
20
|
# 后端工具类大全
|
|
24
21
|
|
|
25
|
-
> 本项目是纯后端项目,本文档专注于 Java 后端工具类。
|
|
26
|
-
|
|
27
22
|
## 快速索引
|
|
28
23
|
|
|
29
24
|
| 功能 | 工具类 | 包路径 | 常用方法 |
|
|
@@ -40,9 +35,6 @@ description: |
|
|
|
40
35
|
| 登录用户 | `LoginHelper` | `o.d.common.satoken.utils` | `getUserId()`, `getUsername()` |
|
|
41
36
|
| 业务异常 | `ServiceException` | `o.d.common.core.exception` | `throw new ServiceException()` |
|
|
42
37
|
| Spring容器 | `SpringUtils` | `o.d.common.core.utils` | `getBean()` |
|
|
43
|
-
| Hutool集合 | `CollUtil` | `cn.hutool.core.collection` | `isEmpty()`, `newArrayList()` |
|
|
44
|
-
| Hutool对象 | `ObjectUtil` | `cn.hutool.core.util` | `isNull()`, `isEmpty()` |
|
|
45
|
-
| ID生成 | `IdUtil` | `cn.hutool.core.util` | `getSnowflakeNextId()` |
|
|
46
38
|
|
|
47
39
|
> **包路径说明**: `o.d` = `org.dromara`
|
|
48
40
|
|
|
@@ -50,42 +42,29 @@ description: |
|
|
|
50
42
|
|
|
51
43
|
## 1. 对象转换 - MapstructUtils(必须使用!)
|
|
52
44
|
|
|
53
|
-
>
|
|
45
|
+
> **强制规范**: 禁止使用 `BeanUtils.copyProperties()`,必须使用 `MapstructUtils.convert()`
|
|
54
46
|
|
|
55
47
|
```java
|
|
56
48
|
import org.dromara.common.core.utils.MapstructUtils;
|
|
57
49
|
|
|
58
|
-
//
|
|
50
|
+
// 单个对象转换
|
|
59
51
|
XxxVo vo = MapstructUtils.convert(entity, XxxVo.class);
|
|
60
|
-
Xxx entity = MapstructUtils.convert(bo, Xxx.class);
|
|
61
52
|
|
|
62
|
-
//
|
|
53
|
+
// 集合转换
|
|
63
54
|
List<XxxVo> voList = MapstructUtils.convert(entityList, XxxVo.class);
|
|
64
55
|
|
|
65
|
-
//
|
|
56
|
+
// 转换到已有对象(合并属性)
|
|
66
57
|
XxxVo vo = MapstructUtils.convert(source, existingVo);
|
|
67
|
-
|
|
68
|
-
// ✅ Map 转 Bean
|
|
69
|
-
Xxx entity = MapstructUtils.convert(map, Xxx.class);
|
|
70
|
-
|
|
71
|
-
// ❌ 禁止使用 BeanUtils
|
|
72
|
-
// BeanUtils.copyProperties(source, target); // 禁止!
|
|
73
58
|
```
|
|
74
59
|
|
|
75
60
|
**配合 @AutoMapper 注解**:
|
|
76
61
|
|
|
77
62
|
```java
|
|
78
|
-
// 在 BO 类上声明映射关系
|
|
79
63
|
@AutoMapper(target = Xxx.class, reverseConvertGenerate = false)
|
|
80
|
-
public class XxxBo extends BaseEntity {
|
|
81
|
-
// ...
|
|
82
|
-
}
|
|
64
|
+
public class XxxBo extends BaseEntity { }
|
|
83
65
|
|
|
84
|
-
// 在 VO 类上声明映射关系
|
|
85
66
|
@AutoMapper(target = Xxx.class)
|
|
86
|
-
public class XxxVo implements Serializable {
|
|
87
|
-
// ...
|
|
88
|
-
}
|
|
67
|
+
public class XxxVo implements Serializable { }
|
|
89
68
|
```
|
|
90
69
|
|
|
91
70
|
---
|
|
@@ -95,40 +74,24 @@ public class XxxVo implements Serializable {
|
|
|
95
74
|
```java
|
|
96
75
|
import org.dromara.common.core.utils.StringUtils;
|
|
97
76
|
|
|
98
|
-
//
|
|
99
|
-
StringUtils.isBlank(str); // null / "" / 空白 都返回 true
|
|
100
|
-
StringUtils.isNotBlank(str);
|
|
101
|
-
StringUtils.isEmpty(str); // null / "" 返回 true
|
|
102
|
-
StringUtils.isNotEmpty(str);
|
|
103
|
-
|
|
104
|
-
// 格式化(占位符 {})
|
|
77
|
+
// 格式化(占位符 {})—— 项目特有
|
|
105
78
|
StringUtils.format("用户 {} 不存在", userId);
|
|
106
|
-
// 输出: "用户 123 不存在"
|
|
107
|
-
|
|
108
|
-
// 字符串分割
|
|
109
|
-
List<String> list = StringUtils.splitList("1,2,3"); // ["1", "2", "3"]
|
|
110
|
-
List<String> list = StringUtils.splitList("1|2|3", "|"); // 自定义分隔符
|
|
111
|
-
List<Long> ids = StringUtils.splitTo("1,2,3", Convert::toLong); // 转换类型
|
|
112
79
|
|
|
113
|
-
//
|
|
114
|
-
String
|
|
115
|
-
|
|
80
|
+
// 字符串分割/拼接 —— 项目特有
|
|
81
|
+
List<String> list = StringUtils.splitList("1,2,3");
|
|
82
|
+
List<Long> ids = StringUtils.splitTo("1,2,3", Convert::toLong);
|
|
83
|
+
String str = StringUtils.joinComma(list);
|
|
116
84
|
|
|
117
85
|
// 驼峰转换
|
|
118
86
|
StringUtils.toCamelCase("user_name"); // "userName"
|
|
119
87
|
StringUtils.toUnderScoreCase("userName"); // "user_name"
|
|
120
|
-
StringUtils.convertToCamelCase("user_name"); // "UserName" (首字母大写)
|
|
121
88
|
|
|
122
|
-
//
|
|
123
|
-
StringUtils.
|
|
124
|
-
|
|
125
|
-
// 路径匹配(Ant 风格)
|
|
126
|
-
StringUtils.isMatch("/api/**", "/api/user/list"); // true
|
|
89
|
+
// Ant 风格路径匹配
|
|
90
|
+
StringUtils.isMatch("/api/**", "/api/user/list");
|
|
127
91
|
StringUtils.matches("/api/user", Arrays.asList("/api/**", "/admin/**"));
|
|
128
92
|
|
|
129
93
|
// 左补零
|
|
130
|
-
StringUtils.padl(5, 3);
|
|
131
|
-
StringUtils.padl("ab", 5, '0'); // "000ab"
|
|
94
|
+
StringUtils.padl(5, 3); // "005"
|
|
132
95
|
```
|
|
133
96
|
|
|
134
97
|
---
|
|
@@ -139,40 +102,28 @@ StringUtils.padl("ab", 5, '0'); // "000ab"
|
|
|
139
102
|
import org.dromara.common.core.utils.StreamUtils;
|
|
140
103
|
|
|
141
104
|
// 过滤
|
|
142
|
-
List<User>
|
|
105
|
+
List<User> active = StreamUtils.filter(users, u -> "1".equals(u.getStatus()));
|
|
143
106
|
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
User user = StreamUtils.findFirstValue(users, u -> u.getId().equals(id)); // 返回 null 而非 Optional
|
|
107
|
+
// 查找
|
|
108
|
+
User user = StreamUtils.findFirstValue(users, u -> u.getId().equals(id));
|
|
147
109
|
|
|
148
|
-
//
|
|
110
|
+
// 提取属性
|
|
149
111
|
List<Long> ids = StreamUtils.toList(users, User::getId);
|
|
150
|
-
|
|
151
|
-
// 提取属性为 Set
|
|
152
112
|
Set<Long> deptIds = StreamUtils.toSet(users, User::getDeptId);
|
|
153
113
|
|
|
154
|
-
//
|
|
114
|
+
// 转 Map
|
|
155
115
|
Map<Long, User> userMap = StreamUtils.toIdentityMap(users, User::getId);
|
|
156
|
-
|
|
157
|
-
// 转为 Map(自定义 key 和 value)
|
|
158
116
|
Map<Long, String> nameMap = StreamUtils.toMap(users, User::getId, User::getName);
|
|
159
117
|
|
|
160
118
|
// 分组
|
|
161
|
-
Map<Long, List<User>>
|
|
162
|
-
|
|
163
|
-
// 双层分组
|
|
164
|
-
Map<Long, Map<String, List<User>>> map = StreamUtils.groupBy2Key(
|
|
165
|
-
users, User::getDeptId, User::getStatus
|
|
166
|
-
);
|
|
119
|
+
Map<Long, List<User>> grouped = StreamUtils.groupByKey(users, User::getDeptId);
|
|
167
120
|
|
|
168
121
|
// 拼接字符串
|
|
169
|
-
String names = StreamUtils.join(users, User::getName);
|
|
170
|
-
String names = StreamUtils.join(users, User::getName, "|");
|
|
122
|
+
String names = StreamUtils.join(users, User::getName); // "张三,李四,王五"
|
|
123
|
+
String names = StreamUtils.join(users, User::getName, "|"); // 自定义分隔符
|
|
171
124
|
|
|
172
|
-
// 排序
|
|
125
|
+
// 排序 / 合并 Map
|
|
173
126
|
List<User> sorted = StreamUtils.sorted(users, Comparator.comparing(User::getCreateTime));
|
|
174
|
-
|
|
175
|
-
// 合并两个 Map
|
|
176
127
|
Map<Long, String> merged = StreamUtils.merge(map1, map2, (v1, v2) -> v1 + v2);
|
|
177
128
|
```
|
|
178
129
|
|
|
@@ -184,36 +135,16 @@ Map<Long, String> merged = StreamUtils.merge(map1, map2, (v1, v2) -> v1 + v2);
|
|
|
184
135
|
import org.dromara.common.core.utils.TreeBuildUtils;
|
|
185
136
|
import cn.hutool.core.lang.tree.Tree;
|
|
186
137
|
|
|
187
|
-
// 构建树(自动检测根节点)
|
|
188
138
|
List<Tree<Long>> tree = TreeBuildUtils.build(list, (node, item) -> {
|
|
189
139
|
node.setId(item.getId());
|
|
190
140
|
node.setParentId(item.getParentId());
|
|
191
141
|
node.setName(item.getName());
|
|
192
|
-
node.setWeight(item.getOrderNum());
|
|
193
|
-
// 扩展属性
|
|
142
|
+
node.setWeight(item.getOrderNum());
|
|
194
143
|
node.putExtra("icon", item.getIcon());
|
|
195
|
-
node.putExtra("path", item.getPath());
|
|
196
144
|
});
|
|
197
145
|
|
|
198
146
|
// 指定根节点 ID
|
|
199
|
-
List<Tree<Long>> tree = TreeBuildUtils.build(list, 0L, (node, item) -> {
|
|
200
|
-
// ...
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
// 多根节点树
|
|
204
|
-
List<Tree<Long>> tree = TreeBuildUtils.buildMultiRoot(
|
|
205
|
-
list,
|
|
206
|
-
Item::getId,
|
|
207
|
-
Item::getParentId,
|
|
208
|
-
(node, item) -> {
|
|
209
|
-
node.setId(item.getId());
|
|
210
|
-
node.setParentId(item.getParentId());
|
|
211
|
-
node.setName(item.getName());
|
|
212
|
-
}
|
|
213
|
-
);
|
|
214
|
-
|
|
215
|
-
// 获取叶子节点
|
|
216
|
-
List<Tree<Long>> leaves = TreeBuildUtils.getLeafNodes(tree);
|
|
147
|
+
List<Tree<Long>> tree = TreeBuildUtils.build(list, 0L, (node, item) -> { ... });
|
|
217
148
|
```
|
|
218
149
|
|
|
219
150
|
---
|
|
@@ -225,51 +156,29 @@ import org.dromara.common.core.utils.DateUtils;
|
|
|
225
156
|
import org.dromara.common.core.enums.FormatsType;
|
|
226
157
|
|
|
227
158
|
// 获取当前时间
|
|
228
|
-
|
|
229
|
-
String
|
|
230
|
-
String time = DateUtils.getTime(); // "2026-01-24 15:30:00"
|
|
159
|
+
String date = DateUtils.getDate(); // "2026-01-24"
|
|
160
|
+
String time = DateUtils.getTime(); // "2026-01-24 15:30:00"
|
|
231
161
|
|
|
232
|
-
// 格式化
|
|
233
|
-
DateUtils.
|
|
234
|
-
DateUtils.formatDateTime(date); // "2026-01-24 15:30:00"
|
|
162
|
+
// 格式化 / 解析
|
|
163
|
+
DateUtils.formatDateTime(date);
|
|
235
164
|
DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM, date);
|
|
236
|
-
|
|
237
|
-
// 解析
|
|
238
|
-
Date date = DateUtils.parseDate("2026-01-24");
|
|
239
165
|
Date date = DateUtils.parseDateTime(FormatsType.YYYY_MM_DD_HH_MM_SS, "2026-01-24 15:30:00");
|
|
240
166
|
|
|
241
167
|
// 时间差
|
|
242
168
|
long days = DateUtils.difference(start, end, TimeUnit.DAYS);
|
|
243
169
|
String diff = DateUtils.getDatePoor(endDate, startDate); // "3天 2小时 30分钟"
|
|
244
|
-
String diff = DateUtils.getTimeDifference(endDate, startDate); // 智能省略0值
|
|
245
170
|
|
|
246
171
|
// 日期范围校验
|
|
247
|
-
DateUtils.validateDateRange(startDate, endDate, 30, TimeUnit.DAYS);
|
|
172
|
+
DateUtils.validateDateRange(startDate, endDate, 30, TimeUnit.DAYS);
|
|
248
173
|
|
|
249
174
|
// 友好时间(仿微信)
|
|
250
|
-
DateUtils.formatFriendlyTime(date); // "刚刚" / "5分钟前" / "昨天 14:30"
|
|
251
|
-
|
|
252
|
-
// 时间段
|
|
253
|
-
DateUtils.getTodayHour(date); // "凌晨" / "上午" / "中午" / "下午" / "晚上"
|
|
175
|
+
DateUtils.formatFriendlyTime(date); // "刚刚" / "5分钟前" / "昨天 14:30"
|
|
254
176
|
|
|
255
177
|
// 类型转换
|
|
256
178
|
Date date = DateUtils.toDate(localDateTime);
|
|
257
|
-
Date date = DateUtils.toDate(localDate);
|
|
258
|
-
|
|
259
|
-
// 路径格式
|
|
260
|
-
DateUtils.datePath(); // "2026/01/24"
|
|
261
179
|
```
|
|
262
180
|
|
|
263
|
-
**FormatsType 枚举**:
|
|
264
|
-
|
|
265
|
-
| 枚举值 | 格式 |
|
|
266
|
-
|-------|------|
|
|
267
|
-
| `YYYY_MM_DD` | yyyy-MM-dd |
|
|
268
|
-
| `YYYY_MM_DD_HH_MM_SS` | yyyy-MM-dd HH:mm:ss |
|
|
269
|
-
| `YYYY_MM_DD_HH_MM` | yyyy-MM-dd HH:mm |
|
|
270
|
-
| `YYYYMMDD` | yyyyMMdd |
|
|
271
|
-
| `YYYYMMDDHHMMSS` | yyyyMMddHHmmss |
|
|
272
|
-
| `HH_MM_SS` | HH:mm:ss |
|
|
181
|
+
**FormatsType 枚举**: `YYYY_MM_DD` | `YYYY_MM_DD_HH_MM_SS` | `YYYY_MM_DD_HH_MM` | `YYYYMMDD` | `YYYYMMDDHHMMSS` | `HH_MM_SS`
|
|
273
182
|
|
|
274
183
|
---
|
|
275
184
|
|
|
@@ -280,43 +189,27 @@ import org.dromara.common.core.utils.ValidatorUtils;
|
|
|
280
189
|
import org.dromara.common.core.validate.AddGroup;
|
|
281
190
|
import org.dromara.common.core.validate.EditGroup;
|
|
282
191
|
|
|
283
|
-
//
|
|
192
|
+
// Service 层手动校验
|
|
284
193
|
ValidatorUtils.validate(bo, AddGroup.class);
|
|
285
|
-
ValidatorUtils.validate(bo, EditGroup.class);
|
|
286
194
|
|
|
287
|
-
// Controller
|
|
195
|
+
// Controller 层(推荐)
|
|
288
196
|
@PostMapping
|
|
289
|
-
public R<Void> add(@Validated(AddGroup.class) @RequestBody XxxBo bo) {
|
|
290
|
-
// ...
|
|
291
|
-
}
|
|
197
|
+
public R<Void> add(@Validated(AddGroup.class) @RequestBody XxxBo bo) { }
|
|
292
198
|
|
|
293
199
|
@PutMapping
|
|
294
|
-
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XxxBo bo) {
|
|
295
|
-
// ...
|
|
296
|
-
}
|
|
200
|
+
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XxxBo bo) { }
|
|
297
201
|
```
|
|
298
202
|
|
|
299
203
|
**BO 类校验注解**:
|
|
300
204
|
|
|
301
205
|
```java
|
|
302
206
|
public class XxxBo extends BaseEntity {
|
|
303
|
-
|
|
304
207
|
@NotNull(message = "ID不能为空", groups = { EditGroup.class })
|
|
305
208
|
private Long id;
|
|
306
209
|
|
|
307
210
|
@NotBlank(message = "名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
|
308
211
|
@Size(max = 100, message = "名称长度不能超过100个字符")
|
|
309
212
|
private String name;
|
|
310
|
-
|
|
311
|
-
@Email(message = "邮箱格式不正确")
|
|
312
|
-
private String email;
|
|
313
|
-
|
|
314
|
-
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
|
|
315
|
-
private String phone;
|
|
316
|
-
|
|
317
|
-
@Min(value = 0, message = "数量不能小于0")
|
|
318
|
-
@Max(value = 9999, message = "数量不能大于9999")
|
|
319
|
-
private Integer count;
|
|
320
213
|
}
|
|
321
214
|
```
|
|
322
215
|
|
|
@@ -324,59 +217,35 @@ public class XxxBo extends BaseEntity {
|
|
|
324
217
|
|
|
325
218
|
## 7. Redis 缓存 - RedisUtils
|
|
326
219
|
|
|
220
|
+
> 详细 API 见 `references/redis-utils-api.md`
|
|
221
|
+
|
|
327
222
|
```java
|
|
328
223
|
import org.dromara.common.redis.utils.RedisUtils;
|
|
329
|
-
import java.time.Duration;
|
|
330
224
|
|
|
331
225
|
// 基本操作
|
|
332
|
-
RedisUtils.setCacheObject("key", value);
|
|
333
|
-
RedisUtils.setCacheObject("key", value, Duration.ofMinutes(30));
|
|
226
|
+
RedisUtils.setCacheObject("key", value);
|
|
227
|
+
RedisUtils.setCacheObject("key", value, Duration.ofMinutes(30));
|
|
334
228
|
RedisUtils.getCacheObject("key");
|
|
335
229
|
RedisUtils.deleteObject("key");
|
|
336
230
|
RedisUtils.hasKey("key");
|
|
337
|
-
RedisUtils.expire("key", 3600); // 设置过期时间(秒)
|
|
338
231
|
|
|
339
232
|
// 条件设置
|
|
340
|
-
RedisUtils.setObjectIfAbsent("key", value, Duration.ofMinutes(5));
|
|
341
|
-
RedisUtils.setObjectIfExists("key", value, Duration.ofMinutes(5)); // 存在才设置
|
|
233
|
+
RedisUtils.setObjectIfAbsent("key", value, Duration.ofMinutes(5));
|
|
342
234
|
|
|
343
|
-
// List 操作
|
|
235
|
+
// List / Set / Map 操作
|
|
344
236
|
RedisUtils.setCacheList("listKey", dataList);
|
|
345
|
-
RedisUtils.addCacheList("listKey", item);
|
|
346
|
-
List<T> list = RedisUtils.getCacheList("listKey");
|
|
347
|
-
List<T> range = RedisUtils.getCacheListRange("listKey", 0, 10);
|
|
348
|
-
|
|
349
|
-
// Set 操作
|
|
350
|
-
RedisUtils.setCacheSet("setKey", dataSet);
|
|
351
|
-
RedisUtils.addCacheSet("setKey", item);
|
|
352
|
-
Set<T> set = RedisUtils.getCacheSet("setKey");
|
|
353
|
-
|
|
354
|
-
// Map/Hash 操作
|
|
355
237
|
RedisUtils.setCacheMap("mapKey", dataMap);
|
|
356
238
|
RedisUtils.setCacheMapValue("mapKey", "field", value);
|
|
357
|
-
T value = RedisUtils.getCacheMapValue("mapKey", "field");
|
|
358
|
-
Map<String, T> map = RedisUtils.getCacheMap("mapKey");
|
|
359
|
-
RedisUtils.delCacheMapValue("mapKey", "field");
|
|
360
239
|
|
|
361
240
|
// 原子操作
|
|
362
|
-
RedisUtils.
|
|
363
|
-
long val = RedisUtils.incrAtomicValue("counter"); // +1
|
|
364
|
-
long val = RedisUtils.decrAtomicValue("counter"); // -1
|
|
365
|
-
long val = RedisUtils.getAtomicValue("counter");
|
|
366
|
-
|
|
367
|
-
// 批量操作
|
|
368
|
-
Collection<String> keys = RedisUtils.keys("user:*");
|
|
369
|
-
RedisUtils.deleteKeys("temp:*");
|
|
241
|
+
long val = RedisUtils.incrAtomicValue("counter");
|
|
370
242
|
|
|
371
243
|
// 发布订阅
|
|
372
244
|
RedisUtils.publish("channel", message);
|
|
373
|
-
RedisUtils.subscribe("channel", Message.class, msg -> {
|
|
374
|
-
// 处理消息
|
|
375
|
-
});
|
|
245
|
+
RedisUtils.subscribe("channel", Message.class, msg -> { });
|
|
376
246
|
|
|
377
247
|
// 限流
|
|
378
248
|
long remaining = RedisUtils.rateLimiter("api:user:list", RateType.OVERALL, 100, 60);
|
|
379
|
-
// 每60秒最多100次,返回剩余次数,-1表示被限流
|
|
380
249
|
```
|
|
381
250
|
|
|
382
251
|
---
|
|
@@ -386,23 +255,14 @@ long remaining = RedisUtils.rateLimiter("api:user:list", RateType.OVERALL, 100,
|
|
|
386
255
|
```java
|
|
387
256
|
import org.dromara.common.satoken.utils.LoginHelper;
|
|
388
257
|
|
|
389
|
-
// 获取当前登录用户信息
|
|
390
258
|
Long userId = LoginHelper.getUserId();
|
|
391
259
|
String username = LoginHelper.getUsername();
|
|
392
260
|
Long deptId = LoginHelper.getDeptId();
|
|
393
261
|
String tenantId = LoginHelper.getTenantId();
|
|
394
262
|
LoginUser loginUser = LoginHelper.getLoginUser();
|
|
395
|
-
|
|
396
|
-
// 判断登录状态
|
|
397
263
|
boolean isLogin = LoginHelper.isLogin();
|
|
398
|
-
|
|
399
|
-
// 判断是否超级管理员
|
|
400
264
|
boolean isSuperAdmin = LoginHelper.isSuperAdmin();
|
|
401
|
-
boolean isSuperAdmin = LoginHelper.isSuperAdmin(userId);
|
|
402
|
-
|
|
403
|
-
// 判断是否租户管理员
|
|
404
265
|
boolean isTenantAdmin = LoginHelper.isTenantAdmin();
|
|
405
|
-
boolean isTenantAdmin = LoginHelper.isTenantAdmin(rolePermission);
|
|
406
266
|
```
|
|
407
267
|
|
|
408
268
|
---
|
|
@@ -412,17 +272,9 @@ boolean isTenantAdmin = LoginHelper.isTenantAdmin(rolePermission);
|
|
|
412
272
|
```java
|
|
413
273
|
import org.dromara.common.core.exception.ServiceException;
|
|
414
274
|
|
|
415
|
-
// 抛出业务异常
|
|
416
275
|
throw new ServiceException("用户不存在");
|
|
417
276
|
throw new ServiceException("用户 {} 不存在", userId);
|
|
418
|
-
|
|
419
|
-
// 条件判断
|
|
420
|
-
if (user == null) {
|
|
421
|
-
throw new ServiceException("用户不存在");
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
// 带错误码
|
|
425
|
-
throw new ServiceException("用户不存在", 500);
|
|
277
|
+
throw new ServiceException("用户不存在", 500); // 带错误码
|
|
426
278
|
```
|
|
427
279
|
|
|
428
280
|
---
|
|
@@ -432,7 +284,7 @@ throw new ServiceException("用户不存在", 500);
|
|
|
432
284
|
```java
|
|
433
285
|
import org.dromara.common.excel.utils.ExcelUtil;
|
|
434
286
|
|
|
435
|
-
//
|
|
287
|
+
// 导出
|
|
436
288
|
@PostMapping("/export")
|
|
437
289
|
public void export(XxxBo bo, HttpServletResponse response) {
|
|
438
290
|
List<XxxVo> list = xxxService.queryList(bo);
|
|
@@ -443,7 +295,6 @@ public void export(XxxBo bo, HttpServletResponse response) {
|
|
|
443
295
|
@PostMapping("/import")
|
|
444
296
|
public R<Void> importData(@RequestPart("file") MultipartFile file) throws Exception {
|
|
445
297
|
List<XxxVo> list = ExcelUtil.importExcel(file.getInputStream(), XxxVo.class);
|
|
446
|
-
// 处理导入数据
|
|
447
298
|
return R.ok();
|
|
448
299
|
}
|
|
449
300
|
```
|
|
@@ -452,19 +303,12 @@ public R<Void> importData(@RequestPart("file") MultipartFile file) throws Except
|
|
|
452
303
|
|
|
453
304
|
```java
|
|
454
305
|
public class XxxVo implements Serializable {
|
|
455
|
-
|
|
456
306
|
@ExcelProperty(value = "ID")
|
|
457
307
|
private Long id;
|
|
458
308
|
|
|
459
|
-
@ExcelProperty(value = "名称")
|
|
460
|
-
private String name;
|
|
461
|
-
|
|
462
309
|
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
|
|
463
310
|
@ExcelDictFormat(dictType = "sys_normal_disable")
|
|
464
311
|
private String status;
|
|
465
|
-
|
|
466
|
-
@ExcelProperty(value = "创建时间")
|
|
467
|
-
private Date createTime;
|
|
468
312
|
}
|
|
469
313
|
```
|
|
470
314
|
|
|
@@ -475,92 +319,24 @@ public class XxxVo implements Serializable {
|
|
|
475
319
|
```java
|
|
476
320
|
import org.dromara.common.json.utils.JsonUtils;
|
|
477
321
|
|
|
478
|
-
// 对象转 JSON
|
|
479
322
|
String json = JsonUtils.toJsonString(obj);
|
|
480
|
-
|
|
481
|
-
// JSON 转对象
|
|
482
323
|
User user = JsonUtils.parseObject(json, User.class);
|
|
483
|
-
|
|
484
|
-
// JSON 转 List
|
|
485
324
|
List<User> list = JsonUtils.parseArray(json, User.class);
|
|
486
|
-
|
|
487
|
-
// JSON 转 Map
|
|
488
325
|
Map<String, Object> map = JsonUtils.parseMap(json);
|
|
489
326
|
```
|
|
490
327
|
|
|
491
328
|
---
|
|
492
329
|
|
|
493
|
-
## 12. Hutool 常用工具
|
|
494
|
-
|
|
495
|
-
```java
|
|
496
|
-
import cn.hutool.core.collection.CollUtil;
|
|
497
|
-
import cn.hutool.core.util.ObjectUtil;
|
|
498
|
-
import cn.hutool.core.util.StrUtil;
|
|
499
|
-
import cn.hutool.core.util.IdUtil;
|
|
500
|
-
import cn.hutool.crypto.SecureUtil;
|
|
501
|
-
|
|
502
|
-
// 集合判空
|
|
503
|
-
CollUtil.isEmpty(list);
|
|
504
|
-
CollUtil.isNotEmpty(list);
|
|
505
|
-
CollUtil.newArrayList(1, 2, 3);
|
|
506
|
-
CollUtil.newHashSet("a", "b");
|
|
507
|
-
|
|
508
|
-
// 对象判空
|
|
509
|
-
ObjectUtil.isNull(obj);
|
|
510
|
-
ObjectUtil.isNotNull(obj);
|
|
511
|
-
ObjectUtil.isEmpty(obj); // null / 空字符串 / 空集合
|
|
512
|
-
ObjectUtil.defaultIfNull(obj, defaultValue);
|
|
513
|
-
|
|
514
|
-
// ID 生成
|
|
515
|
-
long snowflakeId = IdUtil.getSnowflakeNextId(); // 雪花ID(推荐)
|
|
516
|
-
String uuid = IdUtil.simpleUUID(); // 无横线 UUID
|
|
517
|
-
String uuid = IdUtil.randomUUID(); // 标准 UUID
|
|
518
|
-
String nanoId = IdUtil.nanoId(); // NanoID
|
|
519
|
-
|
|
520
|
-
// 加密
|
|
521
|
-
String md5 = SecureUtil.md5("password");
|
|
522
|
-
String sha256 = SecureUtil.sha256("password");
|
|
523
|
-
|
|
524
|
-
// Base64
|
|
525
|
-
import cn.hutool.core.codec.Base64;
|
|
526
|
-
String encoded = Base64.encode("data");
|
|
527
|
-
String decoded = Base64.decodeStr(encoded);
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
---
|
|
531
|
-
|
|
532
|
-
## 常用正则表达式
|
|
533
|
-
|
|
534
|
-
```java
|
|
535
|
-
// 手机号
|
|
536
|
-
String phoneReg = "^1[3-9]\\d{9}$";
|
|
537
|
-
|
|
538
|
-
// 邮箱
|
|
539
|
-
String emailReg = "^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$";
|
|
540
|
-
|
|
541
|
-
// 身份证
|
|
542
|
-
String idCardReg = "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$";
|
|
543
|
-
|
|
544
|
-
// URL
|
|
545
|
-
String urlReg = "^https?://.+";
|
|
546
|
-
|
|
547
|
-
// 中文
|
|
548
|
-
String chineseReg = "^[\\u4e00-\\u9fa5]+$";
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
---
|
|
552
|
-
|
|
553
330
|
## 工具类选择速查
|
|
554
331
|
|
|
555
332
|
| 需求 | 推荐工具 | 说明 |
|
|
556
333
|
|------|---------|------|
|
|
557
|
-
| BO
|
|
558
|
-
| 字符串判空 | `StringUtils.isBlank()` |
|
|
334
|
+
| BO/Entity/VO 转换 | `MapstructUtils.convert()` | **必须使用** |
|
|
335
|
+
| 字符串判空 | `StringUtils.isBlank()` | 项目工具类 |
|
|
559
336
|
| 集合判空 | `CollUtil.isEmpty()` | Hutool |
|
|
560
337
|
| 对象判空 | `ObjectUtil.isNull()` | Hutool |
|
|
561
338
|
| 提取集合属性 | `StreamUtils.toList()` | 项目工具类 |
|
|
562
339
|
| 集合转 Map | `StreamUtils.toIdentityMap()` | 项目工具类 |
|
|
563
|
-
| 分组 | `StreamUtils.groupByKey()` | 项目工具类 |
|
|
564
340
|
| 构建树 | `TreeBuildUtils.build()` | 项目工具类 |
|
|
565
341
|
| 日期格式化 | `DateUtils.formatDateTime()` | 项目工具类 |
|
|
566
342
|
| 抛业务异常 | `throw new ServiceException()` | 项目异常类 |
|
|
@@ -568,7 +344,6 @@ String chineseReg = "^[\\u4e00-\\u9fa5]+$";
|
|
|
568
344
|
| Redis 缓存 | `RedisUtils.setCacheObject()` | 项目工具类 |
|
|
569
345
|
| Excel 导出 | `ExcelUtil.exportExcel()` | 项目工具类 |
|
|
570
346
|
| 生成 ID | `IdUtil.getSnowflakeNextId()` | Hutool |
|
|
571
|
-
| MD5/SHA | `SecureUtil.md5()` | Hutool |
|
|
572
347
|
|
|
573
348
|
---
|
|
574
349
|
|
|
@@ -576,18 +351,12 @@ String chineseReg = "^[\\u4e00-\\u9fa5]+$";
|
|
|
576
351
|
|
|
577
352
|
```java
|
|
578
353
|
// ❌ 禁止使用 BeanUtils
|
|
579
|
-
BeanUtils.copyProperties(source, target);
|
|
354
|
+
BeanUtils.copyProperties(source, target);
|
|
580
355
|
|
|
581
356
|
// ❌ 禁止使用 Map 传递业务数据
|
|
582
|
-
public Map<String, Object> getXxx() { ... }
|
|
357
|
+
public Map<String, Object> getXxx() { ... }
|
|
583
358
|
|
|
584
359
|
// ❌ 禁止手写 stream 转换(应使用 StreamUtils)
|
|
585
360
|
list.stream().map(User::getId).collect(Collectors.toList()); // 不推荐
|
|
586
361
|
StreamUtils.toList(list, User::getId); // ✅ 推荐
|
|
587
|
-
|
|
588
|
-
// ❌ 禁止使用完整类型引用
|
|
589
|
-
public org.dromara.common.core.domain.R<XxxVo> getXxx() // 禁止!
|
|
590
|
-
// ✅ 正确:先 import,再使用短类名
|
|
591
|
-
import org.dromara.common.core.domain.R;
|
|
592
|
-
public R<XxxVo> getXxx()
|
|
593
362
|
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# RedisUtils 完整 API
|
|
2
|
+
|
|
3
|
+
```java
|
|
4
|
+
import org.dromara.common.redis.utils.RedisUtils;
|
|
5
|
+
import java.time.Duration;
|
|
6
|
+
|
|
7
|
+
// ========== 基本操作 ==========
|
|
8
|
+
RedisUtils.setCacheObject("key", value); // 永久
|
|
9
|
+
RedisUtils.setCacheObject("key", value, Duration.ofMinutes(30)); // 30分钟过期
|
|
10
|
+
RedisUtils.getCacheObject("key");
|
|
11
|
+
RedisUtils.deleteObject("key");
|
|
12
|
+
RedisUtils.hasKey("key");
|
|
13
|
+
RedisUtils.expire("key", 3600); // 设置过期时间(秒)
|
|
14
|
+
|
|
15
|
+
// ========== 条件设置 ==========
|
|
16
|
+
RedisUtils.setObjectIfAbsent("key", value, Duration.ofMinutes(5)); // 不存在才设置
|
|
17
|
+
RedisUtils.setObjectIfExists("key", value, Duration.ofMinutes(5)); // 存在才设置
|
|
18
|
+
|
|
19
|
+
// ========== List 操作 ==========
|
|
20
|
+
RedisUtils.setCacheList("listKey", dataList);
|
|
21
|
+
RedisUtils.addCacheList("listKey", item);
|
|
22
|
+
List<T> list = RedisUtils.getCacheList("listKey");
|
|
23
|
+
List<T> range = RedisUtils.getCacheListRange("listKey", 0, 10);
|
|
24
|
+
|
|
25
|
+
// ========== Set 操作 ==========
|
|
26
|
+
RedisUtils.setCacheSet("setKey", dataSet);
|
|
27
|
+
RedisUtils.addCacheSet("setKey", item);
|
|
28
|
+
Set<T> set = RedisUtils.getCacheSet("setKey");
|
|
29
|
+
|
|
30
|
+
// ========== Map/Hash 操作 ==========
|
|
31
|
+
RedisUtils.setCacheMap("mapKey", dataMap);
|
|
32
|
+
RedisUtils.setCacheMapValue("mapKey", "field", value);
|
|
33
|
+
T value = RedisUtils.getCacheMapValue("mapKey", "field");
|
|
34
|
+
Map<String, T> map = RedisUtils.getCacheMap("mapKey");
|
|
35
|
+
RedisUtils.delCacheMapValue("mapKey", "field");
|
|
36
|
+
|
|
37
|
+
// ========== 原子操作 ==========
|
|
38
|
+
RedisUtils.setAtomicValue("counter", 0);
|
|
39
|
+
long val = RedisUtils.incrAtomicValue("counter"); // +1
|
|
40
|
+
long val = RedisUtils.decrAtomicValue("counter"); // -1
|
|
41
|
+
long val = RedisUtils.getAtomicValue("counter");
|
|
42
|
+
|
|
43
|
+
// ========== 批量操作 ==========
|
|
44
|
+
Collection<String> keys = RedisUtils.keys("user:*");
|
|
45
|
+
RedisUtils.deleteKeys("temp:*");
|
|
46
|
+
|
|
47
|
+
// ========== 发布订阅 ==========
|
|
48
|
+
RedisUtils.publish("channel", message);
|
|
49
|
+
RedisUtils.subscribe("channel", Message.class, msg -> {
|
|
50
|
+
// 处理消息
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// ========== 限流 ==========
|
|
54
|
+
long remaining = RedisUtils.rateLimiter("api:user:list", RateType.OVERALL, 100, 60);
|
|
55
|
+
// 每60秒最多100次,返回剩余次数,-1表示被限流
|
|
56
|
+
```
|