ai-engineering-init 1.3.4 → 1.4.0

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.
Files changed (226) hide show
  1. package/.claude/hooks/skill-forced-eval.js +2 -0
  2. package/.claude/settings.json +3 -3
  3. package/.claude/skills/add-skill/SKILL.md +79 -32
  4. package/.claude/skills/api-development/SKILL.md +83 -377
  5. package/.claude/skills/architecture-design/SKILL.md +138 -632
  6. package/.claude/skills/backend-annotations/SKILL.md +134 -506
  7. package/.claude/skills/banana-image/SKILL.md +10 -3
  8. package/.claude/skills/brainstorm/SKILL.md +103 -535
  9. package/.claude/skills/bug-detective/SKILL.md +147 -1097
  10. package/.claude/skills/bug-detective/references/error-patterns.md +242 -0
  11. package/.claude/skills/code-patterns/SKILL.md +116 -426
  12. package/.claude/skills/code-patterns/references/leniu-code-patterns.md +87 -0
  13. package/.claude/skills/crud-development/SKILL.md +64 -304
  14. package/.claude/skills/data-permission/SKILL.md +105 -412
  15. package/.claude/skills/data-permission/references/custom-data-scope.md +90 -0
  16. package/.claude/skills/file-oss-management/SKILL.md +106 -714
  17. package/.claude/skills/file-oss-management/references/entities.md +105 -0
  18. package/.claude/skills/file-oss-management/references/service-impl.md +104 -0
  19. package/.claude/skills/leniu-api-development/SKILL.md +142 -626
  20. package/.claude/skills/leniu-api-development/references/real-examples.md +273 -0
  21. package/.claude/skills/leniu-architecture-design/SKILL.md +176 -391
  22. package/.claude/skills/leniu-backend-annotations/SKILL.md +132 -519
  23. package/.claude/skills/leniu-brainstorm/SKILL.md +132 -541
  24. package/.claude/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
  25. package/.claude/skills/leniu-crud-development/SKILL.md +232 -938
  26. package/.claude/skills/leniu-crud-development/references/templates.md +597 -0
  27. package/.claude/skills/leniu-customization-location/SKILL.md +410 -0
  28. package/.claude/skills/leniu-data-permission/SKILL.md +70 -0
  29. package/.claude/skills/leniu-java-entity/SKILL.md +76 -590
  30. package/.claude/skills/leniu-java-entity/references/templates.md +237 -0
  31. package/.claude/skills/leniu-java-export/SKILL.md +94 -379
  32. package/.claude/skills/leniu-java-logging/SKILL.md +106 -709
  33. package/.claude/skills/leniu-java-logging/references/data-mask.md +46 -0
  34. package/.claude/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
  35. package/.claude/skills/leniu-java-mybatis/SKILL.md +73 -446
  36. package/.claude/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
  37. package/.claude/skills/leniu-report-customization/SKILL.md +111 -365
  38. package/.claude/skills/leniu-report-customization/references/table-fields.md +93 -0
  39. package/.claude/skills/leniu-report-standard-customization/SKILL.md +111 -334
  40. package/.claude/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
  41. package/.claude/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
  42. package/.claude/skills/leniu-security-guard/SKILL.md +133 -347
  43. package/.claude/skills/mysql-debug/SKILL.md +364 -0
  44. package/.claude/skills/openspec-apply-change/SKILL.md +10 -1
  45. package/.claude/skills/openspec-archive-change/SKILL.md +9 -1
  46. package/.claude/skills/openspec-bulk-archive-change/SKILL.md +9 -1
  47. package/.claude/skills/openspec-continue-change/SKILL.md +9 -1
  48. package/.claude/skills/openspec-explore/SKILL.md +10 -1
  49. package/.claude/skills/openspec-ff-change/SKILL.md +9 -1
  50. package/.claude/skills/openspec-new-change/SKILL.md +9 -1
  51. package/.claude/skills/openspec-onboard/SKILL.md +15 -130
  52. package/.claude/skills/openspec-sync-specs/SKILL.md +9 -1
  53. package/.claude/skills/openspec-verify-change/SKILL.md +9 -1
  54. package/.claude/skills/performance-doctor/SKILL.md +110 -434
  55. package/.claude/skills/redis-cache/SKILL.md +89 -595
  56. package/.claude/skills/redis-cache/references/listeners.md +23 -0
  57. package/.claude/skills/scheduled-jobs/SKILL.md +88 -407
  58. package/.claude/skills/security-guard/SKILL.md +137 -532
  59. package/.claude/skills/security-guard/references/encrypt-config.md +103 -0
  60. package/.claude/skills/security-guard/references/sensitive-strategies.md +42 -0
  61. package/.claude/skills/sms-mail/SKILL.md +116 -574
  62. package/.claude/skills/sms-mail/references/mail-config.md +88 -0
  63. package/.claude/skills/sms-mail/references/sms-config.md +74 -0
  64. package/.claude/skills/social-login/SKILL.md +112 -514
  65. package/.claude/skills/social-login/references/provider-configs.md +118 -0
  66. package/.claude/skills/tenant-management/SKILL.md +129 -444
  67. package/.claude/skills/tenant-management/references/tenant-scenarios.md +91 -0
  68. package/.claude/skills/test-development/SKILL.md +86 -540
  69. package/.claude/skills/test-development/references/parameterized-examples.md +119 -0
  70. package/.claude/skills/utils-toolkit/SKILL.md +52 -305
  71. package/.claude/skills/utils-toolkit/references/redis-utils-api.md +56 -0
  72. package/.claude/skills/websocket-sse/SKILL.md +105 -550
  73. package/.claude/skills/workflow-engine/SKILL.md +147 -502
  74. package/.codex/skills/add-skill/SKILL.md +79 -32
  75. package/.codex/skills/api-development/SKILL.md +172 -599
  76. package/.codex/skills/architecture-design/SKILL.md +138 -504
  77. package/.codex/skills/backend-annotations/SKILL.md +134 -496
  78. package/.codex/skills/banana-image/SKILL.md +10 -3
  79. package/.codex/skills/brainstorm/SKILL.md +103 -535
  80. package/.codex/skills/bug-detective/SKILL.md +147 -1097
  81. package/.codex/skills/bug-detective/references/error-patterns.md +242 -0
  82. package/.codex/skills/code-patterns/SKILL.md +120 -282
  83. package/.codex/skills/code-patterns/references/leniu-code-patterns.md +87 -0
  84. package/.codex/skills/crud-development/SKILL.md +64 -292
  85. package/.codex/skills/data-permission/SKILL.md +108 -407
  86. package/.codex/skills/data-permission/references/custom-data-scope.md +90 -0
  87. package/.codex/skills/database-ops/SKILL.md +8 -154
  88. package/.codex/skills/error-handler/SKILL.md +10 -0
  89. package/.codex/skills/file-oss-management/SKILL.md +106 -714
  90. package/.codex/skills/file-oss-management/references/entities.md +105 -0
  91. package/.codex/skills/file-oss-management/references/service-impl.md +104 -0
  92. package/.codex/skills/git-workflow/SKILL.md +27 -5
  93. package/.codex/skills/leniu-api-development/SKILL.md +142 -626
  94. package/.codex/skills/leniu-api-development/references/real-examples.md +273 -0
  95. package/.codex/skills/leniu-architecture-design/SKILL.md +176 -391
  96. package/.codex/skills/leniu-backend-annotations/SKILL.md +132 -519
  97. package/.codex/skills/leniu-brainstorm/SKILL.md +132 -541
  98. package/.codex/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
  99. package/.codex/skills/leniu-crud-development/SKILL.md +232 -938
  100. package/.codex/skills/leniu-crud-development/references/templates.md +597 -0
  101. package/.codex/skills/leniu-customization-location/SKILL.md +410 -0
  102. package/.codex/skills/leniu-data-permission/SKILL.md +70 -0
  103. package/.codex/skills/leniu-java-code-style/SKILL.md +510 -0
  104. package/.codex/skills/leniu-java-entity/SKILL.md +76 -590
  105. package/.codex/skills/leniu-java-entity/references/templates.md +237 -0
  106. package/.codex/skills/leniu-java-export/SKILL.md +94 -379
  107. package/.codex/skills/leniu-java-logging/SKILL.md +106 -709
  108. package/.codex/skills/leniu-java-logging/references/data-mask.md +46 -0
  109. package/.codex/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
  110. package/.codex/skills/leniu-java-mybatis/SKILL.md +73 -446
  111. package/.codex/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
  112. package/.codex/skills/leniu-report-customization/SKILL.md +111 -365
  113. package/.codex/skills/leniu-report-customization/references/table-fields.md +93 -0
  114. package/.codex/skills/leniu-report-standard-customization/SKILL.md +111 -334
  115. package/.codex/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
  116. package/.codex/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
  117. package/.codex/skills/leniu-security-guard/SKILL.md +133 -347
  118. package/.codex/skills/mysql-debug/SKILL.md +364 -0
  119. package/.codex/skills/openspec-apply-change/SKILL.md +10 -1
  120. package/.codex/skills/openspec-archive-change/SKILL.md +9 -1
  121. package/.codex/skills/openspec-bulk-archive-change/SKILL.md +9 -1
  122. package/.codex/skills/openspec-continue-change/SKILL.md +9 -1
  123. package/.codex/skills/openspec-explore/SKILL.md +10 -1
  124. package/.codex/skills/openspec-ff-change/SKILL.md +9 -1
  125. package/.codex/skills/openspec-new-change/SKILL.md +9 -1
  126. package/.codex/skills/openspec-onboard/SKILL.md +15 -130
  127. package/.codex/skills/openspec-sync-specs/SKILL.md +9 -1
  128. package/.codex/skills/openspec-verify-change/SKILL.md +9 -1
  129. package/.codex/skills/performance-doctor/SKILL.md +110 -434
  130. package/.codex/skills/project-navigator/SKILL.md +20 -1
  131. package/.codex/skills/redis-cache/SKILL.md +93 -589
  132. package/.codex/skills/redis-cache/references/listeners.md +23 -0
  133. package/.codex/skills/scheduled-jobs/SKILL.md +88 -407
  134. package/.codex/skills/security-guard/SKILL.md +141 -527
  135. package/.codex/skills/security-guard/references/encrypt-config.md +103 -0
  136. package/.codex/skills/security-guard/references/sensitive-strategies.md +42 -0
  137. package/.codex/skills/sms-mail/SKILL.md +116 -574
  138. package/.codex/skills/sms-mail/references/mail-config.md +88 -0
  139. package/.codex/skills/sms-mail/references/sms-config.md +74 -0
  140. package/.codex/skills/social-login/SKILL.md +112 -514
  141. package/.codex/skills/social-login/references/provider-configs.md +118 -0
  142. package/.codex/skills/store-pc/SKILL.md +258 -383
  143. package/.codex/skills/tenant-management/SKILL.md +129 -444
  144. package/.codex/skills/tenant-management/references/tenant-scenarios.md +91 -0
  145. package/.codex/skills/test-development/SKILL.md +86 -540
  146. package/.codex/skills/test-development/references/parameterized-examples.md +119 -0
  147. package/.codex/skills/ui-pc/SKILL.md +350 -387
  148. package/.codex/skills/utils-toolkit/SKILL.md +52 -283
  149. package/.codex/skills/utils-toolkit/references/redis-utils-api.md +56 -0
  150. package/.codex/skills/websocket-sse/SKILL.md +105 -550
  151. package/.codex/skills/workflow-engine/SKILL.md +147 -502
  152. package/.cursor/hooks.json +3 -3
  153. package/.cursor/skills/add-skill/SKILL.md +79 -32
  154. package/.cursor/skills/api-development/SKILL.md +83 -377
  155. package/.cursor/skills/architecture-design/SKILL.md +138 -632
  156. package/.cursor/skills/backend-annotations/SKILL.md +134 -506
  157. package/.cursor/skills/banana-image/SKILL.md +10 -3
  158. package/.cursor/skills/brainstorm/SKILL.md +103 -535
  159. package/.cursor/skills/bug-detective/SKILL.md +147 -1097
  160. package/.cursor/skills/bug-detective/references/error-patterns.md +242 -0
  161. package/.cursor/skills/code-patterns/SKILL.md +116 -426
  162. package/.cursor/skills/code-patterns/references/leniu-code-patterns.md +87 -0
  163. package/.cursor/skills/crud-development/SKILL.md +64 -304
  164. package/.cursor/skills/data-permission/SKILL.md +105 -412
  165. package/.cursor/skills/data-permission/references/custom-data-scope.md +90 -0
  166. package/.cursor/skills/file-oss-management/SKILL.md +106 -714
  167. package/.cursor/skills/file-oss-management/references/entities.md +105 -0
  168. package/.cursor/skills/file-oss-management/references/service-impl.md +104 -0
  169. package/.cursor/skills/git-workflow/SKILL.md +27 -5
  170. package/.cursor/skills/leniu-api-development/SKILL.md +142 -626
  171. package/.cursor/skills/leniu-api-development/references/real-examples.md +273 -0
  172. package/.cursor/skills/leniu-architecture-design/SKILL.md +176 -391
  173. package/.cursor/skills/leniu-backend-annotations/SKILL.md +132 -519
  174. package/.cursor/skills/leniu-brainstorm/SKILL.md +132 -541
  175. package/.cursor/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
  176. package/.cursor/skills/leniu-crud-development/SKILL.md +232 -938
  177. package/.cursor/skills/leniu-crud-development/references/templates.md +597 -0
  178. package/.cursor/skills/leniu-customization-location/SKILL.md +410 -0
  179. package/.cursor/skills/leniu-data-permission/SKILL.md +70 -0
  180. package/.cursor/skills/leniu-java-code-style/SKILL.md +510 -0
  181. package/.cursor/skills/leniu-java-entity/SKILL.md +76 -590
  182. package/.cursor/skills/leniu-java-entity/references/templates.md +237 -0
  183. package/.cursor/skills/leniu-java-export/SKILL.md +94 -379
  184. package/.cursor/skills/leniu-java-logging/SKILL.md +106 -709
  185. package/.cursor/skills/leniu-java-logging/references/data-mask.md +46 -0
  186. package/.cursor/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
  187. package/.cursor/skills/leniu-java-mybatis/SKILL.md +73 -446
  188. package/.cursor/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
  189. package/.cursor/skills/leniu-report-customization/SKILL.md +111 -365
  190. package/.cursor/skills/leniu-report-customization/references/table-fields.md +93 -0
  191. package/.cursor/skills/leniu-report-standard-customization/SKILL.md +111 -334
  192. package/.cursor/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
  193. package/.cursor/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
  194. package/.cursor/skills/leniu-security-guard/SKILL.md +133 -347
  195. package/.cursor/skills/mysql-debug/SKILL.md +364 -0
  196. package/.cursor/skills/openspec-apply-change/SKILL.md +10 -1
  197. package/.cursor/skills/openspec-archive-change/SKILL.md +9 -1
  198. package/.cursor/skills/openspec-bulk-archive-change/SKILL.md +9 -1
  199. package/.cursor/skills/openspec-continue-change/SKILL.md +9 -1
  200. package/.cursor/skills/openspec-explore/SKILL.md +10 -1
  201. package/.cursor/skills/openspec-ff-change/SKILL.md +9 -1
  202. package/.cursor/skills/openspec-new-change/SKILL.md +9 -1
  203. package/.cursor/skills/openspec-onboard/SKILL.md +15 -130
  204. package/.cursor/skills/openspec-sync-specs/SKILL.md +9 -1
  205. package/.cursor/skills/openspec-verify-change/SKILL.md +9 -1
  206. package/.cursor/skills/performance-doctor/SKILL.md +110 -434
  207. package/.cursor/skills/redis-cache/SKILL.md +89 -595
  208. package/.cursor/skills/redis-cache/references/listeners.md +23 -0
  209. package/.cursor/skills/scheduled-jobs/SKILL.md +88 -407
  210. package/.cursor/skills/security-guard/SKILL.md +137 -532
  211. package/.cursor/skills/security-guard/references/encrypt-config.md +103 -0
  212. package/.cursor/skills/security-guard/references/sensitive-strategies.md +42 -0
  213. package/.cursor/skills/sms-mail/SKILL.md +116 -574
  214. package/.cursor/skills/sms-mail/references/mail-config.md +88 -0
  215. package/.cursor/skills/sms-mail/references/sms-config.md +74 -0
  216. package/.cursor/skills/social-login/SKILL.md +112 -514
  217. package/.cursor/skills/social-login/references/provider-configs.md +118 -0
  218. package/.cursor/skills/tenant-management/SKILL.md +129 -444
  219. package/.cursor/skills/tenant-management/references/tenant-scenarios.md +91 -0
  220. package/.cursor/skills/test-development/SKILL.md +86 -540
  221. package/.cursor/skills/test-development/references/parameterized-examples.md +119 -0
  222. package/.cursor/skills/utils-toolkit/SKILL.md +52 -305
  223. package/.cursor/skills/utils-toolkit/references/redis-utils-api.md +56 -0
  224. package/.cursor/skills/websocket-sse/SKILL.md +105 -550
  225. package/.cursor/skills/workflow-engine/SKILL.md +147 -502
  226. package/package.json +1 -1
