上一节:第7节:顶层设计全流程
本节:第8节:工程初始化-后端骨架与公共基础设施
下一节:待更新
前面几节里,我们已经把 Hify 的产品边界、技术选型、模块划分和工程规范定下来了。到这一步,很多人会自然地觉得,接下来不就是"让 Claude Code 一把梭,把后端项目初始化出来"吗?
我确实试过这么做。
结果表面上看很热闹,Claude Code 一次生成了很多文件,pom.xml、公共类、配置类、模块目录,似乎一应俱全。但仔细一看,问题也会一起冒出来:父 pom 和子模块目录不一致、依赖关系写乱、版本声明重复、统一响应和异常处理风格不统一,甚至同一个项目里能出现两套不同的错误码写法。
这不是 Claude Code 不够强,而是一次性生成的东西太多,细节之间的依赖关系也太密。当生成范围失控时,AI 的输出虽然快,但 review 成本会急剧上升,你很容易漏掉真正关键的问题。
所以这一节真正要讲的,不只是"怎么初始化一个 Spring Boot 工程",更重要的是:
当任务体量变大时,怎么把它拆成 Claude Code 能稳定完成、你也能稳定验收的小任务。
为什么工程初始化不能一把梭
工程初始化看上去像模板活,但它其实同时满足两个高风险条件。
第一,生成量大。
一个后端工程骨架,往往会涉及父 pom、多个子模块 pom、公共基础设施、目录结构、配置类、启动类,少则十几个文件,多则几十个文件。只要一次输出超过你肉眼能轻松 review 的范围,就不适合让 AI 一次性全部生成。
第二,步骤之间强依赖。
比如业务模块的 pom 依赖公共模块,公共模块里的统一响应和异常处理又会被所有业务模块复用,配置类还会影响后续实体、Mapper、Service 的写法。前面一环如果错了,后面不是"局部返工",而是整串都要跟着改。
所以判断一个任务该不该拆,我通常看两个标准:
-
生成结果是否已经超出你一次能完整 review 的范围。
-
各步骤之间是否存在明显的前后依赖关系。
只要满足其中之一,就应该拆。工程初始化这件事,两条都满足。
Hify 后端初始化,我是怎么拆的
这一次我把 Hify 的后端初始化拆成四步:
-
Maven 多模块骨架
-
hify-common 公共基础设施
-
业务模块空壳
-
最后验收
这个顺序不是随便排的,而是严格按依赖关系来的。
先把父子模块关系和目录结构搭好,再把公共设施铺好,最后再给业务模块放标准 package。这样每一步都足够小,也足够清晰,Claude Code 更容易对,你也更容易查。
一句话概括就是:
先地基,后框架,最后验收。
这不只是工程初始化的做法,后面你做任何复杂模块,其实都可以用同样的思路。
第一步:先搭 Maven 多模块骨架
第一步的目标非常单纯:只创建父 pom、子模块 pom 和目录结构,不碰 Java 代码。
我当时给 Claude Code 的指令大概是这样:
在项目的根目录下创建 hify,然后按照 CLAUDE.md 中的项目结构和技术栈, 创建 Hify 的 Maven 多模块工程骨架。 父 pom 声明所有子模块,统一管理 Spring Boot、MyBatis-Plus、Redis 等版本号。 子模块之间的依赖关系按 CLAUDE.md 中定义的架构来。 只创建 pom 和目录结构,不需要写 Java 代码。
最后那句"只创建 pom 和目录结构,不需要写 Java 代码"非常关键。
如果你不把边界说死,Claude Code 很容易顺手把启动类、配置文件、示例类也一起生成出来。这样不仅会和后续步骤冲突,还会让当前任务的 review 范围瞬间失控。
这一阶段我重点检查三件事:
-
父 pom 里的 <modules> 列表,和实际目录结构是否一一对应。
-
子模块之间的依赖关系是否符合前面定下来的架构约束。
-
版本号是否只在父 pom 的 dependencyManagement 里统一管理。
只要这三件事没问题,第一步就算通过。
第二步:把 hify-common 当成重中之重
如果说第一步是在搭地基,那第二步就是在浇承重梁。
因为 hify-common 里的东西,不是某个模块自己用,而是后面所有业务模块都会依赖。这里一旦写歪,后面每一层都会被带偏。
所以这一部分我没有继续让 Claude Code 一口气生成,而是继续拆成更小的任务,一个一个做:
-
统一响应 Result 和 PageResult
-
错误码枚举 ErrorCode 和业务异常 BizException
-
全局异常处理器 GlobalExceptionHandler
-
MyBatis-Plus 配置
-
Redis 配置
注意这里的顺序也不是随便排的。
比如全局异常处理器,天然依赖 Result、ErrorCode 和 BizException;而 MyBatis-Plus 配置和 Redis 配置相对独立,可以后放。这样拆完之后,每个任务上下文都很小,Claude Code 的输出会明显更稳。
1. 先做统一响应
这一步我让它只做一件事:定义统一接口返回结构。
在 hify-common 中创建统一响应类。 按照 CLAUDE.md 接口规范: Result 包含 code、message、data 三个字段,提供 ok() 和 fail() 静态方法。 PageResult 继承 Result,额外包含 total、page、size。
这类任务的好处是范围极小,几乎不会发散。你检查的重点也很简单:
-
字段对不对
-
静态方法对不对
-
包路径对不对
2. 再做错误码和业务异常
接着补错误码体系和业务异常:
在 hify-common 中创建错误码枚举 ErrorCode 和业务异常类 BizException。 ErrorCode 包含 code 和 message,覆盖通用错误。 BizException 持有 ErrorCode,支持自定义 message 覆盖。
这一步的核心不是"类能不能编译",而是它是否真正符合前面定下来的规范:错误码要统一分段,异常语义要统一表达,不能每个模块自己发明一套返回格式。
3. 然后补全局异常处理器
这一块我当时特别留意,因为 AI 很容易在这里"功能上没错,规范上跑偏"。
在 hify-common 中创建全局异常处理器 GlobalExceptionHandler, 使用 @RestControllerAdvice。 捕获 BizException 返回对应错误码, 捕获 MethodArgumentNotValidException 返回参数校验错误, 兜底捕获 Exception 返回系统内部错误。 所有异常响应必须使用 Result.fail() 和 ErrorCode 枚举。
这里最值得注意的,不是它会不会写 @ExceptionHandler,而是它会不会偷偷在兜底逻辑里硬编码一套错误结构,比如直接写 code=500、message="系统繁忙"。
这种代码从功能上说当然也能跑,但它已经违反了前面定义好的项目规范。
这也是为什么我一直强调 SDD 的闭环不是"发现 bug 再修掉",而是:
一旦发现 AI 跑偏,要么修提示词,要么补项目规范,尽量堵住同类问题的复发。
4. MyBatis-Plus 配置
这一步继续单独下指令:
在 hify-common 中创建 MyBatis-Plus 配置类。 ``包含:分页插件、自动填充(createTime、updateTime)、逻辑删除配置。
这类配置类看似不复杂,但会长期影响实体字段命名、分页行为和删除语义,所以放在公共模块里尽早统一非常有必要。
5. Redis 配置
最后再补 Redis:
在 hify-common 中创建 Redis 配置类。 ``包含:RedisTemplate 序列化配置(key 用 String,value 用 JSON)、 ``基础的 RedisUtil 工具类(get/set/delete/expire)。
这一步的重点也不是"能不能用 Redis",而是先把项目级的序列化规则和基础访问方式定下来,避免后面每个模块自己配一套。
第三步:业务模块空壳,只做结构不做逻辑
等 Maven 骨架和 hify-common 都稳定之后,才轮到业务模块。
这一阶段的目标不是写业务,而是把每个模块的标准 package 结构先搭出来,让后续开发有统一落点。
我当时给 Claude Code 的指令大概是这样:
为 hify-provider、hify-agent、hify-chat、hify-mcp 等业务模块 创建标准的 package 结构。 按照 CLAUDE.md 代码组织规范, 每个模块包含 controller/service/service-impl/mapper/entity/dto/config 目录。 每个模块只创建 package 和一个空的占位类,不需要写业务代码。
这一步看起来很简单,但它的价值并不低。
因为你一旦把结构先统一下来,后面让 Claude Code 继续补 Controller、Service、Mapper 的时候,它就更容易沿着这条轨道稳定输出,而不是一会儿写成 modules/{module}/api/domain/infra/web,一会儿又写回传统三层结构,最后项目里出现两套组织方式。
这其实也是工程初始化里很常见的误区:很多人急着写第一批 CRUD,结果等写到第三个模块才发现目录结构已经开始漂了。到那时再回头统一,代价就比现在大得多。
大批量代码应该怎么 review
这一节里 Claude Code 生成的文件并不少。如果你真的想逐行看完每一行,很容易把自己拖进低效率。
更实用的做法,是按影响范围排优先级。
第一优先级:结构性问题
先看模块结构、父子 pom、依赖关系、目录命名。
因为这一层一旦错了,后面所有代码都是建在歪地基上。结构错了,是全盘问题。
第二优先级:公共模块核心代码
再看 Result、BizException、GlobalExceptionHandler、MyBatis-Plus 配置、Redis 配置。
因为这些类一旦出错,不是影响一个接口,而是影响所有模块。
第三优先级:配置项
再看 application.yml、序列化规则、逻辑删除设置、分页限制这类配置。
它们的影响范围也不小,但通常还没有结构和公共模块那么致命。
第四优先级:业务模块空壳
最后才看 controller/service/mapper/entity/dto/config 这些空 package 和占位类。
因为这里几乎没有业务逻辑,主要是确认路径一致、命名一致即可。
这套顺序背后的逻辑很简单:
影响范围越大的问题,越应该先查。
不要把最宝贵的 review 精力,浪费在最不容易出大错的地方。
每一步都验收,不要攒到最后
还有一点我特别想强调:工程初始化不要等"全部做完"才验收。
正确做法是,每一步做完,就做一次对应层级的验证。
比如:
-
Maven 骨架搭完,就先检查模块声明、依赖关系、版本管理。
-
hify-common 写完,就先检查公共类和配置是否符合规范。
-
业务模块空壳搭完,就先确认目录结构和包路径是否一致。
-
最后再做整体启动和联调验证。
这样做的价值在于,你始终知道:
到当前这一步为止,哪些东西已经是对的。
一旦后面出问题,排查范围也会小很多。
如果你什么都不验,就一路往前冲,到最后报错的时候,问题可能来自任何一个阶段,定位成本会陡增。
这一节真正想讲的方法论
如果只看表面,这一节做的事很像"让 AI 帮你搭了一个 Spring Boot 工程骨架"。
但我觉得更重要的,其实是下面三条方法论。
1. 大任务先拆,再交给 AI
拆分标准只有两个:
-
生成量是否已经超出你一次能稳定 review 的范围。
-
各步骤之间是否存在明显依赖关系。
只要满足其一,就拆。
2. review 按影响范围排优先级
先查结构,再查公共模块,再查配置,最后查空壳。
因为结构错了是全盘问题,公共模块错了是系统性问题,空壳错了通常只是局部问题。
3. 每一步都要局部验收
不要把所有风险压到最后一次启动。
你真正需要建立的,是一种稳定推进的节奏:
做一小步,验一小步;确认没问题,再进入下一步。
总结
这一节我们完成了两件事。
第一件,是让 Claude Code 帮我们把 Hify 后端工程的基础骨架搭了起来:Maven 多模块、公共基础设施、业务模块空壳,全部就位。
第二件,更重要,是把一套后面会反复复用的方法论跑通了:
-
任务太大就拆
-
拆分顺序按依赖关系来
-
review 顺序按影响范围来
-
每一步做完都要验收
你会发现,真正让 AI 产出稳定的,不是某一句特别神的提示词,而是你有没有把任务边界切清楚、把检查点设明白、把规范前置好。
到这里为止,我们其实还没有开始写真正的业务代码,但后端工程已经不再是"从零开始"的状态了。后面不管是实现 Provider 管理、Agent 配置,还是对话引擎和 RAG,都会比一开始轻松很多。
这也是我越来越喜欢 Claude Code 的地方。
它最有价值的,并不是替你一次写出多少代码,而是它能在你把任务切对、规则定好之后,持续稳定地沿着同一条轨道往前推进。