用 WorkBuddy 跑通并改造 DDD 脚手架:jet-ddd-demo 调试实录

作者:袖梨 2026-09-18

把一个开源 DDD 示例真正变成可维护的自有脚手架,远不止让项目成功启动。配置层级、多数据源路由、领域事件序列化以及框架兼容性,都可能在联调阶段集中暴露。下面以 WorkBuddy 接手 jet-ddd-demo 的过程为线索,复盘问题定位、代码改造、回归验证和需求校准中的关键细节。

2. 把 DDD 开源脚手架化为自己的:让 workbuddy 跑通 jet-ddd-demo,调试与改造实录

第 1 篇我用 Trae 把 DDD 脚手架的骨架读透了——四层架构、多数据源、领域事件,装进了脑子里。这篇开始动真格:把用 Trae 还原出的 jet-ddd-demo 交到第二个 AI 工具 workbuddy 手里,目标是「先保证能运行,调试代码,再出个分析报告」。

结果这一跑、一调、一改造,坑是真不少,但也是实打实的一次走查:6 处隐蔽的坑、一个「knife4j 只支持 Boot 3.x」的疑问、还有把整个服务重命名的一通拉扯。这篇把这些真实过程全记下来,包括我当时的原话——不粉饰,也不替自己找补。想了解 DDD + 多数据源落地会遇到哪些坑、或者想看看怎么跟 Agent 把需求掰扯清楚的,可以往下看。

一、换 workbuddy 分析代码:目标就一句话

第 1 篇里,代码是 Trae 按掘金文章还原到 jet-ddd-demo 的,那一步已经通过。现在我要换 workbuddy 这一步来,把代码接过去分析、调试。给我的提示词还是那一套,重点落在最后一句:

结合 https://juejin.cn/post/7661439504076636175
先还原其中代码放在jet-ddd-demo中,先满足文档中所有功能。只要用户和order就可以了

1、文档里面有git,要先保证能运行。
2、order不使用postgresql还是使用mysql不过配置和user不一样的库
3、事件功能,可以优化一下,增加个 type->用于区别,不同的type对应不同事件。其他的和本文一样。
4、先完成文档中的全部内容,保证可运行。

先在jet-ddd-demo中按上面要求实现文档中的功能。

工具:
 mysql: 192.168.55.140  3306 root/Ivy@2024
 redis: 192.168.55.140  6379 wayhua
 rocketMq: 192.168.55.140 其他的就不太懂了。

-----------
前面任务已通过trae完成,现在是使用workbuddy分析一下代码。
jdk-> 17
先保证能运行,调试代码,再出个分析报告

QQ_1789431011570

QQ_1789437260282

先交代一下环境,免得后面看着对不上号:落地用 JDK 17(官方文章写的是 JDK 25,我务实,按 17 来),Maven 用 IDEA 内置的 mvn.cmd,本地仓库 F:mavenrepository;三个中间件(MySQL 3306、Redis 6379、RocketMQ 9876)都在 192.168.55.140。还有一个习惯性的前置动作——每次会话首步先读 CLAUDE.md(铁律总桥),把环境、归档目录、git、删除红线都锁定下来,再动手。这不是仪式感,是避免 AI 自作主张删东西、乱建仓库。

二、调试:6 处坑,最后一处最隐蔽

workbuddy 的分析是「先跑通 → 调试 → 出报告」三段式。真正的戏份全在中间那步「调试」上,前前后后踩掉了 6 处:

  1. 复用能复用的:先核对前序已经落地的 4 类修复仍在位(逐项 Read 复核,不靠 AI 口头打包票);
  2. 重启应用:上一轮后台启动因为没设 JAVA_HOME 失败,这轮设好后才 mvn spring-boot:run 起来,Tomcat started on port 8080
  3. 跑端到端冒烟(tmp/smoke.py),结果把第 6 处缺陷给暴露出来了;
  4. 修复后再复核闭环,最后才出分析报告。