@@ -17,70 +17,29 @@ description: |
17
17
 
18
18
  > **适用模块**:`ruoyi-common-websocket`、`ruoyi-common-sse`
19
19
 
20
- ## 概述
20
+ ## 方案选型
21
21
 
22
- 本框架提供两种实时通信方案:
22
+ | 方案 | 模块 | 方向 | 场景 |
23
+ |------|------|------|------|
24
+ | **WebSocket** | `ruoyi-common-websocket` | 双向 | 聊天、协作、低延迟交互 |
25
+ | **SSE** | `ruoyi-common-sse` | 服务端→客户端 | 通知推送、状态更新、AI流式响应 |
23
26
 
24
- | 方案 | 模块 | 通信方向 | 适用场景 |
25
- |------|------|---------|---------|
26
- | **WebSocket** | `ruoyi-common-websocket` | 双向通信 | 聊天、协作编辑、游戏 |
27
- | **SSE** | `ruoyi-common-sse` | 服务端→客户端 | 通知推送、状态更新、数据流 |
28
-
29
- **共同特性**:
30
- - ✅ Sa-Token 认证集成
31
- - ✅ Redis 发布订阅(多实例消息同步)
32
- - ✅ 开箱即用,配置启用即可
27
+ **共同特性**:Sa-Token 认证集成、Redis 发布订阅(多实例消息同步)、配置启用即可。
33
28
 
