切换日光/暗黑模式
108. 覆盖默认接口与并发更新演示
学习目标
这一节补齐 Vibe 系统后端的最后一块关键能力:让模块后端代码可以覆盖默认 CRUD 接口,并用并发更新演示后端代码的真实能力。
学完后,你应该能理解:
- 自定义接口和默认接口有什么区别;
- 为什么业务经常需要覆盖默认更新或删除逻辑;
- 拦截器为什么不能解决所有业务规则;
- 覆盖默认接口需要怎样的约定;
- 技能文档为什么要同步更新;
- 悲观锁如何解决并发更新问题。
默认接口的限制
通用模块默认提供增删改查接口。
这对普通后台页面已经够用。
但真实业务经常会有额外规则。
例如餐厅补贴或请假审批这类数据,如果状态已经是“已通过”,就不应该继续编辑或删除。
默认接口只知道怎么更新、删除数据,并不知道这些业务限制。
所以系统需要一种方式,让模块可以覆盖默认行为。
自定义接口和覆盖接口
自定义接口是额外新增的接口。
例如你新增一个 /special-delete,它和默认删除接口互不影响。
覆盖接口则不同。
它的目标是改变默认接口本身的行为。
例如用户仍然点击表格里的删除按钮,前端仍然调用默认删除路径,但后端执行时先检查模块后端代码里有没有覆盖逻辑。
如果有,就执行覆盖逻辑。
如果没有,就走默认删除。
这让前端交互保持不变,业务规则由模块后端代码接管。
拦截器的局限
前面通用 CRUD 已经有前置拦截器和后置拦截器。
它们可以在默认行为前后加逻辑。
但有些场景只靠拦截器不够。
例如你想完全替换更新或删除逻辑,或者想让 AI 写一段完整业务接口,这时更适合让模块后端代码声明覆盖函数。
可以这样理解:
- 拦截器适合补充通用流程;
- 覆盖接口适合替换默认流程;
- 自定义接口适合新增额外能力。
覆盖接口的约定
课程里通过装饰器或类似约定来声明覆盖逻辑。
系统执行默认接口时,会先加载模块后端代码。
然后判断这段代码里是否声明了对应接口的覆盖函数。
例如:
- 覆盖列表查询;
- 覆盖单条查询;
- 覆盖新建;
- 覆盖更新;
- 覆盖删除。
如果找到了覆盖函数,就执行它。
如果没有找到,就继续执行原来的通用 CRUD。
这样模块既能保留默认能力,又能在需要时接入特殊业务。
更新技能文档
后端支持覆盖默认接口以后,技能文档也必须更新。
否则 AI 不知道系统已经有新能力。
课程里特别强调技能名称和内容要写清楚:
- 什么时候使用覆盖默认接口;
- 每种覆盖函数有哪些参数;
- 如何调用默认更新或默认删除;
- 如何返回错误码和错误信息;
- 哪些代码格式是系统能识别的。
这一步很容易被忽略。
但在 AI 系统里,代码能力变了,给 AI 的规则也必须同步变。
验证业务规则
示例里让 AI 生成覆盖逻辑:
已通过的数据不允许更新,也不允许删除。
保存模块后端代码后,再回到表格页面操作。
删除已通过数据时,系统会返回自定义错误信息。
删除未通过或其他状态的数据,则可以走正常流程。
更新已通过数据时,也会被拦住。
这说明默认接口已经被模块后端代码成功接管。
并发更新演示
课程最后用充值接口演示后端代码的能力。
同一条数据同时发起多个充值请求,例如分别加 1、2、3、4。
如果没有加锁,多个请求可能同时读到旧余额,再分别写回,最终结果就不一定等于加 10。
这就是并发更新问题。
带悲观锁的版本会在查询时锁住记录,让更新按顺序执行。
这样每次并发请求结束后,余额都会正确增加 10。
这个演示说明:模块后端代码不是玩具代码,它可以使用事务、锁和数据库会话,能力接近正常后端项目里的接口。
阶段重点
这一节让 Vibe 系统的后端能力完整起来。
前端可以生成页面和调用模块,后端可以新增自定义接口,也可以覆盖默认接口。
再加上技能发现和工具审批,AI 才能在受控范围内完成从建表、配置、页面到业务接口的完整开发流程。