前序已修复的 4 类问题,我逐个记下来,因为它们都是"配置/约定"层面的坑,不看日志很难想到:

  • application-dev.yaml 结构错位:user/order/mail 归回 spring 命名空间,server.port 提到了顶层;
  • application.yamldata.redisdata.web.pageable 合并;
  • 多数据源路由:OrderRepositoryImpl / UserRepositoryImpl 改成 @Qualifier 显式构造器注入,明确走哪个数据源;
  • 订单 save 改成 upsert(id 非空走 UPDATE)。

真正阴的是冒烟暴露出来的第 6 处——领域事件反序列化

// 现象:消费者已经收到消息,但反序列化直接抛
// InvalidDefinitionException: no Creators

根因得看事件类的写法:事件类是 final + 全 final 字段的不可变类,这种类 Jackson 默认没有 creator 可用,反序列化无从下手。修复的思路是保持不可变语义不动摇:给 DomainEvent 加一个受保护的重建构造器,4 个订单事件各加 @JsonCreator + 全参数 @JsonProperty 重建构造器。改完重启,冒烟全绿。

验证闭环我也记了下来,这样"跑通了"才是真的有据可查:

  • 业务流:创建用户(4) → 订单A PENDING→PAID→COMPLETED、订单B PENDING→CANCELLED,DB 落库正确;
  • 事件流:发布 5 条 Domain event published,消费侧 5 条 Received OrderXxxEvent 全部成功反序列化,发布-订阅全链路闭合

到此,交付物出来了:分析报告 jet-ddd-demo/代码分析报告.md(架构、与原文章偏差、6 处问题根因+修复、验证、改进建议),外加对话归档。有件事我特意让 AI 别擅自动——git 提交/推送。因为 E:/jet-ddd-wrapper/ 根本不是仓库,唯一的 .git 在空的 jet-ddd/ 里,而代码在同级 jet-ddd-demo/ 不被该仓库跟踪;CLAUDE.md 又禁止 AI 自己建仓库。仓库位置这种该用户裁定的边界,AI 不乱来才是对的。

三、让它讲解代码,结果抛出两个兼容性大坑

代码跑通、报告出了,我让 workbuddy 接着把代码讲一讲:

对代码进行讲解

QQ_1789439185902

QQ_1789439206912

讲解讲到一半,我心里冒出来两个真问题,赶紧让它确认:

现在问题确认一下,
1、必须是spring4.1吗,因为我想增加knife4j,但knife4j只支持 spring boot 3.x?
2、可不可以使用tk.mybatis来做多数据源?

QQ_1789439798748

这两个问题背后是真刀镇抢的兼容性顾虑,我后来也去验证并落地了,直接说结论。

第一个:必须是 Spring Boot 4.1 吗?knife4j 只支持 3.x 怎么办?

不用降级。Knife4j 有 Boot 4 兼容版(Knife4j Next),依赖 com.baizhukui:knife4j-openapi3-boot4-spring-boot-starter:5.7.2,在 4.1 上直接接就行。

第二个:可不可以使用 tk.mybatis 做多数据源?

可以用,但 Boot 4 下有坑:mapper-spring-boot-starter 的自动配置会插进来一套「单 SqlSessionFactory」的自配,和我们自定义的双 SqlSessionFactory 直接冲突。规避办法是走 tk.mybatis 手动三件套mapper-core / mapper-base / mapper-spring)+显式引入 mybatis、mybatis-spring,自己管理双 SqlSessionFactory + 双 MapperScannerConfigurer