34
29
  ---
35
30
 
36
- ## 技术选型指南
37
-
38
- ### 何时使用 WebSocket
39
-
40
- ```
41
- ✅ 需要双向通信(客户端也要发送消息)
42
- ✅ 即时聊天、协作编辑
43
- ✅ 游戏、实时交互应用
44
- ✅ 需要低延迟的场景
45
- ```
46
-
47
- ### 何时使用 SSE
31
+ ## 一、WebSocket
48
32
 
49
- ```
50
- ✅ 只需服务端向客户端推送
51
- ✅ 系统通知、订单状态变更
52
- ✅ 数据仪表盘实时更新
53
- ✅ AI 流式响应(类似 ChatGPT)
54
- ✅ 需要简单实现、不需要双向通信
55
- ```
56
-
57
- ### 对比表
58
-
59
- | 特性 | WebSocket | SSE |
60
- |------|-----------|-----|
61
- | 通信方向 | 双向 | 单向(服务端→客户端) |
62
- | 协议 | ws:// / wss:// | HTTP |
63
- | 浏览器支持 | 全部现代浏览器 | 全部现代浏览器 |
64
- | 自动重连 | 需自行实现 | 浏览器原生支持 |
65
- | 连接数限制 | 无 | 浏览器限制(6个/域名) |
66
- | 防火墙穿透 | 可能被阻止 | 走 HTTP,穿透性好 |
67
- | 实现复杂度 | 中等 | 简单 |
68
-
69
- ---
70
-
71
- ## 一、WebSocket 开发指南
72
-
73
- ### 1.1 启用配置
33
+ ### 1.1 配置
74
34
 
