💡 摘要: 传统 SpringBoot 项目开发中,Controller/Service/Mapper/DTO 四层代码占据总编码量的 60% 以上,从建项目搭骨架到写 JWT 鉴权,一个简单 CRUD 接口平均耗时 45 分钟。WorkBuddy 是腾讯推出的 AI 原生桌面工作台,能直接操作本地 IDE 和文件系统,用自然语言指令驱动 SpringBoot 代码生成、依赖管理、数据库反向建模和单元测试编写。本文通过 JWT 登录接口、RabbitMQ 消息消费、MyBatis-Plus 逆向生成三个实战案例,实测将纯手工 4.5 小时的开发流程压缩至 35 分钟,效率提升 87%。
📅 技术栈版本: WorkBuddy v2.6+ | Spring Boot 3.3.x | JDK 17+ | MyBatis-Plus 3.5.x | 更新时间: 2026-06
一、背景与痛点
1.1 一个 SpringBoot CRUD 接口的开发真相
2026 年 5 月,我带一个 4 人后端小组开发企业 OA 系统。某天下午,产品甩来一个需求:“用户管理模块,支持按部门筛选、分页查询、批量导出”。我看着组员统计了实际耗时:
| 创建 Entity + DTO | 手写 @Entity、@Column、Getter/Setter | 12 分钟 |
| 编写 Mapper | XML 映射、分页 SQL 手写 | 15 分钟 |
| 实现 Service | 业务逻辑 + 事务 + 异常处理 | 18 分钟 |
| 写 Controller | 参数校验 + 返回格式 + Swagger 注解 | 10 分钟 |
| 联调修正 | 字段名拼错、类型不对 | 20 分钟 |
| 合计 | 75 分钟 |
一个 75 分钟的 CRUD 接口,真正需要动脑的业务逻辑只有 15%——其余全是机械性的"体力编码"。
1.2 三个典型痛点
痛点一:项目骨架搭建繁琐
每次新模块都要:建包 → 写 pom.xml 依赖 → 配置 application.yml → 建 Controller/Service/Mapper/DTO 四层目录。这些步骤没有技术含量,但缺一步就编译不过。
痛点二:安全代码容易遗漏
写登录接口时,JWT 生成、BCrypt 加密、Token 刷新、过期处理这些安全代码逻辑固定但代码量大,手写容易遗漏异常处理导致生产事故。
痛点三:消息中间件集成门槛高
RabbitMQ 消费者需要写 @RabbitListener、消息确认、异常重试、死信队列、JSON 解析——配置项多,新手容易写错。
1.3 成本量化
按一个 4 人后端团队、月均开发 40 个接口计算:
| 单接口平均耗时 | 45 分钟 | 8 分钟 | 缩短 82% |
| 月度新增 Bug 数 | 24 个 | 6 个 | 降低 75% |
| 代码风格投诉(CR) | 12 次/周 | 2 次/周 | 降低 83% |
| 新人上手时间 | 2 周 | 3 天 | 缩短 79% |
二、WorkBuddy 核心能力
2.1 产品定位
WorkBuddy 是腾讯推出的 AI 原生桌面智能体工作台,与 Copilot 等行内补全工具有本质区别:
#mermaid-svg-HeAnHc14c81tZruK{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HeAnHc14c81tZruK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HeAnHc14c81tZruK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HeAnHc14c81tZruK .error-icon{fill:#552222;}#mermaid-svg-HeAnHc14c81tZruK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HeAnHc14c81tZruK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HeAnHc14c81tZruK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HeAnHc14c81tZruK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HeAnHc14c81tZruK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HeAnHc14c81tZruK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HeAnHc14c81tZruK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HeAnHc14c81tZruK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HeAnHc14c81tZruK .marker.cross{stroke:#333333;}#mermaid-svg-HeAnHc14c81tZruK svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HeAnHc14c81tZruK p{margin:0;}#mermaid-svg-HeAnHc14c81tZruK .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-HeAnHc14c81tZruK .cluster-label text{fill:#333;}#mermaid-svg-HeAnHc14c81tZruK .cluster-label span{color:#333;}#mermaid-svg-HeAnHc14c81tZruK .cluster-label span p{background-color:transparent;}#mermaid-svg-HeAnHc14c81tZruK .label text,#mermaid-svg-HeAnHc14c81tZruK span{fill:#333;color:#333;}#mermaid-svg-HeAnHc14c81tZruK .node rect,#mermaid-svg-HeAnHc14c81tZruK .node circle,#mermaid-svg-HeAnHc14c81tZruK .node ellipse,#mermaid-svg-HeAnHc14c81tZruK .node polygon,#mermaid-svg-HeAnHc14c81tZruK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HeAnHc14c81tZruK .rough-node .label text,#mermaid-svg-HeAnHc14c81tZruK .node .label text,#mermaid-svg-HeAnHc14c81tZruK .image-shape .label,#mermaid-svg-HeAnHc14c81tZruK .icon-shape .label{text-anchor:middle;}#mermaid-svg-HeAnHc14c81tZruK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HeAnHc14c81tZruK .rough-node .label,#mermaid-svg-HeAnHc14c81tZruK .node .label,#mermaid-svg-HeAnHc14c81tZruK .image-shape .label,#mermaid-svg-HeAnHc14c81tZruK .icon-shape .label{text-align:center;}#mermaid-svg-HeAnHc14c81tZruK .node.clickable{cursor:pointer;}#mermaid-svg-HeAnHc14c81tZruK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HeAnHc14c81tZruK .arrowheadPath{fill:#333333;}#mermaid-svg-HeAnHc14c81tZruK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HeAnHc14c81tZruK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HeAnHc14c81tZruK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HeAnHc14c81tZruK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HeAnHc14c81tZruK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HeAnHc14c81tZruK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HeAnHc14c81tZruK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HeAnHc14c81tZruK .cluster text{fill:#333;}#mermaid-svg-HeAnHc14c81tZruK .cluster span{color:#333;}#mermaid-svg-HeAnHc14c81tZruK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HeAnHc14c81tZruK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HeAnHc14c81tZruK rect.text{fill:none;stroke-width:0;}#mermaid-svg-HeAnHc14c81tZruK .icon-shape,#mermaid-svg-HeAnHc14c81tZruK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HeAnHc14c81tZruK .icon-shape p,#mermaid-svg-HeAnHc14c81tZruK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HeAnHc14c81tZruK .icon-shape .label rect,#mermaid-svg-HeAnHc14c81tZruK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HeAnHc14c81tZruK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HeAnHc14c81tZruK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HeAnHc14c81tZruK :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
WorkBuddy AI Agent
WorkBuddy
读写本地文件
执行 Maven/Gradle
修改 pom.xml
连接数据库
生成完整项目骨架
传统 AI 编程助手
Copilot
行内代码补全
对话式问答
❌ 不能操作文件
❌ 不能运行命令
一句话总结:Copilot 帮你"想代码",WorkBuddy 帮你"写代码 + 跑代码 + 修代码"。
2.2 SpringBoot 开发的三大能力
| 智能代码生成 | 自然语言描述需求,生成完整 Controller/Service/Mapper 层 | “创建一个用户登录接口,用 JWT+BCrypt” |
| 数据库反向建模 | 连接 MySQL,读取表结构,生成 Entity+Mapper+Service+Controller | “把 user_info 表生成全套 CRUD 代码” |
| 项目环境管理 | 自动识别缺失依赖,修改 pom.xml,运行 mvn clean install | “检查项目是否缺少 spring-boot-starter-amqp” |
2.3 WorkBuddy SpringBoot 开发工作流
#mermaid-svg-uoFRWR2DS9GvkDL2{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uoFRWR2DS9GvkDL2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uoFRWR2DS9GvkDL2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uoFRWR2DS9GvkDL2 .error-icon{fill:#552222;}#mermaid-svg-uoFRWR2DS9GvkDL2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uoFRWR2DS9GvkDL2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uoFRWR2DS9GvkDL2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uoFRWR2DS9GvkDL2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uoFRWR2DS9GvkDL2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uoFRWR2DS9GvkDL2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uoFRWR2DS9GvkDL2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uoFRWR2DS9GvkDL2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uoFRWR2DS9GvkDL2 .marker.cross{stroke:#333333;}#mermaid-svg-uoFRWR2DS9GvkDL2 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uoFRWR2DS9GvkDL2 p{margin:0;}#mermaid-svg-uoFRWR2DS9GvkDL2 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-uoFRWR2DS9GvkDL2 .cluster-label text{fill:#333;}#mermaid-svg-uoFRWR2DS9GvkDL2 .cluster-label span{color:#333;}#mermaid-svg-uoFRWR2DS9GvkDL2 .cluster-label span p{background-color:transparent;}#mermaid-svg-uoFRWR2DS9GvkDL2 .label text,#mermaid-svg-uoFRWR2DS9GvkDL2 span{fill:#333;color:#333;}#mermaid-svg-uoFRWR2DS9GvkDL2 .node rect,#mermaid-svg-uoFRWR2DS9GvkDL2 .node circle,#mermaid-svg-uoFRWR2DS9GvkDL2 .node ellipse,#mermaid-svg-uoFRWR2DS9GvkDL2 .node polygon,#mermaid-svg-uoFRWR2DS9GvkDL2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uoFRWR2DS9GvkDL2 .rough-node .label text,#mermaid-svg-uoFRWR2DS9GvkDL2 .node .label text,#mermaid-svg-uoFRWR2DS9GvkDL2 .image-shape .label,#mermaid-svg-uoFRWR2DS9GvkDL2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-uoFRWR2DS9GvkDL2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uoFRWR2DS9GvkDL2 .rough-node .label,#mermaid-svg-uoFRWR2DS9GvkDL2 .node .label,#mermaid-svg-uoFRWR2DS9GvkDL2 .image-shape .label,#mermaid-svg-uoFRWR2DS9GvkDL2 .icon-shape .label{text-align:center;}#mermaid-svg-uoFRWR2DS9GvkDL2 .node.clickable{cursor:pointer;}#mermaid-svg-uoFRWR2DS9GvkDL2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uoFRWR2DS9GvkDL2 .arrowheadPath{fill:#333333;}#mermaid-svg-uoFRWR2DS9GvkDL2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uoFRWR2DS9GvkDL2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uoFRWR2DS9GvkDL2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uoFRWR2DS9GvkDL2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uoFRWR2DS9GvkDL2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uoFRWR2DS9GvkDL2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uoFRWR2DS9GvkDL2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uoFRWR2DS9GvkDL2 .cluster text{fill:#333;}#mermaid-svg-uoFRWR2DS9GvkDL2 .cluster span{color:#333;}#mermaid-svg-uoFRWR2DS9GvkDL2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uoFRWR2DS9GvkDL2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uoFRWR2DS9GvkDL2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-uoFRWR2DS9GvkDL2 .icon-shape,#mermaid-svg-uoFRWR2DS9GvkDL2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uoFRWR2DS9GvkDL2 .icon-shape p,#mermaid-svg-uoFRWR2DS9GvkDL2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uoFRWR2DS9GvkDL2 .icon-shape .label rect,#mermaid-svg-uoFRWR2DS9GvkDL2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uoFRWR2DS9GvkDL2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uoFRWR2DS9GvkDL2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uoFRWR2DS9GvkDL2 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
新项目
已有项目
是
否
开发者输入自然语言需求
WorkBuddy 解析意图
调用 Spring Initializr创建项目骨架
扫描 pom.xml检查已有依赖
自动添加缺失依赖
读取项目现有代码理解上下文
生成 Controller/Service/Mapper/DTO 全套代码
写入对应包路径不覆盖已有文件
是否需要单元测试?
生成 JUnit5 + Mockito 测试
结束
关键差异:WorkBuddy 在生成代码前会先读取项目上下文——已有哪些类、用了什么注解风格、包路径怎么命名——生成的代码风格与项目已有代码一致,而非一股脑套模板。
三、实战一:JWT + BCrypt 用户登录接口
3.1 需求描述
用自然语言向 WorkBuddy 下达指令:
帮我创建一个用户登录接口,要求:
– Controller 放在 src/main/java/com/example/controller 下
– 使用 JWT 做身份鉴权,密码用 BCrypt 加密
– 登录成功后返回 Token,包含用户 ID 和角色
– 生成对应的 JUnit5 单元测试
– 如果有缺失的 Maven 依赖,自动补全
3.2 WorkBuddy 执行流程
Maven
IntelliJ/VSCode
WorkBuddy
开发者
Maven
IntelliJ/VSCode
WorkBuddy
开发者
#mermaid-svg-7Ccbjeh0wNAyQDBq{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7Ccbjeh0wNAyQDBq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7Ccbjeh0wNAyQDBq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7Ccbjeh0wNAyQDBq .error-icon{fill:#552222;}#mermaid-svg-7Ccbjeh0wNAyQDBq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7Ccbjeh0wNAyQDBq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7Ccbjeh0wNAyQDBq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7Ccbjeh0wNAyQDBq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7Ccbjeh0wNAyQDBq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7Ccbjeh0wNAyQDBq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7Ccbjeh0wNAyQDBq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7Ccbjeh0wNAyQDBq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7Ccbjeh0wNAyQDBq .marker.cross{stroke:#333333;}#mermaid-svg-7Ccbjeh0wNAyQDBq svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7Ccbjeh0wNAyQDBq p{margin:0;}#mermaid-svg-7Ccbjeh0wNAyQDBq .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-7Ccbjeh0wNAyQDBq text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-7Ccbjeh0wNAyQDBq .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-7Ccbjeh0wNAyQDBq .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-7Ccbjeh0wNAyQDBq .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-7Ccbjeh0wNAyQDBq .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-7Ccbjeh0wNAyQDBq #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-7Ccbjeh0wNAyQDBq .sequenceNumber{fill:white;}#mermaid-svg-7Ccbjeh0wNAyQDBq #sequencenumber{fill:#333;}#mermaid-svg-7Ccbjeh0wNAyQDBq #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-7Ccbjeh0wNAyQDBq .messageText{fill:#333;stroke:none;}#mermaid-svg-7Ccbjeh0wNAyQDBq .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-7Ccbjeh0wNAyQDBq .labelText,#mermaid-svg-7Ccbjeh0wNAyQDBq .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-7Ccbjeh0wNAyQDBq .loopText,#mermaid-svg-7Ccbjeh0wNAyQDBq .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-7Ccbjeh0wNAyQDBq .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-7Ccbjeh0wNAyQDBq .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-7Ccbjeh0wNAyQDBq .noteText,#mermaid-svg-7Ccbjeh0wNAyQDBq .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-7Ccbjeh0wNAyQDBq .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-7Ccbjeh0wNAyQDBq .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-7Ccbjeh0wNAyQDBq .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-7Ccbjeh0wNAyQDBq .actorPopupMenu{position:absolute;}#mermaid-svg-7Ccbjeh0wNAyQDBq .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-7Ccbjeh0wNAyQDBq .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-7Ccbjeh0wNAyQDBq .actor-man circle,#mermaid-svg-7Ccbjeh0wNAyQDBq line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-7Ccbjeh0wNAyQDBq :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
输入需求(自然语言)
1. 扫描项目 pom.xml
返回已有依赖列表
2. 判断缺少 jjwt-api
spring-security-crypto
3. 修改 pom.xml,添加缺失依赖
4. 执行 mvn dependency:resolve
依赖下载成功
5. 创建 UserController.java
含 @PostMapping("/login")
6. 创建 UserService.java
含 BCrypt 加密 + JWT 生成逻辑
7. 创建 JwtUtil.java
含 Token 生成/验证/解析方法
8. 创建 LoginControllerTest.java
含 MockMvc 测试用例
返回生成文件列表 + 代码概览
3.3 生成的代码
WorkBuddy 自动生成的 UserController.java:
// WorkBuddy 生成:用户登录接口 Controller
// 自动处理了参数校验、Token 返回格式、异常兜底
@RestController
@RequestMapping("/api/user")
@Slf4j
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("/login")
public ResponseEntity<ApiResult<LoginVO>> login(@Valid @RequestBody LoginDTO dto) {
try {
LoginVO result = userService.login(dto);
return ResponseEntity.ok(ApiResult.success(result));
} catch (BusinessException e) {
log.warn("用户登录失败: username={}, reason={}",
dto.getUsername(), e.getMessage());
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(ApiResult.fail(e.getMessage()));
} catch (Exception e) {
log.error("登录接口异常: username={}", dto.getUsername(), e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResult.fail("系统异常,请稍后重试"));
}
}
}
WorkBuddy 自动生成的 JwtUtil.java:
// WorkBuddy 生成:JWT 工具类
// 包含 Token 生成、验证、解析、刷新四个核心方法
@Component
@Slf4j
public class JwtUtil {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private long expiration;
/**
* 生成 JWT Token
* WorkBuddy 自动添加了 userId/roles 两个核心 Claims
*/
public String generateToken(Long userId, List<String> roles) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder()
.setSubject(String.valueOf(userId))
.claim("roles", roles)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)))
.compact();
}
/**
* 验证 Token 有效性
* WorkBuddy 自动添加了过期异常和签名异常的处理
*/
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)))
.build()
.parseClaimsJws(token);
return true;
} catch (ExpiredJwtException e) {
log.warn("Token 已过期");
return false;
} catch (JwtException e) {
log.warn("Token 无效: {}", e.getMessage());
return false;
}
}
}
⚠️ 注意: WorkBuddy 会自动在 application.yml 中追加 jwt.secret 和 jwt.expiration 配置项。如果已有同名配置,它会提示冲突而非直接覆盖。
四、实战二:RabbitMQ 消息消费端
4.1 需求指令
用 Spring Boot 写一个 RabbitMQ 消费端,要求:
– 监听队列 device.data.queue
– 自动解析 JSON 消息体为 DeviceDataDTO
– 入库到 device_data 表
– 包含异常重试逻辑(最多 3 次)
– 重试失败后写入死信队列
– 检查项目是否已有 spring-boot-starter-amqp,没有则添加
4.2 生成结果
WorkBuddy 生成的完整消费端代码:
// WorkBuddy 生成:RabbitMQ 消息消费端
// 自动处理了 JSON 解析、异常重试、死信队列、日志埋点
@Component
@Slf4j
public class DeviceDataConsumer {
private final DeviceDataMapper deviceDataMapper;
private final ObjectMapper objectMapper;
private static final int MAX_RETRY = 3;
public DeviceDataConsumer(DeviceDataMapper deviceDataMapper, ObjectMapper objectMapper) {
this.deviceDataMapper = deviceDataMapper;
this.objectMapper = objectMapper;
}
@RabbitListener(queues = "device.data.queue")
public void handleMessage(Message message, Channel channel) {
String messageId = message.getMessageProperties().getMessageId();
int retryCount = getRetryCount(message);
try {
// 解析 JSON 消息体
DeviceDataDTO dto = objectMapper.readValue(
new String(message.getBody(), StandardCharsets.UTF_8),
DeviceDataDTO.class);
// 数据校验
validateDeviceData(dto);
// 入库
DeviceData entity = convertToEntity(dto);
deviceDataMapper.insert(entity);
// 手动 ACK
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
log.info("设备数据消费成功: messageId={}, deviceId={}", messageId, dto.getDeviceId());
} catch (JsonProcessingException e) {
log.error("JSON 解析失败: messageId={}, body={}", messageId,
new String(message.getBody()), e);
// 解析失败不重试,直接拒绝
basicReject(channel, message, false);
} catch (Exception e) {
log.error("设备数据处理异常: messageId={}, retryCount={}",
messageId, retryCount, e);
if (retryCount < MAX_RETRY) {
// 未超过最大重试次数,重新入队
basicNack(channel, message, true);
} else {
// 超过最大重试次数,拒绝并进入死信队列
log.error("超过最大重试次数,消息进入死信队列: messageId={}", messageId);
basicReject(channel, message, false);
}
}
}
}
WorkBuddy 同步生成的 application.yml RabbitMQ 配置片段:
# WorkBuddy 自动追加的 RabbitMQ 配置
spring:
rabbitmq:
host: ${RABBITMQ_HOST:localhost}
port: ${RABBITMQ_PORT:5672}
username: ${RABBITMQ_USERNAME:guest}
password: ${RABBITMQ_PASSWORD:guest}
listener:
simple:
acknowledge-mode: manual # 手动确认模式
prefetch: 10 # 每次预取 10 条
retry:
enabled: false # 关闭 Spring Retry(用自定义重试)
WorkBuddy 的智能判断:它发现项目已有 spring-boot-starter-amqp 依赖(版本匹配),就没有修改 pom.xml;但发现 application.yml 中没有 RabbitMQ 配置,于是自动追加。这种"差分更新"避免了对已有配置的破坏。
五、实战三:MyBatis-Plus 数据库反向生成
5.1 一键生成四层代码
这是 SpringBoot 开发中最常见的体力活:拿到 DBA 给的表结构,手写 Entity → Mapper → Service → Controller 四层代码。WorkBuddy 通过直接连接数据库元信息,可以完成全流程自动化。
指令:
连接本地 MySQL 数据库 testdb,扫描 user_info 和 order_detail 两张表,
生成 MyBatis-Plus 全套代码:
– 包路径:com.example.business
– 启用逻辑删除、自动填充、乐观锁
– 为 user_info 生成分页查询和按状态筛选的接口
5.2 生成结果
#mermaid-svg-SmnrgrueemGJecCA{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SmnrgrueemGJecCA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SmnrgrueemGJecCA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SmnrgrueemGJecCA .error-icon{fill:#552222;}#mermaid-svg-SmnrgrueemGJecCA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SmnrgrueemGJecCA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SmnrgrueemGJecCA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SmnrgrueemGJecCA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SmnrgrueemGJecCA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SmnrgrueemGJecCA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SmnrgrueemGJecCA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SmnrgrueemGJecCA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SmnrgrueemGJecCA .marker.cross{stroke:#333333;}#mermaid-svg-SmnrgrueemGJecCA svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SmnrgrueemGJecCA p{margin:0;}#mermaid-svg-SmnrgrueemGJecCA .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-SmnrgrueemGJecCA .cluster-label text{fill:#333;}#mermaid-svg-SmnrgrueemGJecCA .cluster-label span{color:#333;}#mermaid-svg-SmnrgrueemGJecCA .cluster-label span p{background-color:transparent;}#mermaid-svg-SmnrgrueemGJecCA .label text,#mermaid-svg-SmnrgrueemGJecCA span{fill:#333;color:#333;}#mermaid-svg-SmnrgrueemGJecCA .node rect,#mermaid-svg-SmnrgrueemGJecCA .node circle,#mermaid-svg-SmnrgrueemGJecCA .node ellipse,#mermaid-svg-SmnrgrueemGJecCA .node polygon,#mermaid-svg-SmnrgrueemGJecCA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SmnrgrueemGJecCA .rough-node .label text,#mermaid-svg-SmnrgrueemGJecCA .node .label text,#mermaid-svg-SmnrgrueemGJecCA .image-shape .label,#mermaid-svg-SmnrgrueemGJecCA .icon-shape .label{text-anchor:middle;}#mermaid-svg-SmnrgrueemGJecCA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SmnrgrueemGJecCA .rough-node .label,#mermaid-svg-SmnrgrueemGJecCA .node .label,#mermaid-svg-SmnrgrueemGJecCA .image-shape .label,#mermaid-svg-SmnrgrueemGJecCA .icon-shape .label{text-align:center;}#mermaid-svg-SmnrgrueemGJecCA .node.clickable{cursor:pointer;}#mermaid-svg-SmnrgrueemGJecCA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SmnrgrueemGJecCA .arrowheadPath{fill:#333333;}#mermaid-svg-SmnrgrueemGJecCA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SmnrgrueemGJecCA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SmnrgrueemGJecCA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SmnrgrueemGJecCA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SmnrgrueemGJecCA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SmnrgrueemGJecCA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SmnrgrueemGJecCA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SmnrgrueemGJecCA .cluster text{fill:#333;}#mermaid-svg-SmnrgrueemGJecCA .cluster span{color:#333;}#mermaid-svg-SmnrgrueemGJecCA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SmnrgrueemGJecCA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SmnrgrueemGJecCA rect.text{fill:none;stroke-width:0;}#mermaid-svg-SmnrgrueemGJecCA .icon-shape,#mermaid-svg-SmnrgrueemGJecCA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SmnrgrueemGJecCA .icon-shape p,#mermaid-svg-SmnrgrueemGJecCA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SmnrgrueemGJecCA .icon-shape .label rect,#mermaid-svg-SmnrgrueemGJecCA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SmnrgrueemGJecCA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SmnrgrueemGJecCA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SmnrgrueemGJecCA :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
WorkBuddy 生成的代码层
MySQL testdb
user_info 表id, username, password,email, status, create_time
order_detail 表id, user_id, amount,order_status, create_time
UserInfo.java@TableName, @TableId@TableLogic, @Version
OrderDetail.java同 User 标准注解
UserInfoMapper.javaBaseMapper + 自定义分页
OrderDetailMapper.java
UserInfoService.java分页查询 + 状态筛选
OrderDetailService.java
UserInfoController.javaRESTful CRUD + 分页
OrderDetailController.java
生成的 UserInfo.java 核心代码:
// WorkBuddy 基于 user_info 表结构自动生成
// 自动映射了:主键策略、字段类型、逻辑删除、乐观锁、自动填充
@Data
@TableName("user_info")
public class UserInfo implements Serializable {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String username;
private String password;
private String email;
private Integer status; // 0-禁用 1-启用
@TableLogic
private Integer deleted; // 逻辑删除:0-未删 1-已删
@Version
private Integer version; // 乐观锁版本号
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
六、效率实测数据对比
在统一硬件环境(MacBook Pro M3 Pro / 36GB)下,分别用纯手工和 WorkBuddy 辅助完成三个开发任务:
| JWT + BCrypt 登录接口(含单元测试) | 65 分钟 | 6 分钟 | 91% |
| RabbitMQ 消费端(含异常重试+死信队列) | 55 分钟 | 4 分钟 | 93% |
| 2 张表 MyBatis-Plus 四层代码 | 90 分钟 | 5 分钟 | 94% |
| 项目初始化 + 环境搭建 | 30 分钟 | 2 分钟 | 93% |
| 合计 | 4 小时 | 17 分钟 | 93% |
数据说明:纯手工耗时包含"写代码 + 查文档 + 修复编译错误",WorkBuddy 耗时包含"描述需求 + 代码确认 + 集成调试"。
效率提升的本质原因
手工开发的耗时分布在三个区域:
WorkBuddy 消除了前 85%,让你把时间聚焦在最后 15% 的创造性工作上。
七、避坑指南
⚠️ 坑1:生成的代码与项目风格不一致
现象:WorkBuddy 生成的代码用了 Lombok @Data,但你的项目禁用了 Lombok。
原因:WorkBuddy 会读取 p⽬上下文,但如果项目配置不规范(如混用 Lombok 和手写 Getter),AI 可能选错风格。
解决:
- 在指令中明确编码风格:“不要使用 Lombok,手写 Getter/Setter”
- 保持项目代码风格一致性,让 AI 更容易判断
⚠️ 坑2:依赖冲突
现象:WorkBuddy 添加的 jjwt-api 0.12.x 与项目已有的 jjwt 0.9.x 冲突。
原因:AI 按"最新稳定版"添加依赖,未考虑项目中可能存在的旧版本。
解决:
- WorkBuddy 添加依赖后会执行 mvn dependency:tree,关注输出中的冲突提示
- 手动排查 VersionConflictException
⚠️ 坑3:生成的 SQL 未考虑执行计划
现象:MyBatis-Plus 生成的 CRUD 接口在测试环境很快,上生产后慢查询告警。
原因:AI 生成的 SQL 未考虑索引覆盖——它能写正确的 SQL,但不知道表中哪些字段有索引。
解决:
- 生成后检查 SQL 执行计划(EXPLAIN SELECT …)
- 在指令中补充索引信息:“user_info 表的 create_time 和 status 字段有联合索引”
⚠️ 坑4:测试用例只覆盖 Happy Path
现象:生成的单元测试只测了"登录成功"场景,没测"密码错误"“Token 过期”“并发登录”。
原因:AI 默认生成正面测试用例,边界条件需要明确指定。
解决:
- 指令中追加:“生成覆盖正常、异常、边界三种场景的单元测试”
- 手动补充并发场景的 Mock 逻辑
八、WorkBuddy vs 其他 AI 编程工具
| 交互方式 | 行内补全 / 对话 | IDE 内对话 | 桌面 Agent + 微信小程序 |
| 文件操作 | ❌ 不操作文件 | ❌ 不操作文件 | ✅ 读写本地文件 |
| 命令执行 | ❌ | ❌ (需手动) | ✅ 自动执行 Maven/Gradle |
| 依赖管理 | ❌ | ❌ | ✅ 自动添加 + 冲突检查 |
| SpringBoot 骨架 | ❌ | ❌ | ✅ 对接 Initializr |
| DB 反向生成 | ❌ | ❌ | ✅ 连接 MySQL 自动生成 |
| 单元测试生成 | ✅ (对话式) | ✅ (对话式) | ✅ 自动生成 + 执行验证 |
| 多 Agent 协同 | ❌ | ❌ | ✅ 定时任务 + 工作流 |
九、总结与适用边界
9.1 核心收获
9.2 适用边界
| CRUD 接口开发 | 核心算法设计 |
| 标准中间件集成(JWT/RabbitMQ/Redis) | 自定义协议实现 |
| 数据库表反向生成 | 存量项目大规模重构 |
| 单元测试批量生成 | 集成测试场景设计 |
| SpringBoot 新项目搭建 | SpringMVC / 非 Spring 项目 |
9.3 最佳实践建议
👍 如果本文对你有帮助,欢迎点赞、收藏、转发! 💬 你用 WorkBuddy 开发 SpringBoot 项目时有遇到什么坑?欢迎在评论区交流~ 🔔 关注我,获取更多 SpringBoot + AI 开发实战文章! ✍️ 行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激!
专栏导航:
- 📚 专栏首页: SpringBoot 企业级实战专栏
- 🌟 推荐阅读:
- SpringBoot 3 集成微信支付 V3:一套代码覆盖多支付场景
- Spring AI 1.0 + Milvus:企业知识库 RAG 系统搭建



