ai-engineering-init 1.1.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 (313) hide show
  1. package/.claude/agents/code-reviewer.md +139 -0
  2. package/.claude/agents/project-manager.md +159 -0
  3. package/.claude/audio/completed.wav +0 -0
  4. package/.claude/commands/add-todo.md +255 -0
  5. package/.claude/commands/check.md +210 -0
  6. package/.claude/commands/crud.md +454 -0
  7. package/.claude/commands/dev.md +503 -0
  8. package/.claude/commands/init-docs.md +681 -0
  9. package/.claude/commands/next.md +251 -0
  10. package/.claude/commands/progress.md +242 -0
  11. package/.claude/commands/start.md +199 -0
  12. package/.claude/commands/sync.md +307 -0
  13. package/.claude/commands/update-status.md +428 -0
  14. package/.claude/docs/Mixin/344/275/277/347/224/250/346/214/207/345/215/227.md +299 -0
  15. package/.claude/docs/README.md +167 -0
  16. package/.claude/docs//345/211/215/347/253/257/345/274/200/345/217/221/346/214/207/345/215/227.md +599 -0
  17. package/.claude/docs//345/220/216/347/253/257/345/274/200/345/217/221/346/214/207/345/215/227.md +726 -0
  18. package/.claude/docs//345/267/245/344/275/234/346/265/201/345/274/200/345/217/221/346/214/207/345/215/227.md +714 -0
  19. package/.claude/docs//345/267/245/345/205/267/347/261/273/344/275/277/347/224/250/346/214/207/345/215/227.md +463 -0
  20. package/.claude/docs//346/225/260/346/215/256/345/272/223/350/256/276/350/256/241/350/247/204/350/214/203.md +390 -0
  21. package/.claude/docs//346/226/260/345/212/237/350/203/275/345/274/200/345/217/221/346/265/201/347/250/213/350/247/204/350/214/203.md +688 -0
  22. package/.claude/docs//346/226/260/351/241/271/347/233/256/345/274/200/345/217/221/346/265/201/347/250/213.md +365 -0
  23. package/.claude/docs//346/241/206/346/236/266/350/257/264/346/230/216.md +393 -0
  24. package/.claude/docs//350/267/257/347/224/261/351/205/215/347/275/256/346/214/207/345/215/227.md +246 -0
  25. package/.claude/framework-config.json +73 -0
  26. package/.claude/hooks/pre-tool-use.js +117 -0
  27. package/.claude/hooks/skill-forced-eval.js +167 -0
  28. package/.claude/hooks/stop.js +58 -0
  29. package/.claude/settings.json +41 -0
  30. package/.claude/skills/add-skill/SKILL.md +352 -0
  31. package/.claude/skills/api-development/SKILL.md +560 -0
  32. package/.claude/skills/architecture-design/SKILL.md +756 -0
  33. package/.claude/skills/backend-annotations/SKILL.md +674 -0
  34. package/.claude/skills/banana-image/CHANGELOG.md +37 -0
  35. package/.claude/skills/banana-image/README.md +146 -0
  36. package/.claude/skills/banana-image/SKILL.md +164 -0
  37. package/.claude/skills/banana-image/assets/logo.png +0 -0
  38. package/.claude/skills/banana-image/references/advanced-usage.md +189 -0
  39. package/.claude/skills/banana-image/scripts/apply_template.py +125 -0
  40. package/.claude/skills/banana-image/scripts/banana_image_exec.ts +412 -0
  41. package/.claude/skills/banana-image/scripts/batch_prep.py +82 -0
  42. package/.claude/skills/banana-image/scripts/package-lock.json +1437 -0
  43. package/.claude/skills/banana-image/scripts/package.json +18 -0
  44. package/.claude/skills/banana-image/scripts/requirements.txt +10 -0
  45. package/.claude/skills/banana-image/templates/poster.json +22 -0
  46. package/.claude/skills/banana-image/templates/product.json +17 -0
  47. package/.claude/skills/banana-image/templates/social.json +22 -0
  48. package/.claude/skills/banana-image/templates/thumbnail.json +17 -0
  49. package/.claude/skills/brainstorm/SKILL.md +648 -0
  50. package/.claude/skills/bug-detective/SKILL.md +1206 -0
  51. package/.claude/skills/code-patterns/SKILL.md +590 -0
  52. package/.claude/skills/collaborating-with-codex/SKILL.md +174 -0
  53. package/.claude/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
  54. package/.claude/skills/collaborating-with-gemini/SKILL.md +194 -0
  55. package/.claude/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
  56. package/.claude/skills/crud-development/SKILL.md +649 -0
  57. package/.claude/skills/data-permission/SKILL.md +599 -0
  58. package/.claude/skills/database-ops/SKILL.md +407 -0
  59. package/.claude/skills/error-handler/SKILL.md +371 -0
  60. package/.claude/skills/file-oss-management/SKILL.md +863 -0
  61. package/.claude/skills/git-workflow/SKILL.md +375 -0
  62. package/.claude/skills/json-serialization/SKILL.md +357 -0
  63. package/.claude/skills/leniu-api-development/SKILL.md +803 -0
  64. package/.claude/skills/leniu-architecture-design/SKILL.md +598 -0
  65. package/.claude/skills/leniu-backend-annotations/SKILL.md +664 -0
  66. package/.claude/skills/leniu-code-patterns/SKILL.md +365 -0
  67. package/.claude/skills/leniu-crud-development/SKILL.md +1110 -0
  68. package/.claude/skills/leniu-data-permission/SKILL.md +256 -0
  69. package/.claude/skills/leniu-database-ops/SKILL.md +426 -0
  70. package/.claude/skills/leniu-error-handler/SKILL.md +462 -0
  71. package/.claude/skills/leniu-java-amount-handling/SKILL.md +461 -0
  72. package/.claude/skills/leniu-java-code-style/SKILL.md +510 -0
  73. package/.claude/skills/leniu-java-concurrent/SKILL.md +400 -0
  74. package/.claude/skills/leniu-java-entity/SKILL.md +751 -0
  75. package/.claude/skills/leniu-java-export/SKILL.md +560 -0
  76. package/.claude/skills/leniu-java-logging/SKILL.md +832 -0
  77. package/.claude/skills/leniu-java-mq/SKILL.md +338 -0
  78. package/.claude/skills/leniu-java-mybatis/SKILL.md +640 -0
  79. package/.claude/skills/leniu-java-report-query-param/SKILL.md +291 -0
  80. package/.claude/skills/leniu-java-task/SKILL.md +367 -0
  81. package/.claude/skills/leniu-java-total-line/SKILL.md +195 -0
  82. package/.claude/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
  83. package/.claude/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
  84. package/.claude/skills/leniu-mealtime/SKILL.md +215 -0
  85. package/.claude/skills/leniu-redis-cache/SKILL.md +316 -0
  86. package/.claude/skills/leniu-security-guard/SKILL.md +520 -0
  87. package/.claude/skills/leniu-utils-toolkit/SKILL.md +380 -0
  88. package/.claude/skills/openspec-apply-change/SKILL.md +156 -0
  89. package/.claude/skills/openspec-archive-change/SKILL.md +114 -0
  90. package/.claude/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  91. package/.claude/skills/openspec-continue-change/SKILL.md +118 -0
  92. package/.claude/skills/openspec-explore/SKILL.md +290 -0
  93. package/.claude/skills/openspec-ff-change/SKILL.md +101 -0
  94. package/.claude/skills/openspec-new-change/SKILL.md +74 -0
  95. package/.claude/skills/openspec-onboard/SKILL.md +529 -0
  96. package/.claude/skills/openspec-sync-specs/SKILL.md +138 -0
  97. package/.claude/skills/openspec-verify-change/SKILL.md +168 -0
  98. package/.claude/skills/performance-doctor/SKILL.md +627 -0
  99. package/.claude/skills/project-navigator/SKILL.md +305 -0
  100. package/.claude/skills/redis-cache/SKILL.md +839 -0
  101. package/.claude/skills/scheduled-jobs/SKILL.md +633 -0
  102. package/.claude/skills/security-guard/SKILL.md +748 -0
  103. package/.claude/skills/sms-mail/SKILL.md +766 -0
  104. package/.claude/skills/social-login/SKILL.md +668 -0
  105. package/.claude/skills/store-pc/SKILL.md +366 -0
  106. package/.claude/skills/task-tracker/SKILL.md +307 -0
  107. package/.claude/skills/tech-decision/SKILL.md +393 -0
  108. package/.claude/skills/tenant-management/SKILL.md +603 -0
  109. package/.claude/skills/test-development/SKILL.md +755 -0
  110. package/.claude/skills/ui-pc/SKILL.md +438 -0
  111. package/.claude/skills/utils-toolkit/SKILL.md +615 -0
  112. package/.claude/skills/websocket-sse/SKILL.md +716 -0
  113. package/.claude/skills/workflow-engine/SKILL.md +676 -0
  114. package/.claude/templates//345/276/205/345/212/236/346/270/205/345/215/225/346/250/241/346/235/277.md +56 -0
  115. package/.claude/templates//351/234/200/346/261/202/346/226/207/346/241/243/346/250/241/346/235/277.md +85 -0
  116. package/.claude/templates//351/241/271/347/233/256/347/212/266/346/200/201/346/250/241/346/235/277.md +43 -0
  117. package/.codex/skills/add-skill/SKILL.md +352 -0
  118. package/.codex/skills/add-todo/SKILL.md +269 -0
  119. package/.codex/skills/api-development/SKILL.md +693 -0
  120. package/.codex/skills/architecture-design/SKILL.md +628 -0
  121. package/.codex/skills/backend-annotations/SKILL.md +664 -0
  122. package/.codex/skills/banana-image/CHANGELOG.md +37 -0
  123. package/.codex/skills/banana-image/README.md +146 -0
  124. package/.codex/skills/banana-image/SKILL.md +164 -0
  125. package/.codex/skills/banana-image/assets/logo.png +0 -0
  126. package/.codex/skills/banana-image/references/advanced-usage.md +189 -0
  127. package/.codex/skills/banana-image/scripts/apply_template.py +125 -0
  128. package/.codex/skills/banana-image/scripts/banana_image_exec.ts +412 -0
  129. package/.codex/skills/banana-image/scripts/batch_prep.py +82 -0
  130. package/.codex/skills/banana-image/scripts/package-lock.json +1437 -0
  131. package/.codex/skills/banana-image/scripts/package.json +18 -0
  132. package/.codex/skills/banana-image/scripts/requirements.txt +10 -0
  133. package/.codex/skills/banana-image/templates/poster.json +22 -0
  134. package/.codex/skills/banana-image/templates/product.json +17 -0
  135. package/.codex/skills/banana-image/templates/social.json +22 -0
  136. package/.codex/skills/banana-image/templates/thumbnail.json +17 -0
  137. package/.codex/skills/brainstorm/SKILL.md +648 -0
  138. package/.codex/skills/bug-detective/SKILL.md +1206 -0
  139. package/.codex/skills/check/SKILL.md +367 -0
  140. package/.codex/skills/code-patterns/SKILL.md +442 -0
  141. package/.codex/skills/collaborating-with-codex/SKILL.md +174 -0
  142. package/.codex/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
  143. package/.codex/skills/collaborating-with-gemini/SKILL.md +194 -0
  144. package/.codex/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
  145. package/.codex/skills/crud/SKILL.md +265 -0
  146. package/.codex/skills/crud-development/SKILL.md +637 -0
  147. package/.codex/skills/data-permission/SKILL.md +591 -0
  148. package/.codex/skills/database-ops/SKILL.md +553 -0
  149. package/.codex/skills/dev/SKILL.md +187 -0
  150. package/.codex/skills/error-handler/SKILL.md +361 -0
  151. package/.codex/skills/file-oss-management/SKILL.md +863 -0
  152. package/.codex/skills/git-workflow/SKILL.md +375 -0
  153. package/.codex/skills/init-docs/SKILL.md +194 -0
  154. package/.codex/skills/json-serialization/SKILL.md +357 -0
  155. package/.codex/skills/leniu-api-development/SKILL.md +803 -0
  156. package/.codex/skills/leniu-architecture-design/SKILL.md +594 -0
  157. package/.codex/skills/leniu-backend-annotations/SKILL.md +662 -0
  158. package/.codex/skills/leniu-code-patterns/SKILL.md +365 -0
  159. package/.codex/skills/leniu-crud-development/SKILL.md +1110 -0
  160. package/.codex/skills/leniu-data-permission/SKILL.md +256 -0
  161. package/.codex/skills/leniu-database-ops/SKILL.md +426 -0
  162. package/.codex/skills/leniu-error-handler/SKILL.md +462 -0
  163. package/.codex/skills/leniu-java-amount-handling/SKILL.md +461 -0
  164. package/.codex/skills/leniu-java-code-style/SKILL.md +510 -0
  165. package/.codex/skills/leniu-java-concurrent/SKILL.md +400 -0
  166. package/.codex/skills/leniu-java-entity/SKILL.md +751 -0
  167. package/.codex/skills/leniu-java-export/SKILL.md +560 -0
  168. package/.codex/skills/leniu-java-logging/SKILL.md +832 -0
  169. package/.codex/skills/leniu-java-mq/SKILL.md +338 -0
  170. package/.codex/skills/leniu-java-mybatis/SKILL.md +640 -0
  171. package/.codex/skills/leniu-java-report-query-param/SKILL.md +291 -0
  172. package/.codex/skills/leniu-java-task/SKILL.md +367 -0
  173. package/.codex/skills/leniu-java-total-line/SKILL.md +195 -0
  174. package/.codex/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
  175. package/.codex/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
  176. package/.codex/skills/leniu-mealtime/SKILL.md +215 -0
  177. package/.codex/skills/leniu-redis-cache/SKILL.md +316 -0
  178. package/.codex/skills/leniu-security-guard/SKILL.md +520 -0
  179. package/.codex/skills/leniu-utils-toolkit/SKILL.md +378 -0
  180. package/.codex/skills/next/SKILL.md +137 -0
  181. package/.codex/skills/openspec-apply-change/SKILL.md +156 -0
  182. package/.codex/skills/openspec-archive-change/SKILL.md +114 -0
  183. package/.codex/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  184. package/.codex/skills/openspec-continue-change/SKILL.md +118 -0
  185. package/.codex/skills/openspec-explore/SKILL.md +290 -0
  186. package/.codex/skills/openspec-ff-change/SKILL.md +101 -0
  187. package/.codex/skills/openspec-new-change/SKILL.md +74 -0
  188. package/.codex/skills/openspec-onboard/SKILL.md +529 -0
  189. package/.codex/skills/openspec-sync-specs/SKILL.md +138 -0
  190. package/.codex/skills/openspec-verify-change/SKILL.md +168 -0
  191. package/.codex/skills/performance-doctor/SKILL.md +627 -0
  192. package/.codex/skills/progress/SKILL.md +193 -0
  193. package/.codex/skills/project-navigator/SKILL.md +286 -0
  194. package/.codex/skills/redis-cache/SKILL.md +829 -0
  195. package/.codex/skills/scheduled-jobs/SKILL.md +633 -0
  196. package/.codex/skills/security-guard/SKILL.md +739 -0
  197. package/.codex/skills/sms-mail/SKILL.md +766 -0
  198. package/.codex/skills/social-login/SKILL.md +668 -0
  199. package/.codex/skills/start/SKILL.md +154 -0
  200. package/.codex/skills/store-pc/SKILL.md +491 -0
  201. package/.codex/skills/sync/SKILL.md +149 -0
  202. package/.codex/skills/task-tracker/SKILL.md +307 -0
  203. package/.codex/skills/tech-decision/SKILL.md +393 -0
  204. package/.codex/skills/tenant-management/SKILL.md +603 -0
  205. package/.codex/skills/test-development/SKILL.md +755 -0
  206. package/.codex/skills/ui-pc/SKILL.md +475 -0
  207. package/.codex/skills/update-status/SKILL.md +159 -0
  208. package/.codex/skills/utils-toolkit/SKILL.md +593 -0
  209. package/.codex/skills/websocket-sse/SKILL.md +716 -0
  210. package/.codex/skills/workflow-engine/SKILL.md +676 -0
  211. package/.cursor/agents/code-reviewer.md +139 -0
  212. package/.cursor/agents/project-manager.md +159 -0
  213. package/.cursor/commands/opsx-apply.md +152 -0
  214. package/.cursor/commands/opsx-archive.md +157 -0
  215. package/.cursor/commands/opsx-bulk-archive.md +242 -0
  216. package/.cursor/commands/opsx-continue.md +114 -0
  217. package/.cursor/commands/opsx-explore.md +174 -0
  218. package/.cursor/commands/opsx-ff.md +94 -0
  219. package/.cursor/commands/opsx-new.md +69 -0
  220. package/.cursor/commands/opsx-onboard.md +525 -0
  221. package/.cursor/commands/opsx-sync.md +134 -0
  222. package/.cursor/commands/opsx-verify.md +164 -0
  223. package/.cursor/mcp.json +22 -0
  224. package/.cursor/skills/add-skill/SKILL.md +352 -0
  225. package/.cursor/skills/api-development/SKILL.md +560 -0
  226. package/.cursor/skills/architecture-design/SKILL.md +756 -0
  227. package/.cursor/skills/backend-annotations/SKILL.md +674 -0
  228. package/.cursor/skills/banana-image/CHANGELOG.md +37 -0
  229. package/.cursor/skills/banana-image/README.md +146 -0
  230. package/.cursor/skills/banana-image/SKILL.md +164 -0
  231. package/.cursor/skills/banana-image/assets/logo.png +0 -0
  232. package/.cursor/skills/banana-image/references/advanced-usage.md +189 -0
  233. package/.cursor/skills/banana-image/scripts/apply_template.py +125 -0
  234. package/.cursor/skills/banana-image/scripts/banana_image_exec.ts +412 -0
  235. package/.cursor/skills/banana-image/scripts/batch_prep.py +82 -0
  236. package/.cursor/skills/banana-image/scripts/package-lock.json +1437 -0
  237. package/.cursor/skills/banana-image/scripts/package.json +18 -0
  238. package/.cursor/skills/banana-image/scripts/requirements.txt +10 -0
  239. package/.cursor/skills/banana-image/templates/poster.json +22 -0
  240. package/.cursor/skills/banana-image/templates/product.json +17 -0
  241. package/.cursor/skills/banana-image/templates/social.json +22 -0
  242. package/.cursor/skills/banana-image/templates/thumbnail.json +17 -0
  243. package/.cursor/skills/brainstorm/SKILL.md +648 -0
  244. package/.cursor/skills/bug-detective/SKILL.md +1206 -0
  245. package/.cursor/skills/code-patterns/SKILL.md +590 -0
  246. package/.cursor/skills/collaborating-with-codex/SKILL.md +174 -0
  247. package/.cursor/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
  248. package/.cursor/skills/collaborating-with-gemini/SKILL.md +194 -0
  249. package/.cursor/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
  250. package/.cursor/skills/crud-development/SKILL.md +649 -0
  251. package/.cursor/skills/data-permission/SKILL.md +599 -0
  252. package/.cursor/skills/database-ops/SKILL.md +407 -0
  253. package/.cursor/skills/error-handler/SKILL.md +371 -0
  254. package/.cursor/skills/file-oss-management/SKILL.md +863 -0
  255. package/.cursor/skills/git-workflow/SKILL.md +375 -0
  256. package/.cursor/skills/json-serialization/SKILL.md +357 -0
  257. package/.cursor/skills/leniu-api-development/SKILL.md +803 -0
  258. package/.cursor/skills/leniu-architecture-design/SKILL.md +598 -0
  259. package/.cursor/skills/leniu-backend-annotations/SKILL.md +664 -0
  260. package/.cursor/skills/leniu-code-patterns/SKILL.md +365 -0
  261. package/.cursor/skills/leniu-crud-development/SKILL.md +1110 -0
  262. package/.cursor/skills/leniu-data-permission/SKILL.md +256 -0
  263. package/.cursor/skills/leniu-database-ops/SKILL.md +426 -0
  264. package/.cursor/skills/leniu-error-handler/SKILL.md +462 -0
  265. package/.cursor/skills/leniu-java-amount-handling/SKILL.md +461 -0
  266. package/.cursor/skills/leniu-java-code-style/SKILL.md +510 -0
  267. package/.cursor/skills/leniu-java-concurrent/SKILL.md +400 -0
  268. package/.cursor/skills/leniu-java-entity/SKILL.md +751 -0
  269. package/.cursor/skills/leniu-java-export/SKILL.md +560 -0
  270. package/.cursor/skills/leniu-java-logging/SKILL.md +832 -0
  271. package/.cursor/skills/leniu-java-mq/SKILL.md +338 -0
  272. package/.cursor/skills/leniu-java-mybatis/SKILL.md +640 -0
  273. package/.cursor/skills/leniu-java-report-query-param/SKILL.md +291 -0
  274. package/.cursor/skills/leniu-java-task/SKILL.md +367 -0
  275. package/.cursor/skills/leniu-java-total-line/SKILL.md +195 -0
  276. package/.cursor/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
  277. package/.cursor/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
  278. package/.cursor/skills/leniu-mealtime/SKILL.md +215 -0
  279. package/.cursor/skills/leniu-redis-cache/SKILL.md +316 -0
  280. package/.cursor/skills/leniu-security-guard/SKILL.md +520 -0
  281. package/.cursor/skills/leniu-utils-toolkit/SKILL.md +380 -0
  282. package/.cursor/skills/openspec-apply-change/SKILL.md +156 -0
  283. package/.cursor/skills/openspec-archive-change/SKILL.md +114 -0
  284. package/.cursor/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  285. package/.cursor/skills/openspec-continue-change/SKILL.md +118 -0
  286. package/.cursor/skills/openspec-explore/SKILL.md +290 -0
  287. package/.cursor/skills/openspec-ff-change/SKILL.md +101 -0
  288. package/.cursor/skills/openspec-new-change/SKILL.md +74 -0
  289. package/.cursor/skills/openspec-onboard/SKILL.md +529 -0
  290. package/.cursor/skills/openspec-sync-specs/SKILL.md +138 -0
  291. package/.cursor/skills/openspec-verify-change/SKILL.md +168 -0
  292. package/.cursor/skills/performance-doctor/SKILL.md +627 -0
  293. package/.cursor/skills/project-navigator/SKILL.md +305 -0
  294. package/.cursor/skills/redis-cache/SKILL.md +839 -0
  295. package/.cursor/skills/scheduled-jobs/SKILL.md +633 -0
  296. package/.cursor/skills/security-guard/SKILL.md +748 -0
  297. package/.cursor/skills/sms-mail/SKILL.md +766 -0
  298. package/.cursor/skills/social-login/SKILL.md +668 -0
  299. package/.cursor/skills/store-pc/SKILL.md +366 -0
  300. package/.cursor/skills/task-tracker/SKILL.md +307 -0
  301. package/.cursor/skills/tech-decision/SKILL.md +393 -0
  302. package/.cursor/skills/tenant-management/SKILL.md +603 -0
  303. package/.cursor/skills/test-development/SKILL.md +755 -0
  304. package/.cursor/skills/ui-pc/SKILL.md +438 -0
  305. package/.cursor/skills/utils-toolkit/SKILL.md +615 -0
  306. package/.cursor/skills/websocket-sse/SKILL.md +716 -0
  307. package/.cursor/skills/workflow-engine/SKILL.md +676 -0
  308. package/AGENTS.md +669 -0
  309. package/CLAUDE.md +205 -0
  310. package/README.md +205 -0
  311. package/bin/index.js +179 -0
  312. package/init.sh +178 -0
  313. package/package.json +27 -0