75
35
  ```yaml
76
- # application.yml
77
36
  websocket:
78
37
  enabled: true
79
- path: /resource/websocket # 连接路径(默认)
80
- allowedOrigins: "*" # 允许跨域(生产环境应限制)
38
+ path: /resource/websocket
39
+ allowedOrigins: "*" # 生产环境应限制
81
40
  ```
82
41
 
83
- ### 1.2 核心工具类:WebSocketUtils
42
+ ### 1.2 WebSocketUtils API
84
43
 
85
44
  **位置**:`org.dromara.common.websocket.utils.WebSocketUtils`
86
45
 
@@ -88,19 +47,17 @@ websocket:
88
47
  import org.dromara.common.websocket.utils.WebSocketUtils;
89
48
  import org.dromara.common.websocket.dto.WebSocketMessageDto;
90
49
 
91
- // ========== 发送消息 ==========
92
-
93
- // 1. 向指定用户发送消息(当前服务实例)
94
- WebSocketUtils.sendMessage(userId, "您有新的订单");
50
+ // 单实例:向指定用户发送
51
+ WebSocketUtils.sendMessage(userId, "消息内容");
95
52
 
96
- // 2. 向指定用户发送消息(支持多实例,通过 Redis 发布订阅)
53
+ // 多实例:通过 Redis Pub/Sub 广播(推荐)
97
54
  WebSocketMessageDto dto = new WebSocketMessageDto();
98
- dto.setSessionKeys(List.of(userId1, userId2)); // 目标用户ID列表
99
- dto.setMessage("订单状态已更新");
55
+ dto.setSessionKeys(List.of(userId1, userId2));
56
+ dto.setMessage("消息内容");
100
57
  WebSocketUtils.publishMessage(dto);
101
58
 
102
- // 3. 向所有在线用户发送消息(群发)
103
- WebSocketUtils.publishAll("系统将于10分钟后维护");
59
+ // 群发所有在线用户
60
+ WebSocketUtils.publishAll("系统广播消息");
104
61
  ```
105
62
 
106
63
  ### 1.3 WebSocketMessageDto
@@ -108,138 +65,46 @@ WebSocketUtils.publishAll("系统将于10分钟后维护");
108
65
  ```java
109
66
  @Data
110
67
  public class WebSocketMessageDto implements Serializable {
111
- /**
112
- * 需要推送到的用户ID列表(为空则群发)
113
- */
114
- private List<Long> sessionKeys;
115
-
116
- /**
117
- * 需要发送的消息内容
118
- */
68
+ private List<Long> sessionKeys; // 目标用户ID(空则群发)
119
69
  private String message;
120
70
  }
121
71
  ```
122
72
 
123
- ### 1.4 会话管理:WebSocketSessionHolder
73
+ ### 1.4 WebSocketSessionHolder(会话管理)
124
74
 
125
75
  **位置**:`org.dromara.common.websocket.holder.WebSocketSessionHolder`
126
76
 
127
77
  ```java
128
- import org.dromara.common.websocket.holder.WebSocketSessionHolder;
129
-
130
- // 检查用户是否在线(当前实例)
131
78
  boolean online = WebSocketSessionHolder.existSession(userId);
132
-
133
- // 获取所有在线用户ID(当前实例)
134
79
  Set<Long> onlineUsers = WebSocketSessionHolder.getSessionsAll();
135
-
136
- // 获取用户的 WebSocket 会话
137
80
  WebSocketSession session = WebSocketSessionHolder.getSessions(userId);
138
81
  ```
139
82
 
140
- ### 1.5 业务集成示例
141
-
142
- #### 示例1:订单状态变更通知
143
-
144
- ```java
145
- @Service
146
- @RequiredArgsConstructor
147
- public class OrderServiceImpl implements IOrderService {
148
-
149
- @Override
150
- @Transactional
151
- public void updateOrderStatus(Long orderId, String status) {
152
- // 1. 更新订单状态
153
- Order order = orderMapper.selectById(orderId);
154
- order.setStatus(status);
155
- orderMapper.updateById(order);
156
-
157
- // 2. 推送消息给用户
158
- WebSocketMessageDto dto = new WebSocketMessageDto();
159
- dto.setSessionKeys(List.of(order.getUserId()));
160
- dto.setMessage(JsonUtils.toJsonString(Map.of(
161
- "type", "ORDER_STATUS",
162
- "orderId", orderId,
163
- "status", status,
164
- "message", "您的订单状态已更新为:" + status
165
- )));
166
- WebSocketUtils.publishMessage(dto);
167
- }
168
- }
169
- ```
170
-
171
- #### 示例2:系统广播通知
172
-
173
- ```java
174
- @Service
175
- public class NoticeServiceImpl implements INoticeService {
176
-
177
- @Override
178
- public void broadcastNotice(String title, String content) {
179
- // 群发给所有在线用户
180
- String message = JsonUtils.toJsonString(Map.of(
181
- "type", "SYSTEM_NOTICE",
182
- "title", title,
183
- "content", content,
184
- "time", DateUtils.getTime()
185
- ));
186
- WebSocketUtils.publishAll(message);
187
- }
188
- }
189
- ```
190
-
191
- ### 1.6 前端连接示例
83
+ ### 1.5 前端连接
192
84
 
193
85
  ```javascript
