欢迎光临
我们一直在努力

WorkBuddy 驱动 SpringBoot 应用开发实战:一句话生成 JWT 登录+RabbitMQ 消费+MyBatis-Plus 全套代码

💡 摘要: 传统 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 个接口计算:

指标纯手工模式WorkBuddy 辅助改善幅度
单接口平均耗时 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 辅助完成三个开发任务:

任务纯手工耗时WorkBuddy 耗时提升
JWT + BCrypt 登录接口(含单元测试) 65 分钟 6 分钟 91%
RabbitMQ 消费端(含异常重试+死信队列) 55 分钟 4 分钟 93%
2 张表 MyBatis-Plus 四层代码 90 分钟 5 分钟 94%
项目初始化 + 环境搭建 30 分钟 2 分钟 93%
合计 4 小时 17 分钟 93%

数据说明:纯手工耗时包含"写代码 + 查文档 + 修复编译错误",WorkBuddy 耗时包含"描述需求 + 代码确认 + 集成调试"。

效率提升的本质原因

手工开发的耗时分布在三个区域:

  • 机械编码(60%):写 Entity 字段映射、XML SQL 拼写、Controller 参数校验——纯体力活
  • 查文档(25%):JWT 依赖版本、RabbitMQ 配置参数、MyBatis-Plus 注解用法——来回切换窗口
  • 业务逻辑(15%):真正需要动脑设计的部分
  • 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 编程工具

    维度CopilotCursorWorkBuddy
    交互方式 行内补全 / 对话 IDE 内对话 桌面 Agent + 微信小程序
    文件操作 ❌ 不操作文件 ❌ 不操作文件 ✅ 读写本地文件
    命令执行 ❌ (需手动) ✅ 自动执行 Maven/Gradle
    依赖管理 ✅ 自动添加 + 冲突检查
    SpringBoot 骨架 ✅ 对接 Initializr
    DB 反向生成 ✅ 连接 MySQL 自动生成
    单元测试生成 ✅ (对话式) ✅ (对话式) ✅ 自动生成 + 执行验证
    多 Agent 协同 ✅ 定时任务 + 工作流

    九、总结与适用边界

    9.1 核心收获

  • WorkBuddy 不是 Copilot 的替代品,而是覆盖了"编码后"环节:它可以修改 pom.xml、执行 Maven 命令、连接数据库反向生成代码——这些是传统 AI 编程助手的盲区
  • SpringBoot 项目的 85% 机械编码可以交给 AI:Entity 映射、Controller 模板、XML 配置——这些重复代码由 WorkBuddy 生成,质量稳定且风格一致
  • 效率提升不是线性叠加,而是流程重构:不查文档了、不用手写 pom.xml 了、不用等人 review 格式问题了——这才是 93% 提升的真正来源
  • 9.2 适用边界

    适用场景不适用场景
    CRUD 接口开发 核心算法设计
    标准中间件集成(JWT/RabbitMQ/Redis) 自定义协议实现
    数据库表反向生成 存量项目大规模重构
    单元测试批量生成 集成测试场景设计
    SpringBoot 新项目搭建 SpringMVC / 非 Spring 项目

    9.3 最佳实践建议

  • 指令要具体:不只是"写一个登录接口",而是"写一个 JWT 登录接口,Controller 放在 xx 包,密码用 BCrypt,生成单元测试"
  • 先跑通再优化:WorkBuddy 生成代码后 mvn clean test 跑通全部测试,确认基础功能正确再手工优化业务逻辑
  • 用于 Review 而非替代 Review:AI 生成的代码仍然需要人工 Review——重点看安全逻辑(密码加密、SQL 注入防护)和业务边界条件
  • 👍 如果本文对你有帮助,欢迎点赞、收藏、转发! 💬 你用 WorkBuddy 开发 SpringBoot 项目时有遇到什么坑?欢迎在评论区交流~ 🔔 关注我,获取更多 SpringBoot + AI 开发实战文章! ✍️ 行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激!

    专栏导航:

    • 📚 专栏首页: SpringBoot 企业级实战专栏
    • 🌟 推荐阅读:
      • SpringBoot 3 集成微信支付 V3:一套代码覆盖多支付场景
      • Spring AI 1.0 + Milvus:企业知识库 RAG 系统搭建
    赞(0)
    未经允许不得转载:171主机测评 » WorkBuddy 驱动 SpringBoot 应用开发实战:一句话生成 JWT 登录+RabbitMQ 消费+MyBatis-Plus 全套代码
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址