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,633 @@
1
+ ---
2
+ name: scheduled-jobs
3
+ description: |
4
+ 定时任务开发指南。涵盖 @Scheduled、SnailJob 两种方案,支持分布式任务调度、失败重试、工作流编排。
5
+
6
+ 触发场景:
7
+ - 每日数据汇总、定期清理等周期性任务(@Scheduled)
8
+ - 分布式复杂业务、失败重试、可视化管理(SnailJob)
9
+ - 任务分片、Map/MapReduce 分布式计算
10
+ - 广播任务(所有节点执行)
11
+
12
+ 触发词:定时任务、SnailJob、任务调度、重试机制、工作流、@JobExecutor、@Scheduled、分布式任务、广播任务、分片任务、MapReduce
13
+
14
+ 核心特性:
15
+ - 方案 1:@Scheduled(简单周期任务、框架内置)
16
+ - 方案 2:SnailJob(分布式集群、可视化管理、失败重试、工作流编排)
17
+ ---
18
+
19
+ # 定时任务开发指南
20
+
21
+ > 模块位置:`ruoyi-modules/ruoyi-job`
22
+
23
+ ## 快速索引
24
+
25
+ | 场景 | 推荐方案 | 理由 |
26
+ |------|---------|------|
27
+ | 简单周期任务(日报、清理) | `@Scheduled` | 框架内置、无依赖 |
28
+ | 分布式任务、失败重试 | **SnailJob** | 可视化管理、完整重试 |
29
+ | 广播任务(所有节点执行) | **SnailJob** | 支持广播模式 |
30
+ | 任务分片(海量数据) | **SnailJob** | 支持静态分片/Map/MapReduce |
31
+
32
+ ---
33
+
34
+ ## 一、@Scheduled 方案(简单场景)
35
+
36
+ ### 1.1 快速开始
37
+
38
+ ```java
39
+ import org.springframework.scheduling.annotation.Scheduled;
40
+ import lombok.extern.slf4j.Slf4j;
41
+
42
+ @Slf4j
43
+ @Component
44
+ public class SimpleScheduledTask {
45
+
46
+ // ✅ 每天凌晨 2 点执行
47
+ @Scheduled(cron = "0 0 2 * * ?")
48
+ public void dailyCleanup() {
49
+ log.info("开始清理过期数据");
50
+ // 业务逻辑
51
+ }
52
+
53
+ // ✅ 固定频率:每隔 60 秒执行
54
+ @Scheduled(fixedRate = 60000)
55
+ public void syncData() {
56
+ log.info("同步数据");
57
+ }
58
+
59
+ // ✅ 固定延迟:上次执行结束后延迟 30 秒
60
+ @Scheduled(fixedDelay = 30000)
61
+ public void checkStatus() {
62
+ log.info("检查状态");
63
+ }
64
+
65
+ // ✅ 初始延迟:启动 10 秒后才开始
66
+ @Scheduled(initialDelay = 10000, fixedRate = 60000)
67
+ public void reportStats() {
68
+ log.info("生成统计");
69
+ }
70
+ }
71
+ ```
72
+
73
+ ### 1.2 CRON 表达式
74
+
75
+ ```
76
+ ┌───────────── 秒 (0-59)
77
+ │ ┌───────────── 分钟 (0-59)
78
+ │ │ ┌───────────── 小时 (0-23)
79
+ │ │ │ ┌───────────── 日期 (1-31)
80
+ │ │ │ │ ┌───────────── 月份 (1-12)
81
+ │ │ │ │ │ ┌───────────── 星期 (0-7, 0和7都是周日)
82
+ * * * * * *
83
+ ```
84
+
85
+ | 表达式 | 说明 |
86
+ |--------|------|
87
+ | `0 0 2 * * ?` | 每天 2:00 |
88
+ | `0 */5 * * * ?` | 每 5 分钟 |
89
+ | `0 0 */6 * * ?` | 每 6 小时 |
90
+ | `0 0 0 * * MON` | 每周一 0:00 |
91
+ | `0 0 0 1 * ?` | 每月 1 号 0:00 |
92
+
93
+ ### 1.3 适用场景
94
+
95
+ - ✅ 任务数 < 100
96
+ - ✅ 简单逻辑、无需重试
97
+ - ✅ 单机执行即可
98
+ - ❌ 不适合:需要可视化管理、失败重试、分布式
99
+
100
+ ---
101
+
102
+ ## 二、SnailJob 方案(分布式场景)
103
+
104
+ > 源码位置:`ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/`
105
+
106
+ ### 2.1 核心特性
107
+
108
+ | 特性 | 说明 |
109
+ |------|------|
110
+ | 可视化管理 | Web 界面管理任务 |
111
+ | 失败重试 | 多策略:指数退避、固定间隔 |
112
+ | 执行模式 | 集群、广播、静态分片、Map、MapReduce |
113
+ | 任务监控 | 实时日志、告警通知 |
114
+ | 工作流编排 | 可视化流程、决策节点 |
115
+
116
+ ### 2.2 配置
117
+
118
+ ```yaml
119
+ # application-dev.yml
120
+ snail-job:
121
+ enabled: ${SNAIL_JOB_ENABLED:false}
122
+ group: ${app.id}
123
+ token: ${SNAIL_JOB_TOKEN:SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT}
124
+ server:
125
+ host: ${SNAIL_JOB_HOST:127.0.0.1}
126
+ port: ${SNAIL_JOB_PORT:17888}
127
+ namespace: ${spring.profiles.active}
128
+ port: 2${server.port}
129
+ ```
130
+
131
+ ### 2.3 启用配置
132
+
133
+ ```java
134
+ // 位置:ruoyi-common/ruoyi-common-job/.../config/SnailJobConfig.java
135
+ @AutoConfiguration
136
+ @ConditionalOnProperty(prefix = "snail-job", name = "enabled", havingValue = "true")
137
+ @EnableScheduling
138
+ @EnableSnailJob
139
+ public class SnailJobConfig {
140
+ }
141
+ ```
142
+
143
+ ---
144
+
145
+ ## 三、SnailJob 任务类型
146
+
147
+ ### 3.1 基础任务(注解方式)
148
+
149
+ > 源码:`ruoyi-job/.../snailjob/TestAnnoJobExecutor.java`
150
+
151
+ ```java
152
+ import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
153
+ import com.aizuda.snailjob.client.job.core.dto.JobArgs;
154
+ import com.aizuda.snailjob.model.dto.ExecuteResult;
155
+ import com.aizuda.snailjob.common.log.SnailJobLog;
156
+ import com.aizuda.snailjob.common.core.util.JsonUtil;
157
+
158
+ @Component
159
+ @JobExecutor(name = "testJobExecutor")
160
+ public class TestAnnoJobExecutor {
161
+
162
+ /**
163
+ * 任务执行方法
164
+ *
165
+ * @param jobArgs 任务参数(包含 jobParams、executorInfo 等)
166
+ * @return ExecuteResult 执行结果
167
+ */
168
+ public ExecuteResult jobExecute(JobArgs jobArgs) {
169
+ // 本地日志(输出到控制台)
170
+ SnailJobLog.LOCAL.info("任务执行,参数: {}", JsonUtil.toJsonString(jobArgs));
171
+
172
+ // 远程日志(上报到 SnailJob 控制台)
173
+ SnailJobLog.REMOTE.info("任务执行,参数: {}", JsonUtil.toJsonString(jobArgs));
174
+
175
+ // 获取任务参数
176
+ String jobParams = jobArgs.getJobParams();
177
+
178
+ // 业务逻辑...
179
+
180
+ return ExecuteResult.success("执行成功");
181
+ }
182
+ }
183
+ ```
184
+
185
+ ### 3.2 基础任务(类方式)
186
+
187
+ > 源码:`ruoyi-job/.../snailjob/TestClassJobExecutor.java`
188
+
189
+ ```java
190
+ import com.aizuda.snailjob.client.job.core.executor.AbstractJobExecutor;
191
+ import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
192
+ import com.aizuda.snailjob.client.job.core.dto.JobArgs;
193
+ import com.aizuda.snailjob.model.dto.ExecuteResult;
194
+ import com.aizuda.snailjob.common.log.SnailJobLog;
195
+
196
+ @Component
197
+ public class TestClassJobExecutor extends AbstractJobExecutor {
198
+
199
+ @Override
200
+ protected ExecuteResult doJobExecute(JobArgs jobArgs) {
201
+ SnailJobLog.REMOTE.info("类方式执行器,参数: {}", jobArgs.getJobParams());
202
+ return ExecuteResult.success("类方式执行成功");
203
+ }
204
+ }
205
+ ```
206
+
207
+ ### 3.3 广播任务
208
+
209
+ > 源码:`ruoyi-job/.../snailjob/TestBroadcastJob.java`
210
+
211
+ 广播任务会在**所有节点**上执行,适用于清理本地缓存等场景。
212
+
213
+ ```java
214
+ import cn.hutool.core.util.RandomUtil;
215
+ import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
216
+ import com.aizuda.snailjob.client.job.core.dto.JobArgs;
217
+ import com.aizuda.snailjob.model.dto.ExecuteResult;
218
+ import com.aizuda.snailjob.common.log.SnailJobLog;
219
+ import org.springframework.beans.factory.annotation.Value;
220
+
221
+ @Slf4j
222
+ @Component
223
+ @JobExecutor(name = "testBroadcastJob")
224
+ public class TestBroadcastJob {
225
+
226
+ @Value("${snail-job.port}")
227
+ private int clientPort;
228
+
229
+ public ExecuteResult jobExecute(JobArgs jobArgs) {
230
+ int randomInt = RandomUtil.randomInt(100);
231
+ SnailJobLog.REMOTE.info("广播任务执行,客户端端口: {}, 随机数: {}", clientPort, randomInt);
232
+
233
+ if (randomInt < 50) {
234
+ // 抛出异常会触发重试
235
+ throw new RuntimeException("随机数小于50,任务失败");
236
+ }
237
+
238
+ return ExecuteResult.success("广播任务执行成功");
239
+ }
240
+ }
241
+ ```
242
+
243
+ ### 3.4 静态分片任务
244
+
245
+ > 源码:`ruoyi-job/.../snailjob/TestStaticShardingJob.java`
246
+
247
+ 静态分片将任务按固定数量分成多个分片,每个节点执行不同分片。
248
+
249
+ ```java
250
+ import cn.hutool.core.convert.Convert;
251
+ import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
252
+ import com.aizuda.snailjob.client.job.core.dto.JobArgs;
253
+ import com.aizuda.snailjob.model.dto.ExecuteResult;
254
+ import com.aizuda.snailjob.common.log.SnailJobLog;
255
+
256
+ @Component
257
+ @JobExecutor(name = "testStaticShardingJob")
258
+ public class TestStaticShardingJob {
259
+
260
+ /**
261
+ * 静态分片任务
262
+ * jobParams 格式:起始ID,结束ID(如:1,100000)
263
+ */
264
+ public ExecuteResult jobExecute(JobArgs jobArgs) {
265
+ String jobParams = Convert.toStr(jobArgs.getJobParams());
266
+ SnailJobLog.LOCAL.info("开始执行分片任务,参数: {}", jobParams);
267
+
268
+ // 解析分片参数
269
+ String[] split = jobParams.split(",");
270
+ Long fromId = Long.parseLong(split[0]);
271
+ Long toId = Long.parseLong(split[1]);
272
+
273
+ SnailJobLog.REMOTE.info("处理 ID 范围: {} - {}", fromId, toId);
274
+
275
+ // 业务逻辑:处理该范围的数据
276
+ // processDataRange(fromId, toId);
277
+
278
+ return ExecuteResult.success("分片任务完成");
279
+ }
280
+ }
281
+ ```
282
+
283
+ **控制台配置分片**:
284
+ 1. 任务类型选择"静态分片"
285
+ 2. 分片参数设置多组(每组对应一个分片):
286
+ - 分片 0:`1,100000`
287
+ - 分片 1:`100001,200000`
288
+ - 分片 2:`200001,300000`
289
+
290
+ ### 3.5 Map 任务(动态分片)
291
+
292
+ > 源码:`ruoyi-job/.../snailjob/TestMapJobAnnotation.java`
293
+
294
+ Map 任务适用于需要动态拆分数据的场景,先 Map 分片,然后并行执行。
295
+
296
+ ```java
297
+ import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
298
+ import com.aizuda.snailjob.client.job.core.annotation.MapExecutor;
299
+ import com.aizuda.snailjob.client.job.core.dto.MapArgs;
300
+ import com.aizuda.snailjob.client.job.core.MapHandler;
301
+ import com.aizuda.snailjob.model.dto.ExecuteResult;
302
+ import com.aizuda.snailjob.common.log.SnailJobLog;
303
+
304
+ import java.util.List;
305
+ import java.util.stream.Collectors;
306
+ import java.util.stream.IntStream;
307
+
308
+ @Component
309
+ @JobExecutor(name = "testMapJobAnnotation")
310
+ public class TestMapJobAnnotation {
311
+
312
+ /**
313
+ * Map 入口:拆分数据
314
+ * 无 taskName 的 @MapExecutor 是入口方法
315
+ */
316
+ @MapExecutor
317
+ public ExecuteResult doJobMapExecute(MapArgs mapArgs, MapHandler mapHandler) {
318
+ SnailJobLog.REMOTE.info("Map 入口执行");
319
+
320
+ // 将 1-200 按每组 50 个分成 4 组
321
+ List<List<Integer>> partition = IntStream.rangeClosed(1, 200)
322
+ .boxed()
323
+ .collect(Collectors.groupingBy(i -> (i - 1) / 50))
324
+ .values()
325
+ .stream()
326
+ .toList();
327
+
328
+ // 分发到子任务 doCalc
329
+ return mapHandler.doMap(partition, "doCalc");
330
+ }
331
+
332
+ /**
333
+ * Map 子任务:处理每个分片
334
+ */
335
+ @MapExecutor(taskName = "doCalc")
336
+ public ExecuteResult doCalc(MapArgs mapArgs) {
337
+ // 获取当前分片的数据
338
+ List<Integer> sourceList = (List<Integer>) mapArgs.getMapResult();
339
+
340
+ SnailJobLog.REMOTE.info("处理分片数据,数量: {}", sourceList.size());
341
+
342
+ // 计算当前分片的总和
343
+ int partitionTotal = sourceList.stream().mapToInt(i -> i).sum();
344
+
345
+ return ExecuteResult.success(partitionTotal);
346
+ }
347
+ }
348
+ ```
349
+
350
+ ### 3.6 MapReduce 任务(分片 + 汇总)
351
+
352
+ > 源码:`ruoyi-job/.../snailjob/TestMapReduceAnnotation1.java`
353
+
354
+ MapReduce 在 Map 基础上增加了 Reduce 汇总阶段。
355
+
356
+ ```java
357
+ import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
358
+ import com.aizuda.snailjob.client.job.core.annotation.MapExecutor;
359
+ import com.aizuda.snailjob.client.job.core.annotation.ReduceExecutor;
360
+ import com.aizuda.snailjob.client.job.core.dto.MapArgs;
361
+ import com.aizuda.snailjob.client.job.core.dto.ReduceArgs;
362
+ import com.aizuda.snailjob.client.job.core.MapHandler;
363
+ import com.aizuda.snailjob.model.dto.ExecuteResult;
364
+ import com.aizuda.snailjob.common.log.SnailJobLog;
365
+
366
+ import java.util.List;
367
+ import java.util.stream.Collectors;
368
+ import java.util.stream.IntStream;
369
+
370
+ @Component
371
+ @JobExecutor(name = "testMapReduceAnnotation1")
372
+ public class TestMapReduceAnnotation1 {
373
+
374
+ /**
375
+ * Map 入口:拆分数据
376
+ */
377
+ @MapExecutor
378
+ public ExecuteResult rootMapExecute(MapArgs mapArgs, MapHandler mapHandler) {
379
+ SnailJobLog.REMOTE.info("MapReduce 入口执行");
380
+
381
+ // 将 1-200 按每组 50 个分成 4 组
382
+ List<List<Integer>> partition = IntStream.rangeClosed(1, 200)
383
+ .boxed()
384
+ .collect(Collectors.groupingBy(i -> (i - 1) / 50))
385
+ .values()
386
+ .stream()
387
+ .toList();
388
+
389
+ return mapHandler.doMap(partition, "doCalc");
390
+ }
391
+
392
+ /**
393
+ * Map 子任务:计算每个分片的总和
394
+ */
395
+ @MapExecutor(taskName = "doCalc")
396
+ public ExecuteResult doCalc(MapArgs mapArgs) {
397
+ List<Integer> sourceList = (List<Integer>) mapArgs.getMapResult();
398
+
399
+ int partitionTotal = sourceList.stream().mapToInt(i -> i).sum();
400
+
401
+ SnailJobLog.REMOTE.info("分片计算完成,总和: {}", partitionTotal);
402
+
403
+ return ExecuteResult.success(partitionTotal);
404
+ }
405
+
406
+ /**
407
+ * Reduce 汇总:合并所有分片结果
408
+ */
409
+ @ReduceExecutor
410
+ public ExecuteResult reduceExecute(ReduceArgs reduceArgs) {
411
+ // 获取所有 Map 子任务的结果
412
+ List<?> mapResults = reduceArgs.getMapResult();
413
+
414
+ int reduceTotal = mapResults.stream()
415
+ .mapToInt(i -> Integer.parseInt((String) i))
416
+ .sum();
417
+
418
+ SnailJobLog.REMOTE.info("Reduce 汇总完成,最终总和: {}", reduceTotal);
419
+
420
+ return ExecuteResult.success(reduceTotal);
421
+ }
422
+ }
423
+ ```
424
+
425
+ ---
426
+
427
+ ## 四、SnailJob 日志工具
428
+
429
+ ### 4.1 日志类型
430
+
431
+ ```java
432
+ import com.aizuda.snailjob.common.log.SnailJobLog;
433
+
434
+ // 本地日志(输出到控制台/日志文件)
435
+ SnailJobLog.LOCAL.info("本地日志: {}", message);
436
+ SnailJobLog.LOCAL.warn("警告: {}", message);
437
+ SnailJobLog.LOCAL.error("错误: {}", message, exception);
438
+
439
+ // 远程日志(上报到 SnailJob 控制台,可在 Web 界面查看)
440
+ SnailJobLog.REMOTE.info("远程日志: {}", message);
441
+ SnailJobLog.REMOTE.warn("警告: {}", message);
442
+ SnailJobLog.REMOTE.error("错误: {}", message, exception);
443
+ ```
444
+
445
+ ### 4.2 日志最佳实践
446
+
447
+ ```java
448
+ @Component
449
+ @JobExecutor(name = "orderProcessJob")
450
+ public class OrderProcessJob {
451
+
452
+ public ExecuteResult jobExecute(JobArgs jobArgs) {
453
+ String jobParams = jobArgs.getJobParams();
454
+
455
+ // 1. 记录任务开始
456
+ SnailJobLog.REMOTE.info("开始处理订单,参数: {}", jobParams);
457
+
458
+ try {
459
+ // 2. 业务逻辑
460
+ int count = processOrders(jobParams);
461
+
462
+ // 3. 记录成功
463
+ SnailJobLog.REMOTE.info("订单处理完成,处理数量: {}", count);
464
+ return ExecuteResult.success("处理 " + count + " 条订单");
465
+
466
+ } catch (Exception e) {
467
+ // 4. 记录失败(同时记录本地和远程)
468
+ SnailJobLog.LOCAL.error("订单处理失败", e);
469
+ SnailJobLog.REMOTE.error("订单处理失败: {}", e.getMessage());
470
+
471
+ // 抛出异常触发重试
472
+ throw e;
473
+ }
474
+ }
475
+ }
476
+ ```
477
+
478
+ ---
479
+
480
+ ## 五、执行模式对比
481
+
482
+ | 模式 | 特点 | 适用场景 |
483
+ |------|------|---------|
484
+ | **集群** | 多节点竞争,只有一个执行 | 订单处理、数据汇总 |
485
+ | **广播** | 所有节点都执行 | 清理缓存、刷新配置 |
486
+ | **静态分片** | 按固定规则分片 | 已知数据范围的批处理 |
487
+ | **Map** | 动态分片 | 需要运行时确定分片的场景 |
488
+ | **MapReduce** | 动态分片 + 结果汇总 | 分布式计算(求和、统计) |
489
+
490
+ ---
491
+
492
+ ## 六、控制台配置
493
+
494
+ ### 6.1 创建任务
495
+
496
+ 1. 访问 SnailJob 控制台
497
+ 2. **任务管理** → **新增任务**
498
+ 3. 配置项:
499
+ - 任务名称:`testJobExecutor`(与 `@JobExecutor(name)` 一致)
500
+ - 任务类型:集群/广播/静态分片/Map/MapReduce
501
+ - 触发类型:CRON / 固定频率
502
+ - CRON 表达式:`0 0 2 * * ?`
503
+
504
+ ### 6.2 重试策略
505
+
506
+ | 策略 | 说明 | 使用场景 |
507
+ |------|------|---------|
508
+ | 固定间隔 | 每次间隔相同 | 网络抖动 |
509
+ | 指数退避 | 间隔逐倍增加 | 服务恢复中 |
510
+ | CRON | 按表达式重试 | 定点重试 |
511
+
512
+ ---
513
+
514
+ ## 七、最佳实践
515
+
516
+ ### 7.1 任务实现规范
517
+
518
+ ```java
519
+ @Component
520
+ @JobExecutor(name = "orderCleanupJob")
521
+ public class OrderCleanupJob {
522
+
523
+ @Autowired
524
+ private IOrderService orderService;
525
+
526
+ public ExecuteResult jobExecute(JobArgs jobArgs) {
527
+ SnailJobLog.REMOTE.info("开始清理过期订单");
528
+
529
+ try {
530
+ // 1. 解析参数
531
+ String params = jobArgs.getJobParams();
532
+ int days = StringUtils.isBlank(params) ? 30 : Integer.parseInt(params);
533
+
534
+ // 2. 执行业务
535
+ int count = orderService.cleanupExpiredOrders(days);
536
+
537
+ // 3. 返回成功
538
+ SnailJobLog.REMOTE.info("清理完成,删除 {} 条订单", count);
539
+ return ExecuteResult.success("清理 " + count + " 条");
540
+
541
+ } catch (Exception e) {
542
+ SnailJobLog.REMOTE.error("清理失败: {}", e.getMessage());
543
+ throw e; // 抛出异常触发重试
544
+ }
545
+ }
546
+ }
547
+ ```
548
+
549
+ ### 7.2 幂等性保证
550
+
551
+ ```java
552
+ @Component
553
+ @JobExecutor(name = "paymentSyncJob")
554
+ public class PaymentSyncJob {
555
+
556
+ public ExecuteResult jobExecute(JobArgs jobArgs) {
557
+ String orderId = jobArgs.getJobParams();
558
+
559
+ // 1. 幂等检查
560
+ if (paymentService.isSynced(orderId)) {
561
+ SnailJobLog.REMOTE.info("订单 {} 已同步,跳过", orderId);
562
+ return ExecuteResult.success("已同步");
563
+ }
564
+
565
+ // 2. 执行同步
566
+ paymentService.sync(orderId);
567
+
568
+ return ExecuteResult.success("同步成功");
569
+ }
570
+ }
571
+ ```
572
+
573
+ ### 7.3 错误处理
574
+
575
+ ```java
576
+ // ✅ 正确:抛出异常触发重试
577
+ public ExecuteResult jobExecute(JobArgs jobArgs) {
578
+ try {
579
+ // 业务逻辑
580
+ } catch (Exception e) {
581
+ SnailJobLog.REMOTE.error("执行失败", e);
582
+ throw e; // ✅ 抛出异常,SnailJob 会自动重试
583
+ }
584
+ }
585
+
586
+ // ❌ 错误:吞掉异常,不会触发重试
587
+ public ExecuteResult jobExecute(JobArgs jobArgs) {
588
+ try {
589
+ // 业务逻辑
590
+ } catch (Exception e) {
591
+ SnailJobLog.REMOTE.error("执行失败", e);
592
+ return ExecuteResult.failure("失败"); // ❌ 不会触发重试
593
+ }
594
+ }
595
+ ```
596
+
597
+ ---
598
+
599
+ ## 八、常见问题
600
+
601
+ ### Q1:任务不执行?
602
+
603
+ 1. 检查 `snail-job.enabled: true`
604
+ 2. 检查 `@JobExecutor(name)` 与控制台配置一致
605
+ 3. 检查 SnailJob 服务是否启动
606
+ 4. 查看日志是否有连接错误
607
+
608
+ ### Q2:@Scheduled vs SnailJob 怎么选?
609
+
610
+ | 条件 | 选择 |
611
+ |------|------|
612
+ | 任务 < 100,简单逻辑 | `@Scheduled` |
613
+ | 需要重试、监控 | SnailJob |
614
+ | 分布式部署 | SnailJob |
615
+ | 需要 Web 管理 | SnailJob |
616
+
617
+ ### Q3:如何查看任务日志?
618
+
619
+ - **本地日志**:查看应用日志文件
620
+ - **远程日志**:SnailJob 控制台 → 任务实例 → 查看日志
621
+
622
+ ---
623
+
624
+ ## 九、核心文件位置
625
+
626
+ | 文件 | 路径 |
627
+ |------|------|
628
+ | 注解方式示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestAnnoJobExecutor.java` |
629
+ | 类方式示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestClassJobExecutor.java` |
630
+ | 广播任务示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestBroadcastJob.java` |
631
+ | 静态分片示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestStaticShardingJob.java` |
632
+ | Map 任务示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestMapJobAnnotation.java` |
633
+ | MapReduce 示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestMapReduceAnnotation1.java` |