194
- // 建立 WebSocket 连接
195
- const token = getToken(); // 获取登录 token
196
- const clientId = getClientId(); // 获取客户端ID
197
-
198
- const ws = new WebSocket(`ws://localhost:8080/resource/websocket?clientid=${clientId}&Authorization=${token}`);
199
-
200
- ws.onopen = () => {
201
- console.log('WebSocket 连接成功');
202
- };
203
-
86
+ const ws = new WebSocket(
87
+ `ws://localhost:8080/resource/websocket?clientid=${clientId}&Authorization=${token}`
88
+ );
204
89
  ws.onmessage = (event) => {
205
90
  const data = JSON.parse(event.data);
206
- console.log('收到消息:', data);
207
-
208
- // 根据消息类型处理
209
- switch (data.type) {
210
- case 'ORDER_STATUS':
211
- handleOrderStatus(data);
212
- break;
213
- case 'SYSTEM_NOTICE':
214
- showNotification(data.title, data.content);
215
- break;
216
- }
217
- };
218
-
219
- ws.onclose = () => {
220
- console.log('WebSocket 连接关闭');
221
- // 可实现自动重连
222
- };
223
-
224
- ws.onerror = (error) => {
225
- console.error('WebSocket 错误:', error);
91
+ // 根据 data.type 路由处理
226
92
  };
227
93
  ```
228
94
 
229
95
  ---
230
96
 
231
- ## 二、SSE 开发指南
97
+ ## 二、SSE
232
98
 
233
- ### 2.1 启用配置
99
+ ### 2.1 配置
234
100
 
235
101
  ```yaml
236
- # application.yml
237
102
  sse:
238
103
  enabled: true
239
- path: /resource/sse # 连接路径
104
+ path: /resource/sse
240
105
  ```
241
106
 
242
- ### 2.2 核心工具类:SseMessageUtils
107
+ ### 2.2 SseMessageUtils API
243
108
 
244
109
  **位置**:`org.dromara.common.sse.utils.SseMessageUtils`
245
110
 
@@ -247,27 +112,21 @@ sse:
247
112
  import org.dromara.common.sse.utils.SseMessageUtils;
248
113
  import org.dromara.common.sse.dto.SseMessageDto;
249
114
 
250
- // ========== 发送消息 ==========
115
+ // 单实例:向指定用户 / 所有用户
116
+ SseMessageUtils.sendMessage(userId, "消息");
117
+ SseMessageUtils.sendMessage("广播消息");
251
118
 
252
- // 1. 向指定用户发送消息(当前服务实例)
253
- SseMessageUtils.sendMessage(userId, "您有新的消息");
254
-
255
- // 2. 向当前实例所有用户发送消息
256
- SseMessageUtils.sendMessage("系统通知内容");
257
-
258
- // 3. 向指定用户发送消息(支持多实例,通过 Redis 发布订阅)
119
+ // 多实例:通过 Redis Pub/Sub
259
120
  SseMessageDto dto = new SseMessageDto();
260
- dto.setUserIds(List.of(userId1, userId2)); // 目标用户ID列表
261
- dto.setMessage("您的审批已通过");
121
+ dto.setUserIds(List.of(userId1, userId2));
122
+ dto.setMessage("消息内容");
262
123
  SseMessageUtils.publishMessage(dto);
263
124
 
264
- // 4. 向所有用户发送消息(群发,多实例)
265
- SseMessageUtils.publishAll("系统维护通知");
125
+ // 群发(多实例)
126
+ SseMessageUtils.publishAll("系统通知");
266
127
 
267
- // 5. 检查 SSE 是否启用
268
- if (SseMessageUtils.isEnable()) {
269
- // SSE 已启用
270
- }
128
+ // 检查是否启用
129
+ if (SseMessageUtils.isEnable()) { ... }
271
130
  ```
272
131
 
273
132
  ### 2.3 SseMessageDto
