跳过正文
Spring 工程上的 AI 编码代理:实时链路、可验证闭环与上下文治理
  1. 文章/

Spring 工程上的 AI 编码代理:实时链路、可验证闭环与上下文治理

·6462 字·13 分钟
NeatGuyCoding
作者
NeatGuyCoding
目录

Spring 工程上的 AI 编码代理:实时链路、可验证闭环与上下文治理
#

摘要:面向已在 JVM/Web 栈上交付服务的工程师,本文从一类典型 Spring Boot + Kotlin 实时互动应用出发,梳理「数据库信号 → 响应式 SSE → 浏览器」的数据路径,并把人机协作拆成可核对的三层:编译与测试闭合可版本化的项目记忆(CLAUDE.md / 规则 / Skills)工具调用路径上的 Hooks 与 MCP。后半部分讨论无规格迭代导致的测试与状态机缺口、结构化澄清(Interview)如何把导航与安全决策写进规格,以及长对话中跨切面步骤被静默丢弃的现象与分段执行思路。文中涉及的具体演示项目名为公开幻灯材料中出现的示例工程;其与第三方仓库的逐行对应关系不在此文证实范围内。


1. 案例语境:投影仪实时互动与常用栈组合
#

(1) 原理与动机
此类场景通常包含大屏展示、移动端参与与限时交互:管理员发起一轮活动,参与者扫码加入,在计时器驱动下消耗「反应预算」 viewing 投影内容,最后在若干类别下揭晓排名。实现上常见诉求是 低延迟信号分发(多客户端订阅同一事件源)与 服务器渲染或渐进增强(例如 HTMX)以降低前端复杂度。

(2) 实现抓手
公开材料中反复出现的工程锚点包括:Spring BootKotlinjOOQHTMX。Kotlin 入口习惯使用 runApplication<Application>(*args);jOOQ 在 Boot 下通过自动配置的 DSLContext 与数据源方言属性衔接 SQL 生成层(参见 Spring Boot 参考手册 — Using jOOQ);浏览器侧若采用 HTMX 的 SSE 扩展,可通过 EventSource 语义连接推送端(参见 htmx SSE 扩展说明)。

(3) 怎么用

@SpringBootApplication
class DemoApplication

fun main(args: Array<String>) {
    runApplication<DemoApplication>(*args)
}

Kotlin 与 Spring Boot 的配套约束(插件、runApplication 等)以官方章节为准(Spring Boot — Kotlin 支持)。

图注:幻灯片标题区可见英文描述「A photo reaction game on a beamer. The manager starts a round, quests join via QR code.」,并配有德语界面字样(如 Ergebnisse),用于说明演示产品的交互形态而非某一固定开源仓库版本。


2. 约定、编译反馈与测试:代理协作的「闭合回路」
#

(1) 原理与动机
分层清晰(Controller / Service / Repository)与广泛采用的注解模型,使自动化助手更容易在陌生仓库中定位扩展点;更重要的是,一次 Gradle 编译或测试运行即可暴露类型与集成错误,从而把「猜测」变成可机器核验的信号,这与下文 Headless CLI、Hooks 与 CI 叙事相容。

(2) 实现抓手
Kotlin Gradle 插件暴露标准任务名 compileKotlin / compileTestKotlin(参见 Kotlin Gradle 编译选项)。Web 层可组合 @SpringBootTestSpring Boot 测试)、MockMvcMockMvc 概述)与 TestcontainersSpring Boot 与 Testcontainers;项目主页见 Testcontainers for Java)。

(3) 怎么用

./gradlew compileKotlin compileTestKotlin test

3. PostgreSQL NOTIFY、WebFlux 与浏览器 SSE
#

(1) 原理与动机
数据库 NOTIFY 将在给定 channel 上向已执行 LISTEN 的会话投递载荷,适合作为轻量级内部事件总线(PostgreSQL NOTIFY)。Spring WebFlux 可将 Flux<ServerSentEvent> 暴露为 text/event-stream,由浏览器 EventSource 消费(ServerSentEvent JavaDocMediaType.TEXT_EVENT_STREAM 常量MDN — EventSource)。幻灯材料中的个案把监听线程、Reactor Sink、轮询间隔等画在一起;这些接线细节属于演示架构示意,并非 Postgres 或 Spring 的唯一规范写法。