@@ -0,0 +1,716 @@
1
+ ---
2
+ name: websocket-sse
3
+ description: |
4
+ 当需要实现实时通信、消息推送、在线状态管理时自动使用此 Skill。
5
+
6
+ 触发场景:
7
+ - 需要实现服务端向客户端推送消息
8
+ - 需要实现双向实时通信(聊天、协作)
9
+ - 需要管理用户在线状态
10
+ - 需要实现系统通知、订单状态变更等实时推送
11
+ - 需要在多实例部署环境下同步消息
12
+
13
+ 触发词:WebSocket、SSE、实时推送、消息通知、在线状态、双向通信、Server-Sent Events、实时通信、消息推送、SseEmitter、WebSocketUtils、SseMessageUtils
14
+ ---
15
+
16
+ # 实时通信开发指南(WebSocket & SSE)
17
+
18
+ > **适用模块**:`ruoyi-common-websocket`、`ruoyi-common-sse`
19
+
20
+ ## 概述
21
+
22
+ 本框架提供两种实时通信方案:
23
+
24
+ | 方案 | 模块 | 通信方向 | 适用场景 |
25
+ |------|------|---------|---------|
26
+ | **WebSocket** | `ruoyi-common-websocket` | 双向通信 | 聊天、协作编辑、游戏 |
27
+ | **SSE** | `ruoyi-common-sse` | 服务端→客户端 | 通知推送、状态更新、数据流 |
28
+
29
+ **共同特性**:
30
+ - ✅ Sa-Token 认证集成
31
+ - ✅ Redis 发布订阅(多实例消息同步)
32
+ - ✅ 开箱即用,配置启用即可
33
+
34
+ ---
35
+
36
+ ## 技术选型指南
37
+
38
+ ### 何时使用 WebSocket
39
+
40
+ ```
41
+ ✅ 需要双向通信(客户端也要发送消息)
42
+ ✅ 即时聊天、协作编辑
43
+ ✅ 游戏、实时交互应用
44
+ ✅ 需要低延迟的场景
45
+ ```
46
+
47
+ ### 何时使用 SSE
48
+
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 启用配置
74
+
75
+ ```yaml
76
+ # application.yml
77
+ websocket:
78
+ enabled: true
79
+ path: /resource/websocket # 连接路径(默认)
80
+ allowedOrigins: "*" # 允许跨域(生产环境应限制)
81
+ ```
82
+
83
+ ### 1.2 核心工具类:WebSocketUtils
84
+
85
+ **位置**:`org.dromara.common.websocket.utils.WebSocketUtils`
86
+
87
+ ```java
88
+ import org.dromara.common.websocket.utils.WebSocketUtils;
89
+ import org.dromara.common.websocket.dto.WebSocketMessageDto;
90
+
91
+ // ========== 发送消息 ==========
92
+
93
+ // 1. 向指定用户发送消息(当前服务实例)
94
+ WebSocketUtils.sendMessage(userId, "您有新的订单");
95
+
96
+ // 2. 向指定用户发送消息(支持多实例,通过 Redis 发布订阅)
97
+ WebSocketMessageDto dto = new WebSocketMessageDto();
98
+ dto.setSessionKeys(List.of(userId1, userId2)); // 目标用户ID列表
99
+ dto.setMessage("订单状态已更新");
100
+ WebSocketUtils.publishMessage(dto);
101
+
102
+ // 3. 向所有在线用户发送消息(群发)
103
+ WebSocketUtils.publishAll("系统将于10分钟后维护");
104
+ ```
105
+
106
+ ### 1.3 WebSocketMessageDto
107
+
108
+ ```java
109
+ @Data
110
+ public class WebSocketMessageDto implements Serializable {
111
+ /**
112
+ * 需要推送到的用户ID列表(为空则群发)
113
+ */
114
+ private List<Long> sessionKeys;
115
+
116
+ /**
117
+ * 需要发送的消息内容
118
+ */
119
+ private String message;
120
+ }
121
+ ```
122
+
123
+ ### 1.4 会话管理:WebSocketSessionHolder
124
+
125
+ **位置**:`org.dromara.common.websocket.holder.WebSocketSessionHolder`
126
+
127
+ ```java
128
+ import org.dromara.common.websocket.holder.WebSocketSessionHolder;
129
+
130
+ // 检查用户是否在线(当前实例)
131
+ boolean online = WebSocketSessionHolder.existSession(userId);
132
+
133
+ // 获取所有在线用户ID(当前实例)
134
+ Set<Long> onlineUsers = WebSocketSessionHolder.getSessionsAll();
135
+
136
+ // 获取用户的 WebSocket 会话
137
+ WebSocketSession session = WebSocketSessionHolder.getSessions(userId);
138
+ ```
139
+
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 前端连接示例
192
+
193
+ ```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
+
204
+ ws.onmessage = (event) => {
205
+ 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);
226
+ };
227
+ ```
228
+
229
+ ---
230
+
231
+ ## 二、SSE 开发指南
232
+
233
+ ### 2.1 启用配置
234
+
235
+ ```yaml
236
+ # application.yml
237
+ sse:
238
+ enabled: true
239
+ path: /resource/sse # 连接路径
240
+ ```
241
+
242
+ ### 2.2 核心工具类:SseMessageUtils
243
+
244
+ **位置**:`org.dromara.common.sse.utils.SseMessageUtils`
245
+
246
+ ```java
247
+ import org.dromara.common.sse.utils.SseMessageUtils;
248
+ import org.dromara.common.sse.dto.SseMessageDto;
249
+
250
+ // ========== 发送消息 ==========
251
+
252
+ // 1. 向指定用户发送消息(当前服务实例)
253
+ SseMessageUtils.sendMessage(userId, "您有新的消息");
254
+
255
+ // 2. 向当前实例所有用户发送消息
256
+ SseMessageUtils.sendMessage("系统通知内容");
257
+
258
+ // 3. 向指定用户发送消息(支持多实例,通过 Redis 发布订阅)
259
+ SseMessageDto dto = new SseMessageDto();
260
+ dto.setUserIds(List.of(userId1, userId2)); // 目标用户ID列表
261
+ dto.setMessage("您的审批已通过");
262
+ SseMessageUtils.publishMessage(dto);
263
+
264
+ // 4. 向所有用户发送消息(群发,多实例)
265
+ SseMessageUtils.publishAll("系统维护通知");
266
+
267
+ // 5. 检查 SSE 是否启用
268
+ if (SseMessageUtils.isEnable()) {
269
+ // SSE 已启用
270
+ }
271
+ ```
272
+
273
+ ### 2.3 SseMessageDto
274
+
275
+ ```java
276
+ @Data
277
+ public class SseMessageDto implements Serializable {
278
+ /**
279
+ * 需要推送到的用户ID列表(为空则群发)
280
+ */
281
+ private List<Long> userIds;
282
+
283
+ /**
284
+ * 需要发送的消息内容
285
+ */
286
+ private String message;
287
+ }
288
+ ```
289
+
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 前端连接示例
383
+
384
+ ```javascript
385
+ // 建立 SSE 连接
386
+ const token = getToken();
387
+ const eventSource = new EventSource(`/resource/sse?Authorization=${token}`);
388
+
389
+ eventSource.onopen = () => {
390
+ console.log('SSE 连接成功');
391
+ };
392
+
393
+ // 监听 message 事件
394
+ eventSource.addEventListener('message', (event) => {
395
+ 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
+ });
407
+
408
+ eventSource.onerror = (error) => {
409
+ console.error('SSE 错误:', error);
410
+ // 浏览器会自动尝试重连
411
+ };
412
+
413
+ // 主动关闭连接
414
+ function closeConnection() {
415
+ eventSource.close();
416
+ // 调用后端关闭接口
417
+ fetch('/resource/sse/close').then(() => {
418
+ console.log('SSE 连接已关闭');
419
+ });
420
+ }
421
+ ```
422
+
423
+ ---
424
+
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 消息同步机制
448
+
449
+ **WebSocket 消息发送流程**:
450
+ 1. 调用 `WebSocketUtils.publishMessage(dto)`
451
+ 2. 先检查目标用户是否在当前实例,在则直接发送
452
+ 3. 不在当前实例的用户,通过 Redis 发布到 `global:websocket` 主题
453
+ 4. 其他实例的 `WebSocketTopicListener` 接收并转发给本地用户
454
+
455
+ **SSE 消息发送流程**:
456
+ 1. 调用 `SseMessageUtils.publishMessage(dto)`
457
+ 2. 通过 Redis 发布到 `global:sse` 主题
458
+ 3. 所有实例的 `SseTopicListener` 接收并检查本地用户
459
+ 4. 匹配到的用户通过 `SseEmitter` 推送消息
460
+
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
+ ```
470
+
471
+ ---
472
+
473
+ ## 四、常见场景实战
474
+
475
+ ### 4.1 场景:系统通知推送
476
+
477
+ ```java
478
+ @Service
479
+ @RequiredArgsConstructor
480
+ public class SystemNoticeService {
481
+
482
+ /**
483
+ * 发送系统通知(SSE 方式)
484
+ */
485
+ public void sendNotice(Long userId, String title, String content) {
486
+ String message = JsonUtils.toJsonString(Map.of(
487
+ "type", "SYSTEM_NOTICE",
488
+ "title", title,
489
+ "content", content,
490
+ "time", DateUtils.getTime()
491
+ ));
492
+
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)
566
+ SseMessageDto buyerDto = new SseMessageDto();
567
+ buyerDto.setUserIds(List.of(order.getBuyerId()));
568
+ buyerDto.setMessage(message);
569
+ SseMessageUtils.publishMessage(buyerDto);
570
+
571
+ // 3. 通知卖家(WebSocket,如果需要双向通信)
572
+ WebSocketMessageDto sellerDto = new WebSocketMessageDto();
573
+ sellerDto.setSessionKeys(List.of(order.getSellerId()));
574
+ sellerDto.setMessage(message);
575
+ WebSocketUtils.publishMessage(sellerDto);
576
+ }
577
+ }
578
+ ```
579
+
580
+ ---
581
+
582
+ ## 五、常见错误与最佳实践
583
+
584
+ ### ❌ 错误1:未启用模块就使用
585
+
586
+ ```java
587
+ // ❌ 错误:未配置 websocket.enabled=true
588
+ WebSocketUtils.sendMessage(userId, "消息"); // 用户收不到
589
+ ```
590
+
591
+ ```yaml
592
+ # ✅ 正确:先启用
593
+ websocket:
594
+ enabled: true
595
+ ```
596
+
597
+ ### ❌ 错误2:混淆单实例和多实例方法
598
+
599
+ ```java
600
+ // ❌ 错误:使用 sendMessage 在多实例环境
601
+ WebSocketUtils.sendMessage(userId, "消息"); // 只能发给当前实例的用户
602
+
603
+ // ✅ 正确:使用 publishMessage 支持多实例
604
+ WebSocketMessageDto dto = new WebSocketMessageDto();
605
+ dto.setSessionKeys(List.of(userId));
606
+ dto.setMessage("消息");
607
+ WebSocketUtils.publishMessage(dto); // 通过 Redis 广播到所有实例
608
+ ```
609
+
610
+ ### ❌ 错误3:SSE 连接未关闭导致资源泄漏
611
+
612
+ ```javascript
613
+ // ❌ 错误:页面关闭时未主动关闭 SSE
614
+ window.onbeforeunload = () => {
615
+ // 没有关闭 eventSource
616
+ };
617
+
618
+ // ✅ 正确:主动关闭连接
619
+ window.onbeforeunload = () => {
620
+ eventSource.close();
621
+ navigator.sendBeacon('/resource/sse/close'); // 使用 sendBeacon 确保请求发出
622
+ };
623
+ ```
624
+
625
+ ### ❌ 错误4:消息格式不统一
626
+
627
+ ```java
628
+ // ❌ 错误:直接发送字符串,前端难以解析
629
+ WebSocketUtils.publishAll("订单已更新");
630
+
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);
638
+ ```
639
+
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
+ ---
683
+
684
+ ## 七、配置参考
685
+
686
+ ### WebSocket 完整配置
687
+
688
+ ```yaml
689
+ websocket:
690
+ enabled: true # 是否启用(必填)
691
+ path: /resource/websocket # 连接路径(默认 /resource/websocket)
692
+ allowedOrigins: "*" # 允许跨域来源(生产环境应限制)
693
+ ```
694
+
695
+ ### SSE 完整配置
696
+
697
+ ```yaml
698
+ sse:
699
+ enabled: true # 是否启用(必填)
700
+ path: /resource/sse # 连接路径(必填)
701
+ ```
702
+
703
+ ---
704
+
705
+ ## 八、参考代码位置
706
+
707
+ | 类型 | 位置 |
708
+ |------|------|
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` |