@@ -275,300 +134,62 @@ if (SseMessageUtils.isEnable()) {
275
134
  ```java
276
135
  @Data
277
136
  public class SseMessageDto implements Serializable {
278
- /**
279
- * 需要推送到的用户ID列表(为空则群发)
280
- */
281
- private List<Long> userIds;
282
-
283
- /**
284
- * 需要发送的消息内容
285
- */
137
+ private List<Long> userIds; // 目标用户ID(空则群发)
286
138
  private String message;
287
139
  }
288
140
  ```
289
141
 
290
- ### 2.4 SseEmitterManager 高级用法
291
-
292
- **位置**:`org.dromara.common.sse.core.SseEmitterManager`
293
-
294
- ```java
295
- import org.dromara.common.sse.core.SseEmitterManager;
296
-
297
- @Service
298
- @RequiredArgsConstructor
299
- public class CustomSseService {
300
-
301
- private final SseEmitterManager sseEmitterManager;
302
-
303
- /**
304
- * 建立 SSE 连接(通常由 SseController 处理,业务代码无需调用)
305
- */
306
- public SseEmitter connect(Long userId, String token) {
307
- return sseEmitterManager.connect(userId, token);
308
- }
309
-
310
- /**
311
- * 断开 SSE 连接
312
- */
313
- public void disconnect(Long userId, String token) {
314
- sseEmitterManager.disconnect(userId, token);
315
- }
316
- }
317
- ```
318
-
319
- ### 2.5 业务集成示例
320
-
321
- #### 示例1:审批流程通知
322
-
323
- ```java
324
- @Service
325
- @RequiredArgsConstructor
326
- public class ApprovalServiceImpl implements IApprovalService {
327
-
328
- @Override
329
- @Transactional
330
- public void approve(Long taskId, Boolean approved, String comment) {
331
- // 1. 处理审批逻辑
332
- ApprovalTask task = taskMapper.selectById(taskId);
333
- task.setStatus(approved ? "APPROVED" : "REJECTED");
334
- task.setComment(comment);
335
- taskMapper.updateById(task);
336
-
337
- // 2. 通知申请人
338
- SseMessageDto dto = new SseMessageDto();
339
- dto.setUserIds(List.of(task.getApplicantId()));
340
- dto.setMessage(JsonUtils.toJsonString(Map.of(
341
- "type", "APPROVAL_RESULT",
342
- "taskId", taskId,
343
- "approved", approved,
344
- "comment", comment,
345
- "time", DateUtils.getTime()
346
- )));
347
- SseMessageUtils.publishMessage(dto);
348
- }
349
- }
350
- ```
351
-
352
- #### 示例2:数据变更实时推送
353
-
354
- ```java
355
- @Service
356
- public class DashboardServiceImpl implements IDashboardService {
357
-
358
- /**
359
- * 推送仪表盘数据更新
360
- */
361
- public void pushDashboardUpdate(Long userId, DashboardData data) {
362
- String message = JsonUtils.toJsonString(Map.of(
363
- "type", "DASHBOARD_UPDATE",
364
- "data", data,
365
- "updateTime", DateUtils.getTime()
366
- ));
367
- SseMessageUtils.sendMessage(userId, message);
368
- }
369
-
370
- /**
371
- * 广播给所有管理员
372
- */
373
- public void broadcastToAdmins(List<Long> adminIds, String content) {
374
- SseMessageDto dto = new SseMessageDto();
375
- dto.setUserIds(adminIds);
376
- dto.setMessage(content);
377
- SseMessageUtils.publishMessage(dto);
378
- }
379
- }
380
- ```
381
-
382
- ### 2.6 前端连接示例
142
+ ### 2.4 前端连接
383
143
 
384
144
  ```javascript
385
- // 建立 SSE 连接
386
- const token = getToken();
387
145
  const eventSource = new EventSource(`/resource/sse?Authorization=${token}`);
388
-
389
- eventSource.onopen = () => {
390
- console.log('SSE 连接成功');
391
- };
392
-
393
- // 监听 message 事件
394
146
  eventSource.addEventListener('message', (event) => {
395
147
  const data = JSON.parse(event.data);
396
- console.log('收到消息:', data);
397
-
398
- switch (data.type) {
399
- case 'APPROVAL_RESULT':
400
- showApprovalResult(data);
401
- break;
402
- case 'DASHBOARD_UPDATE':
403
- updateDashboard(data.data);
404
- break;
405
- }
406
148
  });
407
-
408
- eventSource.onerror = (error) => {
409
- console.error('SSE 错误:', error);
410
- // 浏览器会自动尝试重连
411
- };
412
-
413
- // 主动关闭连接
414
- function closeConnection() {
149
+ // 页面关闭时主动关闭
150
+ window.onbeforeunload = () => {
415
151
  eventSource.close();
416
- // 调用后端关闭接口
417
- fetch('/resource/sse/close').then(() => {
418
- console.log('SSE 连接已关闭');
419
- });
420
- }
152
+ navigator.sendBeacon('/resource/sse/close');
153
+ };
421
154
  ```
422
155
 
423
156
  ---
424
157
 
425
- ## 三、多实例部署与消息同步
426
-
427
- ### 3.1 架构原理
428
-
429
- ```
430
- ┌─────────────────────────────────────────────────────────────┐
431
- │ Redis Pub/Sub │
432
- │ │
433
- │ Topic: global:websocket Topic: global:sse │
434
- └─────────────────────────────────────────────────────────────┘
435
- ▲ │ ▲ │
436
- │ ▼ │ ▼
437
- ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐
438
- │ 实例 1 │ │ 实例 2 │ │ 实例 1 │ │ 实例 2 │
439
- │ WS连接 │ │ WS连接 │ │ SSE连接 │ │ SSE连接 │
440
- └─────────┘ └─────────┘ └─────────┘ └─────────┘
441
- │ │ │ │
442
- ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐
443
- │ 用户 A │ │ 用户 B │ │ 用户 C │ │ 用户 D │
444
- └─────────┘ └─────────┘ └─────────┘ └─────────┘
445
- ```
446
-
447
- ### 3.2 消息同步机制
158
+ ## 三、多实例消息同步
448
159
 
449
- **WebSocket 消息发送流程**:
450
- 1. 调用 `WebSocketUtils.publishMessage(dto)`
451
- 2. 先检查目标用户是否在当前实例,在则直接发送
452
- 3. 不在当前实例的用户,通过 Redis 发布到 `global:websocket` 主题
453
- 4. 其他实例的 `WebSocketTopicListener` 接收并转发给本地用户
160
+ 通过 Redis Pub/Sub 实现跨实例消息投递:
454
161
 
455
- **SSE 消息发送流程**:
456
- 1. 调用 `SseMessageUtils.publishMessage(dto)`
457
- 2. 通过 Redis 发布到 `global:sse` 主题
458
- 3. 所有实例的 `SseTopicListener` 接收并检查本地用户
459
- 4. 匹配到的用户通过 `SseEmitter` 推送消息
162
+ | 方案 | Redis Topic | 方法 |
163
+ |------|------------|------|
164
+ | WebSocket | `global:websocket` | `publishMessage()` / `publishAll()` |
165
+ | SSE | `global:sse` | `publishMessage()` / `publishAll()` |
460
166
 
461
- ### 3.3 Redis 主题常量
462
-
463
- ```java
464
- // WebSocket 主题
465
- public static final String WEB_SOCKET_TOPIC = "global:websocket";
466
-
467
- // SSE 主题
468
- private final static String SSE_TOPIC = "global:sse";
469
- ```
167
+ **流程**:调用 publish 方法 -> 发布到 Redis Topic -> 所有实例的 Listener 接收 -> 匹配本地用户并投递。
470
168
 
471
169
  ---
472
170
 
473
- ## 四、常见场景实战
474
-
475
- ### 4.1 场景:系统通知推送
171
+ ## 四、业务集成示例
476
172
 
477
173
  ```java
478
174
  @Service
479
175
  @RequiredArgsConstructor
480
- public class SystemNoticeService {
176
+ public class OrderNotifyService {
481
177
 
482
- /**
483
- * 发送系统通知(SSE 方式)
484
- */
485
- public void sendNotice(Long userId, String title, String content) {
178
+ public void notifyOrderStatusChange(Order order) {
486
179
  String message = JsonUtils.toJsonString(Map.of(
487
- "type", "SYSTEM_NOTICE",
488
- "title", title,
489
- "content", content,
490
- "time", DateUtils.getTime()
180
+ "type", "ORDER_STATUS_CHANGE",
181
+ "orderId", order.getId(),
182
+ "status", order.getStatus(),
183
+ "updateTime", DateUtils.getTime()
491
184
  ));
492
185
 
493
- SseMessageDto dto = new SseMessageDto();
494
- dto.setUserIds(List.of(userId));
495
- dto.setMessage(message);
496
- SseMessageUtils.publishMessage(dto);
497
- }
498
-
499
- /**
500
- * 广播系统公告
501
- */
502
- public void broadcastAnnouncement(String title, String content) {
503
- String message = JsonUtils.toJsonString(Map.of(
504
- "type", "ANNOUNCEMENT",
505
- "title", title,
506
- "content", content,
507
- "time", DateUtils.getTime()
508
- ));
509
- SseMessageUtils.publishAll(message);
510
- }
511
- }
512
- ```
513
-
514
- ### 4.2 场景:在线用户统计
515
-
516
- ```java
517
- @Service
518
- public class OnlineUserService {
519
-
520
- /**
521
- * 获取当前实例在线用户数(WebSocket)
522
- */
523
- public int getOnlineCount() {
524
- return WebSocketSessionHolder.getSessionsAll().size();
525
- }
526
-
527
- /**
528
- * 检查用户是否在线(当前实例)
529
- */
530
- public boolean isOnline(Long userId) {
531
- return WebSocketSessionHolder.existSession(userId);
532
- }
533
-
534
- /**
535
- * 获取在线用户列表(当前实例)
536
- */
537
- public Set<Long> getOnlineUsers() {
538
- return WebSocketSessionHolder.getSessionsAll();
539
- }
540
- }
541
- ```
542
-
543
- ### 4.3 场景:订单状态实时更新
544
-
545
- ```java
546
- @Service
547
- @RequiredArgsConstructor
548
- public class OrderNotifyService {
549
-
550
- /**
551
- * 订单状态变更通知
552
- */
553
- public void notifyOrderStatusChange(Order order) {
554
- // 1. 构建消息
555
- Map<String, Object> data = new HashMap<>();
556
- data.put("type", "ORDER_STATUS_CHANGE");
557
- data.put("orderId", order.getId());
558
- data.put("orderNo", order.getOrderNo());
559
- data.put("oldStatus", order.getOldStatus());
560
- data.put("newStatus", order.getStatus());
561
- data.put("updateTime", DateUtils.getTime());
562
-
563
- String message = JsonUtils.toJsonString(data);
564
-
565
- // 2. 通知买家(SSE)
186
+ // SSE 通知买家
566
187
  SseMessageDto buyerDto = new SseMessageDto();
567
188
  buyerDto.setUserIds(List.of(order.getBuyerId()));
568
189
  buyerDto.setMessage(message);
569
190
  SseMessageUtils.publishMessage(buyerDto);
570
191
 
571
- // 3. 通知卖家(WebSocket,如果需要双向通信)
192
+ // WebSocket 通知卖家(需要双向通信时)
572
193
  WebSocketMessageDto sellerDto = new WebSocketMessageDto();
573
194
  sellerDto.setSessionKeys(List.of(order.getSellerId()));
574
195
  sellerDto.setMessage(message);
@@ -579,138 +200,72 @@ public class OrderNotifyService {
579
200
 
580
201
  ---
581
202
 
582
- ## 五、常见错误与最佳实践
583
-
584
- ### ❌ 错误1:未启用模块就使用
203
+ ## 五、常见错误
585
204
 
586
205
  ```java
587
- // ❌ 错误:未配置 websocket.enabled=true
588
- WebSocketUtils.sendMessage(userId, "消息"); // 用户收不到
589
- ```
590
-
591
- ```yaml
592
- # ✅ 正确:先启用
593
- websocket:
594
- enabled: true
595
- ```
206
+ // ❌ 多实例环境使用 sendMessage(只能发给当前实例用户)
207
+ WebSocketUtils.sendMessage(userId, "消息");
596
208
 
597
- ### 错误2:混淆单实例和多实例方法
598
-
599
- ```java
600
- // ❌ 错误:使用 sendMessage 在多实例环境
601
- WebSocketUtils.sendMessage(userId, "消息"); // 只能发给当前实例的用户
602
-
603
- // ✅ 正确:使用 publishMessage 支持多实例
209
+ // 使用 publishMessage 支持多实例
604
210
  WebSocketMessageDto dto = new WebSocketMessageDto();
605
211
  dto.setSessionKeys(List.of(userId));
606
212
  dto.setMessage("消息");
607
- WebSocketUtils.publishMessage(dto); // 通过 Redis 广播到所有实例
608
- ```
609
-
610
- ### ❌ 错误3:SSE 连接未关闭导致资源泄漏
611
-
612
- ```javascript
613
- // ❌ 错误:页面关闭时未主动关闭 SSE
614
- window.onbeforeunload = () => {
615
- // 没有关闭 eventSource
616
- };
213
+ WebSocketUtils.publishMessage(dto);
617
214
 
618
- // 正确:主动关闭连接
619
- window.onbeforeunload = () => {
620
- eventSource.close();
621
- navigator.sendBeacon('/resource/sse/close'); // 使用 sendBeacon 确保请求发出
622
- };
623
- ```
215
+ // 循环逐个发送
216
+ for (Long uid : userIds) {
217
+ dto.setSessionKeys(List.of(uid));
218
+ WebSocketUtils.publishMessage(dto);
219
+ }
624
220
 
625
- ### 错误4:消息格式不统一
221
+ // 批量发送
222
+ dto.setSessionKeys(userIds);
223
+ WebSocketUtils.publishMessage(dto);
626
224
 
627
- ```java
628
- // ❌ 错误:直接发送字符串,前端难以解析
225
+ // ❌ 发送纯字符串(前端难解析)
629
226
  WebSocketUtils.publishAll("订单已更新");
630
227
 
631
- // ✅ 正确:使用 JSON 格式,包含类型字段
632
- String message = JsonUtils.toJsonString(Map.of(
633
- "type", "ORDER_UPDATE", // 消息类型,便于前端路由处理
634
- "data", orderData,
635
- "time", DateUtils.getTime()
636
- ));
637
- WebSocketUtils.publishAll(message);
228
+ // ✅ JSON 格式 + type 字段
229
+ WebSocketUtils.publishAll(JsonUtils.toJsonString(Map.of(
230
+ "type", "ORDER_UPDATE", "data", orderData
231
+ )));
638
232
  ```
639
233
 
640
- ### ❌ 错误5:在循环中逐个发送消息
641
-
642
- ```java
643
- // ❌ 错误:效率低
644
- for (Long userId : userIds) {
645
- WebSocketMessageDto dto = new WebSocketMessageDto();
646
- dto.setSessionKeys(List.of(userId));
647
- dto.setMessage(message);
648
- WebSocketUtils.publishMessage(dto); // 每次都发布到 Redis
649
- }
650
-
651
- // ✅ 正确:批量发送
652
- WebSocketMessageDto dto = new WebSocketMessageDto();
653
- dto.setSessionKeys(userIds); // 一次性设置所有目标用户
654
- dto.setMessage(message);
655
- WebSocketUtils.publishMessage(dto); // 只发布一次
656
- ```
657
-
658
- ---
659
-
660
- ## 六、API 速查表
661
-
662
- ### WebSocket API
663
-
664
- | 方法 | 说明 | 适用场景 |
665
- |------|------|---------|
666
- | `WebSocketUtils.sendMessage(userId, message)` | 发送给指定用户(当前实例) | 单实例部署 |
667
- | `WebSocketUtils.publishMessage(dto)` | 发送给指定用户(多实例) | 多实例部署 |
668
- | `WebSocketUtils.publishAll(message)` | 群发所有用户 | 系统广播 |
669
- | `WebSocketSessionHolder.existSession(userId)` | 检查用户是否在线 | 在线状态 |
670
- | `WebSocketSessionHolder.getSessionsAll()` | 获取所有在线用户 | 统计 |
671
-
672
- ### SSE API
673
-
674
- | 方法 | 说明 | 适用场景 |
675
- |------|------|---------|
676
- | `SseMessageUtils.sendMessage(userId, message)` | 发送给指定用户(当前实例) | 单实例部署 |
677
- | `SseMessageUtils.sendMessage(message)` | 发送给所有用户(当前实例) | 单实例广播 |
678
- | `SseMessageUtils.publishMessage(dto)` | 发送给指定用户(多实例) | 多实例部署 |
679
- | `SseMessageUtils.publishAll(message)` | 群发所有用户(多实例) | 系统广播 |
680
- | `SseMessageUtils.isEnable()` | 检查 SSE 是否启用 | 条件判断 |
681
-
682
234
  ---
683
235
 
684
- ## 七、配置参考
236
+ ## 六、API 速查
685
237
 
686
- ### WebSocket 完整配置
238
+ ### WebSocket
687
239
 
688
- ```yaml
689
- websocket:
690
- enabled: true # 是否启用(必填)
691
- path: /resource/websocket # 连接路径(默认 /resource/websocket)
692
- allowedOrigins: "*" # 允许跨域来源(生产环境应限制)
693
- ```
240
+ | 方法 | 说明 |
241
+ |------|------|
242
+ | `WebSocketUtils.sendMessage(userId, msg)` | 发给指定用户(当前实例) |
243
+ | `WebSocketUtils.publishMessage(dto)` | 发给指定用户(多实例) |
244
+ | `WebSocketUtils.publishAll(msg)` | 群发(多实例) |
245
+ | `WebSocketSessionHolder.existSession(userId)` | 检查在线 |
246
+ | `WebSocketSessionHolder.getSessionsAll()` | 所有在线用户 |
694
247
 
695
- ### SSE 完整配置
248
+ ### SSE
696
249
 
697
- ```yaml
698
- sse:
699
- enabled: true # 是否启用(必填)
700
- path: /resource/sse # 连接路径(必填)
701
- ```
250
+ | 方法 | 说明 |
251
+ |------|------|
252
+ | `SseMessageUtils.sendMessage(userId, msg)` | 发给指定用户(当前实例) |
253
+ | `SseMessageUtils.sendMessage(msg)` | 发给所有用户(当前实例) |
254
+ | `SseMessageUtils.publishMessage(dto)` | 发给指定用户(多实例) |
255
+ | `SseMessageUtils.publishAll(msg)` | 群发(多实例) |
256
+ | `SseMessageUtils.isEnable()` | 检查是否启用 |
702
257
 
703
258
  ---
704
259
 
705
- ## 八、参考代码位置
260
+ ## 七、参考代码位置
706
261
 
707
262
  | 类型 | 位置 |
708
263
  |------|------|
709
- | WebSocket 工具类 | `ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java` |
710
- | WebSocket 会话管理 | `ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java` |
711
- | WebSocket 消息DTO | `ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/dto/WebSocketMessageDto.java` |
712
- | WebSocket 配置 | `ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/config/WebSocketConfig.java` |
713
- | SSE 工具类 | `ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java` |
714
- | SSE 连接管理 | `ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java` |
715
- | SSE 控制器 | `ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/controller/SseController.java` |
716
- | SSE 消息DTO | `ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/dto/SseMessageDto.java` |
264
+ | WebSocket 工具类 | `ruoyi-common/ruoyi-common-websocket/.../utils/WebSocketUtils.java` |
265
+ | WebSocket 会话管理 | `ruoyi-common/ruoyi-common-websocket/.../holder/WebSocketSessionHolder.java` |
266
+ | WebSocket 消息DTO | `ruoyi-common/ruoyi-common-websocket/.../dto/WebSocketMessageDto.java` |
267
+ | WebSocket 配置 | `ruoyi-common/ruoyi-common-websocket/.../config/WebSocketConfig.java` |
268
+ | SSE 工具类 | `ruoyi-common/ruoyi-common-sse/.../utils/SseMessageUtils.java` |
269
+ | SSE 连接管理 | `ruoyi-common/ruoyi-common-sse/.../core/SseEmitterManager.java` |
270
+ | SSE 控制器 | `ruoyi-common/ruoyi-common-sse/.../controller/SseController.java` |
271
+ | SSE 消息DTO | `ruoyi-common/ruoyi-common-sse/.../dto/SseMessageDto.java` |