(2) 实现抓手
要点链条(与幻灯英文一致):pg_notify → 通知服务 → Reactor Sink → Flux<ServerSentEvent> → HTTP SSE;浏览器侧标注 EventSource / HTMX。实现者可替换 JDBC 轮询策略或使用 R2DBC 等,但 produces = TEXT_EVENT_STREAM_VALUE 与响应式返回类型仍是 WebFlux SSE 的核心 API 面。

(3) 怎么用

@GetMapping(path = ["/api/sse/slideshow"], produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
fun slideshow(): Flux<ServerSentEvent<String>> = slideshowEvents()
const es = new EventSource("/api/sse/slideshow");
es.onmessage = (ev) => console.log(ev.data);

Mermaid diagram 1

图注:终端摘要写明 The project uses PostgreSQL LISTEN/NOTIFY as the event transport, with Spring WebFlux Flux streams delivering events to browsers.,并列出步骤「Guest uploads photo > pg_notify > SlideshowNotificationService > Reactor Sink > SSE stream」。

图注:同一概述页可见「Guest uploads photo » pg_notify » SlideshowNotificationService » Reactor Sink > SSE stream」与架构行「Spring Controller (Flux)」。


4. 子代理、摘要回流与 Headless 快照检索
#

(1) 原理与动机
重型代码探索会消耗大量 token;把研读任务放到 独立子代理上下文,仅让结构化摘要回到主会话,可降低主窗口的早期信息被挤出的风险。文档侧对子代理、模型路由与钩子交互有专章说明(自定义子代理)。与此同时,打印模式(-p--model 等 CLI 标志适合脚本化「只读问答」(Claude Code CLI 参考)。

(2) 实现抓手
概念分工:主会话保留决策与编辑;子任务负责广读文件与检索;下游消费仅为摘要或结构化列表。与数据库相关的「服务端」此处指 schema 契约:通过迁移或 information_schema 列出表、列与唯一约束,便于低成本对齐领域模型。

(3) 怎么用

claude -p --model haiku "列出 ranking game 相关迁移中的表、唯一约束与状态枚举列"

5. 数据库建模示例:排行会话、参与者与反应
#

(1) 原理与动机
实时多人玩法需要在会话维度维护状态机(如 LOBBY / ACTIVE / FINISHED / REVEAL)、参与者集合以及每人对每条内容的反应;唯一约束用来禁止重复加入或重复投票,是把业务规则下沉到存储层的直接手段。

(2) 实现抓手
幻灯列举表 ranking_game_sessionranking_game_participantranking_game_reaction,并写出 Unique constraint: one participant per guest per sessionone reaction per participant per photo per session 一类语义(英文原文以屏幕为准)。具体列名与 CHECK 约束应以实际迁移为准。

(3) 怎么用

CREATE UNIQUE INDEX ux_participant_per_guest
  ON ranking_game_participant (session_id, event_guest_id);

CREATE UNIQUE INDEX ux_one_reaction_per_submission
  ON ranking_game_reaction (participant_id, submission_id);

图注:幻灯片以大写标题陈述「The ranking game feature uses three main database tables:」,并列出「ranking_game_session」「ranking_game_participant」「ranking_game_reaction」及「Unique constraint: one participant per guest per session」等英文要点。


6. 「氛围编码」基线:缺失测试与终端状态被静默跳过
#

(1) 原理与动机
在缺少规格与分层记忆结构时,仅凭自然语言 prompt 快速堆代码,容易出现 未写自动化测试手工才能发现的缺陷,以及 状态机分支不完整——例如枚举中存在 REVEAL 阶段却无任何迁移路径到达该状态。此类问题根因常被归结为 需求在长上下文中漂移,而非单一语法错误。

(2) 实现抓手
对照可靠栈:JUnit / Spring Boot Test 用于回归;状态迁移可用单元测试表驱动穷举 when(event);关键终端状态应在测试中显式断言可达。

(3) 怎么用

enum class Phase { LOBBY, ACTIVE, FINISHED, REVEAL }

fun next(p: Phase, timerEnded: Boolean): Phase = when (p) {
    Phase.ACTIVE -> if (timerEnded) Phase.FINISHED else p
    Phase.FINISHED -> Phase.REVEAL
    else -> p
}

图注:幻灯片标题为「THE VIBE CODING BASELINE」,正文包含「Iteration 1: no config, no skills, no plan」「No tests written.」「The whole REVEAL state skipped.」等英文句子。


7. 会话内 checkpoint 与 /rewind:试错而不丢对话语义
#

(1) 原理与动机
代理按检查点记录文件编辑;当一次重构偏离预期时,使用者可以中断并在 Rewind / checkpoint 语义下回滚工作区改动,同时 保留对话历史,以便修正指令后继续。官方文档将主题概括为跟踪、回滚与汇总编辑(Checkpointing)。

(2) 实现抓手
产品侧提供会话状态管理与检查点选择交互;工程侧被修改的焦点文件在演示材料中为 RankingGameService.kt。Escape 连按等具体操作应以当前客户端文档为准。

(3) 怎么用
人机流程可描述为:中断当前工具执行 → 调用 rewind → 选中目标检查点 → 确认恢复 → 用更精确的增量指令继续编辑同一服务类。

图注:界面列出多次「Update (../rankinggame/RankingGameService.kt) Added 19 lines」类 diff 摘要,并出现提示「Interrupted - What should Claude do instead?」。


8. CLAUDE.md、路径规则与 Skills 的分工
#

(1) 原理与动机
CLAUDE.md 在每次会话开始加载,适合放置「永远成立」的编译与验收纪律;更细的规则可放入 .claude/rules,仅在读取匹配路径下的文件时注入上下文,从而节省 token(项目记忆与 CLAUDE.md;路径限定规则见 path-specific rules——front matter 使用 paths 列表承载 glob,而非单独的 globs 键名)。Skills 的正文则在 被调用时才加载,用于在动作发生时刷新流程说明(Skills)。

(2) 实现抓手
Hooks 文档中的 InstructionsLoaded 事件标明:CLAUDE.md.claude/rules/*.md 进入上下文时会触发(Hooks 参考)。 /context 命令用于查看上下文构成的实时拆分(Context window)。

(3) 怎么用

# CLAUDE.md(示意)
- Compile after .kt changes: `./gradlew compileKotlin compileTestKotlin`
- Verify before done: run tests or demonstrate correctness
---
paths:
  - "**/src/test/**"
---
Prefer Spring Boot Test + Testcontainers for integration scenarios...

图注:幻灯片段标题为「INSIDE MY CLAUDE.MD」,可见条目「Compile after .kt changes:」「./gradlew compileKotlin compileTestKotlin」以及「Verify before done: never mark a task complete without proving it works」。


9. Interview 工作流:先 Explore,再用结构化提问固化规格
#

(1) 原理与动机
在编码前把 入口路径、边界状态、安全假设 写成可评审文档,能显著降低后续返工。演示材料展示了一条轨迹:先自动执行「Explore codebase architecture」,再通过多选问答澄清 管理员从何处进入 Ranking Game 等产品决策;Skill 文本要求 规格必须以 User Stories 结尾且导航类故事靠前。工具名 AskUserQuestion 出现在 Hooks 与子代理文档中(Hooks — AskUserQuestionCreate custom subagents)。「Interview Skill」固定模板与行数是否为厂商内置产品,公开文档未以同名条目证实;读者应把它理解为 可复制的 Markdown 技能脚手架

(2) 实现抓手
Mandatory topics 覆盖:Entry pointsUser journeyEdge casesState transitionsTerminal states & dead ends 等;输出约束:Write the spec to a fileSpec MUST end with User Stories

(3) 怎么用
澄清所得最终会映射到路由与页面结构,例如为 /admin 或活动详情页增加独立分区。

@Controller
class RankingGameAdminController {
    @GetMapping("/admin/events/{id}/ranking-game")
    fun rankingGamePage(@PathVariable id: UUID): String = "admin/ranking-game"
}

图注:界面可见句子「Let me explore the codebase first to understand the existing architecture before interviewing you.」以及「Explore(Explore codebase architecture) Done (53 tool uses」开头的一行状态摘要。

图注:问答面板标题包含「Where does the manager find the Ranking Game?..」,选项行可见「Manager dashboard (/admin)」「Add a ‘Start Ranking Game’ button」等英文短语。

图注:文档草稿中出现「Interview me relentlessly ## Mandatory interview topics about every aspect…」与「Use AskUserQuestion tool to」「Write the spec to a file.」等连续英文原文。


10. 反应预算与防篡改:HTTP 演示下的服务端强制
#

(1) 原理与动机
若预算仅存于浏览器 Cookie 或前端状态,客户端可篡改计数;服务端必须以可认证的访客主体(如 event_guest)与数据库累计值为权威。幻灯中的选项枚举了 Server-side budget enforcement、纯客户端与 cookie 混合等路径(英文标签以屏幕为准)。

(2) 实现抓手
Spring MVC 常用 @PostMapping@PathVariable@RequestBodyResponseEntity(参见 Spring MVC 注解驱动控制器)。演示约定自定义头名 X-Demo-Guest 仅用于下文草图,真实系统应使用会话或 JWT 等成熟机制。

(3) 怎么用

POST /api/events/550e8400-e29b-41d4-a716-446655440000/reactions HTTP/1.1
Content-Type: application/json
X-Demo-Guest: guest-token-demo

{"submissionId": 99, "type": "HEART"}
@RestController
@RequestMapping("/api/events/{eventId}/reactions")
class ReactionController(
    private val reactions: ReactionService,
) {
    @PostMapping
    fun react(
        @PathVariable eventId: UUID,
        @RequestBody body: ReactionBody,
        @RequestHeader("X-Demo-Guest") guestToken: String,
    ): ResponseEntity<Void> {
        reactions.react(eventId, guestToken, body.submissionId, body.type)
        return ResponseEntity.accepted().build()
    }
}

data class ReactionBody(val submissionId: Long, val type: String)

图注:选项列表可见「Security: should we prevent reaction manipulation?..」「1. Server-side budget enforcement」「DB tracks reactions per guest…」等英文描述。

图注:同一「Storage model」对话分支可见「Clarifying: reactions stored in the DB, but budget tracked client-side via a cookie?..」以及编号行「1. DB reactions, cookie budget」「Each reaction is a DB row. Budget is client-side.」等英文句子。


11. 领域校验:沿用既有异常层次与双语消息
#

(1) 原理与动机
新增业务校验(如计时器时长合法区间)时,复制仓库内既有 PhotoQuestException 子类风格,可避免一人一类错误模型;幻灯片段展示 InvalidTimerDurationException 同时携带德语用户文案与英语系统文案。OCR 将「30」误识为「3@」;正确区间应以项目源码或产品需求为准,此处按常规理解为 1–30 分钟。

(2) 实现抓手
Kotlin 可用 require 抛出非法参数(require 标准库);与 Spring 的 HTTP 映射结合时,异常宜通过 @ControllerAdvice 映射为 400/422(参见 Spring MVC 异常处理)。

(3) 怎么用

class InvalidTimerDurationException : PhotoQuestException(
    userDe = "Die Timer-Dauer muss zwischen 1 und 30 Minuten liegen.",
    systemEn = "Timer duration must be between 1 and 30 minutes",
)

fun createSession(timerMinutes: Long) {
    if (timerMinutes !in 1..30) throw InvalidTimerDurationException()
}

图注:diff 摘要包含「class InvalidTimerDurationException : PhotoQuestException(」以及「Timer duration must be between 1 and 3@ minutes」一行英文(字符「@」为 OCR 噪声,应以源码为准)。


12. Hooks、静态分析与 Jackson 3 迁移叙事
#

(1) 原理与动机
规则文档可能被模型忽略;HooksPreToolUse / PostToolUse / SessionEnd 等事件上插入脚本,用于阻断危险命令或在写盘后运行 formatter / linter(Hooks reference)。演示提及用 Detekt 在自定义规则中拦截 Jackson 2 的 ObjectMapper 引用,引导至 Jackson 3 的 JsonMapper;Spring Boot 4 迁移指南写明 com.fasterxml.jacksontools.jackson 的包迁移方向(Spring Boot 4.0 Migration Guide — Jackson)。Detekt 规则 DSL 细节未在此文附官方页核实。

(2) 实现抓手
Hook 配置以产品 JSON schema 为准;匹配器可过滤 BashEdit|Write 等工具名。

(3) 怎么用

{
  "hooks": {
    "PreToolUse": [{ "matcher": "Bash", "command": "./hooks/git-guard.sh" }],
    "PostToolUse": [{ "matcher": "Edit|Write", "command": "./hooks/detekt-on-write.sh" }]
  }
}

13. MCP:把 IDE 能力暴露为代理可调用的接口
#

(1) 原理与动机
Model Context Protocol 将外部系统(IDE、缺陷跟踪、可观测性后端)以标准工具面暴露给客户端;没有 MCP 时,代理往往依赖 shell 与原始文件 IO。Spring AI 提供多种 MCP Server Boot StartersSpring AI — MCP 概述)。协议规范文档托管于 modelcontextprotocol.io,仓库自述见 modelcontextprotocol/modelcontextprotocol README

(2) 实现抓手
幻灯对比「Without MCP / With IntelliJ MCP」列出 reformat_fileexecute_run_configuration、自动 import 等能力,并写到「The IDE becomes an API that the agent calls.」;JetBrains MCP Steroid 项目在 README 中声明暴露更广的 IntelliJ Platform API(MCP Steroid README)。各工具的确切标识符以实现仓库为准。

(3) 怎么用
CLI 侧通过 claude mcp 配置服务端(参见 CLI reference);IDE 侧安装对应 MCP 插件并授予代理最小权限集。

图注:表格对比「Without MCP」「With IntelliJ MCP」,并包含句子「The IDE becomes an API that the agent calls.」以及「github.com/JetBrains/mcp-steroid」。


14. 长计划漂移与分段 Headless 执行(Ralph 思路)
#

(1) 原理与动机
单一超长会话里,模型可能 有计划但未逐步执行:幻灯将 /frontend-designagent-browser/simplify 等步骤标记为「Phase 早期使用后丢弃」或「Never used」,标题写作「Plans work — until the context window doesn’t.」,结论句为「The agent isn’t a deterministic machine」。这与「把每个阶段放到独立 claude -p 会话、由 shell 循环顺序消耗计划文件」的思路相容;「Ralph」一词是否为社区昵称需对照各自工具文档,厂商页面未强制使用该名称。

(2) 实现抓手
分段执行依赖:机器可读的计划工件阶段边界冷启动会话;Skills 文档列出捆绑命令 /simplifySkills),其实际是否在某一 runs 中被调用属于过程观测。

(3) 怎么用

while read -r phase; do
  claude -p -- "$(cat docs/plan.md)" --phase "$phase"
done < docs/phases.txt

上述 --phase 参数名为示意;真实标志以 CLI reference 为准。

Mermaid diagram 2

图注:幻灯主标题为「LEVEL 4: THE DRIFT PROBLEM」,副标题「Plans work — until the context window doesn’t.」,底部总结句「The agent isn’t a deterministic machine」,并标注「Dropped after Phase 1」「Never used」等英文状态。


参考与延伸阅读
#

相关文章

Spring Boot 4 技术栈纵览:Starter 粒度、MVC 版本协商与安全演进

·4493 字·9 分钟
Spring Boot 4 与 Spring Framework 7 组合下,依赖可按能力拆成更细的 Starter,Web 出站客户端可与服务端 MVC 依赖分离;同一代码库可在 Spring MVC 中启用内置 API 版本解析,并与 Spring Data JDBC、RestClient / 声明式 @HttpExchange 客户端协同。Spring Security 7 侧重可叠加的 Customizer<HttpSecurity>、一次性令牌登录、WebAuthn 与注解式多因子模型;

用 Kotlin 表达力加固 Spring Boot 测试:断言、夹具与响应式边界

·4328 字·9 分钟
Spring Boot 与 Kotlin 在 JVM 上互操作成熟,团队常先在 src/test 引入 Kotlin,把扩展函数、默认参数、类型安全 DSL 与 Kotest 等断言风格用在集成测试与 MockMvc 场景中,以降低样板代码并收紧失败信息。与此同时,Java Builder、静态工具重载与 Project Reactor 的 StepVerifier 仍有各自的认知成本;文中按依赖层次归纳常见动机、可对齐的公开 API,以及需注意的语义边界(例如 JVM 泛型擦除、响应式校验是否真正订阅完成)。