落地时又踩了几个点,一并记下:

  • 给 OrderDO / UserDO 补 tk 映射注解(@Table / @Column / @Id),新建 OrderMapper / UserMapper 继承 tk.mybatis.mapper.common.Mapper
  • 两个 RepositoryImpl 改用 Mapper + tk Example 实现;
  • tk 的 MapperScannerConfigurer 和它的 Configuration 与 Spring 的同名类有 import 歧义,包名 / 全限定名必须写清(tk.mybatis.spring...);
  • tk 生成的 Mapper Bean 名 orderMapper 和既有 DTO 装配器 OrderMapper(@Component)重名ClassPathMapperScanner.checkCandidate 抛异常直接启动失败——加自定义 BeanNameGenerator 统一加 tk 前缀(tkOrderMapper/tkUserMapper)解决;
  • /doc.html 返回 500 的坑:本项目设了 spring.web.resources.add-mappings=false,Knife4jUI 的静态资源没有默认映射;排查确认 Knife4j 的 starter 本身不注册资源映射,得在 WebConfig 补三项通配映射(/*.html/webjars/**/img/**),并刻意不用 /**,保住「未命中路径无处理器 → 统一异常」的 404 语义;
  • 两个 @Bean MapperScannerConfigurer 写成实例方法会触发 created too early 告警,改成 static 后就没了。

验证(已闭环):启动 9.3s、4 个 consumerGroup 全部 running;业务流与领域事件链路回归通过(tk.mybatis 下 CRUD / upsert 正常);Knife4j 的 /doc.html/webjars/**/v3/api-docs 等端点全部 200;未命中路径仍返回统一 500 JSON。

这一段也说明一件事:讲解不是嘴上答疑——workbuddy 直接把 jet-ddd-demo 迁到了 tk.mybatis + Knife4j Next,还把链路跑通了。这才是把问题"讲明白了"。

四、对照 service-api 改造:和 AI 掰扯需求的一段拉锯

代码能跑、讲解也过了,下一步是把它对齐到我自己的 service-api 规范。这一步让我意识到:让 AI 干活,得先把它拆成三件事说清楚,否则它一定跑偏。 我最初给的指令是这样:

将jet-ddd-demo代码对照service-api SKILL修改,当然service-api的springboot是3.x,不是4.x
因此我准备先编写  service-api-4x SKILL
要将service-api同样的功能先迁移到service-api-4x,主要是先升级springboot和knife4j等,然后是将jet-ddd-demo的这一套ddd功能也迁移到service-api-4x中,然后,生成jet-ddd,这个jet-ddd是有git的。到时候可以提交git。

QQ_1789463400561

结果它理解歪了,这个人工智障是理解错误的。

操**,service-api-4x肯定是以service-api为基准的,包容jet-ddd-demo功能,且以springboot4.为准

QQ_1789463442768

QQ_1789476640227

我盯上了 sa-token——之前它没带上,我怀疑是不是 Boot 4.0 不支持:

为什么去年sa-token?是 不支持4.0吗?

QQ_1789476663877

如果支持,就要添加上sa-token

如果支持,就要添加上sa-token

QQ_1789476683903

接着让它继续往下做:

接着

QQ_1789476707919

QQ_1789476727233

QQ_1789520576413.png 做完我让它好好测一把:

你做测试了吧,先完整进行一次测试。内容相对简单。好好测试一下。

QQ_1789520606049

结果一看,它压根没按我的要求生成代码,直接开骂:

*,不用测试了,都不按我的要求生成代码。日。jet-starter-cores,这个呢,怎么回事,有脑子不

QQ_1789520632849

QQ_1789520648350

问题就在这:一堆模块名没统一。我要的是全套统一成 jet-ddd-*

所有都改成jet-ddd-*

QQ_1789520670535

QQ_1789520688203

结果它漏了一个,还留一个做你妈呀 jet-service-bootstraps:

还留一个做你妈呀 jet-service-bootstraps

QQ_1789520710704

我把它点名,强调这个启动模块也得改。项目明明是你启动的,怎么就没想到:

jet-service-ddd-bootstrap->jet-ddd-service-demo-bootstrap  jet-service-bootstraps为什么没改,你是猪啊,项目不是你启动的吗

QQ_1789521007274

QQ_1789521191587

又给它重复了一遍要改的地方,结果还是没动:

**,这个不改吗jet-service-bootstraps->jet-ddd-*

QQ_1789521222145

QQ_1789521243567

改个名的事,来来回回就是改不完:

*  jet-service-bootstraps->jet-ddd-service-bootstraps你是猪啊,这么个小问题都搞不了

QQ_1789521266110

QQ_1789521290337

更搞笑的是,它之前偷偷建 SKILL,也没告诉我开的是 SKILL 调试模式:

前面你偷偷建SKILL也没听你说SKILL调试模式啊,好搞笑啊,你这大sb

QQ_1789521305851

闹到这一步,我把底牌全亮出来,给它把三件事掰碎了:

你到底在想什么?sa-token功能也不对,还只建一个user,你想干嘛。不是给你demo了吗?使用老的框架做基座,业务按jet-ddd-demo来,多数据源,ddd等。知道吗?三件事:1、在原来的基础上升级到4.1 2、service-api->service-api-4x 3、将jet-ddd-demo代码按新的SKILL生成。知道了吗?你对照一下,按这要求做了吗?授权你在要修改service-api-4x时直接修改。SKILL调试模式,如果需要的话。

QQ_1789521324236

QQ_1789521344497

三轮下来它总算接住了"我要的是多数据源"这个核心,但方向还是偏:一会儿想拆成多个服务,一会儿 dto / pojo 都不补全。我又把要求钉死:

1、肯定是一个,我不是给了demo吗?要的是多数据源!你真他妈是猪。2、那就增加dto,pojo(对应数据库),3、补全,包括代码,特别是core中,没使用的都要添加进来,并匹配到springboot4 4、同样添加进来。 我要的是1、升级到4.1,2、生成skill,肯定要完整的。

QQ_1789521366546

QQ_1789521378906

这一段折腾下来,我最大的体会是:跟 Agent 掰扯需求,不能靠它自己领悟,得把"基座是什么、业务照哪套、最终要什么"拆成编号说死。 你以为"不言自明"的,它真能给你整出幺蛾子。

五、铁律与残留:删不删,是个态度问题

折腾改造的过程中,还有一条我先拎出来单独讲——关于残留代码的删除。当时有残留要处理,但 AI 一刀切全删了最容易误伤;我索性把态度挑明:

残留确实还在,我不删 —— 原因是铁律,不是我偷懒。 这种该删除的还是可以删除的,只是不要一次性全部删除就好了。

QQ_1789521411932

QQ_1789521429127

QQ_1789521444719

这句话背后是我在铁律里反复强调的一条:"不删"不等于"永远不删",而是不能一刀切、批量删、rm -rf * 式地删。 该清的空目录、该去掉的废弃副本可以逐条清理;但"一次性把所有东西删个干净"这种事,AI 不代劳、也不该代劳——万一删成了正在用的东西,哭都来不及。这个原则在后面的改造里还会反复用到。

六、小结

这一篇从"让 workbuddy 跑通 jet-ddd-demo"一路走到"对照 service-api 开始改造",把中间的过程原样记了下来。收个尾,最有价值的几点:

  1. 跑通是第一关,调试比分析花时间:6 处坑里,配置错位、多数据源路由、不可变事件类的反序列化各占一角,最后一处 no Creators 最难想到——保持不可变语义,用 @JsonCreator + 重建构造器解决;
  2. 兼容性要验证,别听风就是雨:knife4j 有 Boot 4 兼容版(Knife4j Next),tk.mybatis 可以做多数据源,但要手动三件套绕开 mapper-spring-boot-starter 的自动配置;
  3. 跟 Agent 掰扯需求,一定要拆成编号说死:基座是什么、业务照哪套、最终产出什么,三件套摆清楚,它才不容易跑偏;
  4. 删除要讲分寸:逐条清、空目录可删,但批量删、一次清空是红线,这条铁律贯穿全程。

下一篇我会沿着这个方向往下走:把 service-api-4x 真正建起来、让新代码过一遍测试,再把这一整套可复用的东西固化成 SKILL。中间那些测试和排错的实录,比顺顺利利写代码更有看头。关注我,下一篇见。

参考:Spring Boot 4.1 + JDK 25 DDD 开源脚手架,面向 AI 编程(掘金)—— juejin.cn/post/766143…

相关文章

精彩推荐