news 2026/6/20 14:22:05

Java 8老系统AI Code Review实战:规则扫描+AI分析双层防线,Git合并前先过审

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 8老系统AI Code Review实战:规则扫描+AI分析双层防线,Git合并前先过审

为什么要写这个系列

做Java后端十年,我接触过不少企业的核心系统。

金融、电商、政务——行业不同,但底层的现状惊人地相似:生产系统还在Java 8,框架停在Spring Boot 2.x甚至更早,代码跑了很多年,没人敢轻易动。

去年开始,几乎每个项目都在谈接AI。

但真正动手的时候,团队就卡住了。

不是因为不懂大模型,而是老系统本身接不住。JDK版本不够,Spring AI引不进来;依赖树牵一发动全身,升级一个包怕带崩一片;生产流量压着,不敢拿主流程赌一个AI试点。

更危险的是硬塞。我见过团队在老系统的Service层直接new一个HttpClient调模型API,Prompt拼在业务代码里,超时没配、降级没有。模型响应慢的时候,老系统的订单查询线程池被占满,主流程跟着卡住。还有团队把用户手机号、身份证原样送进Prompt,过了两个月才被安全审计发现。

这种事见多了,我就开始想一个问题:老系统不具备直接接入AI的条件,这是不是大多数企业的常态?

答案是肯定的。而且这不应该成为接不了AI的理由。

核心思路其实就三条:

老系统少改 —— 不升级 JDK,不引入 Spring AI 依赖 AI 能力旁路 —— 独立部署,老系统通过 HTTP 或 MQ 调用 企业边界先行 —— 脱敏、审计、降级、幂等比模型调用更重要

这个系列就是把这三条线展开成10讲。

从AI Gateway到MCP工具中心,从SQL Agent到RAG知识库,从工单Agent到多Agent研发团队——每一讲都围绕同一个前提:

你的老系统还在跑Java 8,你不能为了AI去赌它的稳定性。

每讲配套一个可运行的Maven Lab,不讲空架构,不写Hello World。你跑得通Demo,看得到边界,拿得到代码。

这就是我做这个系列的原因。


Java 8老系统AI Code Review实战:规则扫描+AI分析双层防线

第4讲我们建立了一张结构化的代码地图:

扫描源码 → 识别分层 → 生成调用链 → 输出阅读路线

有了这张地图,团队至少知道一个业务动作经过了哪些地方。

但代码每天都在变。

新人会提交代码,老项目会修Bug,业务会加需求,AI也会生成一堆看着像那么回事的实现。

这时候,第4讲的代码阅读地图帮不上了——因为它分析的是项目现状,不是代码变更。

你需要的是在代码合并之前,有人先帮你扫一眼:

这次改动有没有低级风险? 有没有可能影响老系统稳定性? 有没有漏掉该加的校验?

这就是本讲要解决的问题。

但在开始之前,先说清楚一件事:

AI Code Review 不是替团队做决策,更不是让 AI 自动改代码。

它适合做的是第一道过滤器:把那些容易漏、容易犯、容易在加班时被忽略的低级问题,在合并前提出来。

最终效果

代码目录:

code/spring-ai-enterprise-lab/labs/chapter05-ai-code-review

运行:

.\compile-and-run.ps1

跑完后能看到:

  • 解析sample.diff
  • 识别空指针风险、参数校验缺失、库存校验TODO
  • 输出结构化Markdown Review
  • 预留AI分析接口,当前由Stub透传

输入

Git Diff(本讲用样例 sample.diff 模拟)

输出

结构化 Markdown Review: - 风险等级 - 文件 - 行号 - 风险类型 - 原因 - 建议

企业边界

- 只输出建议,不自动提交代码 - 高风险问题标记需人工确认 - 规则扫描和 AI 分析双层检查 - 输出结构化,方便接入 GitHub / Gitee 评论

为什么不能只靠模型做Review

在讨论怎么实现之前,先想清楚一个问题:为什么Code Review不能直接把Diff丢给模型?

不是因为模型不够好,而是因为Review里有两类完全不同的任务。

第一类:模式匹配型

空指针风险 → 新增代码里有没有 request.getXxx() 没判空? SQL 注入风险 → 有没有字符串拼接 SQL? 敏感字段 → 有没有打印手机号、身份证? 事务边界 → 有没有写库操作没包事务?

这些问题有规律,不需要"理解业务"。它们需要一个确定性的规则引擎,而不是一个概率模型。

第二类:语义理解型

这段代码的设计意图是什么? 这个 catch 掉异常会不会掩盖上游问题? 这个 clientVersion 兼容分支是不是该删了?

这类问题需要上下文、需要解释、需要基于项目事实给出自然建议。这才是模型擅长的事。

所以本讲的核心观点是:

AI Code Review 应该是规则扫描和 AI 分析的双层防线。确定性规则兜底安全问题,AI 负责理解意图和补充上下文。

这一讲先跑通第一层——规则扫描管道。第二层AI分析留好接口,后续接入Spring AI时替换Stub即可。

样例Diff

本讲使用一个经过设计的Diff:

@@ -1,6 +1,10 @@ public String createOrder(OrderRequest request) { + String userId = request.getUserId(); + String productId = request.getProductId(); if (request.getQuantity() <= 0) { throw new IllegalArgumentException("quantity must be positive"); } + // TODO check product stock later return orderService.createOrder(userId, productId, request.getQuantity()); }

这段代码看起来没什么问题,但至少有三个风险点:

第一个问题:直接调用request.getUserId()request.getProductId()但没有判断request是否为空。如果上游传了一个null,这里直接NPE。

第二个问题:创建订单前留下了库存校验TODO。// TODO check product stock later说明团队知道这里要加校验,但还没加。

第三个问题:新增的两个userIdproductId参数没有做非空和格式校验。如果它们是必填字段,说明校验逻辑还在别的地方——或者还没写。

这三个问题,都是规则扫描能识别、也应该识别的。它们不依赖模型,也不依赖对业务的深度理解。

架构设计

本讲链路:

Git Webhook / Push ↓ GitDiffParser ↓ ┌──────────────────────────┐ │ 第一层:规则扫描 │ │ 空指针 / SQL 注入 / 事务 │ │ 敏感字段 / 参数校验 / 异常 │ └──────────────────────────┘ ↓ ┌──────────────────────────┐ │ 第二层:AI 分析(预留) │ │ 语义理解 / 上下文补充 │ │ 自然建议 / 风险解释 │ └──────────────────────────┘ ↓ ReviewCommentFormatter ↓ Markdown Review

和第1-3讲一样,AI不直接接入老系统流程。老系统的代码变更通过Git Webhook进来,进入独立的Review管道,规则引擎先做确定性扫描,AI再做语义分析,最终输出结构化评论。

这一讲当前只实现了第一层和第二层的接口。Stub模式让管道先跑通,后续替换Stub为真实模型调用时不需要改管道代码。

代码结构

src/main/java/com/ynzz/lab/chapter05 ├── Chapter05Demo.java ├── diff │ ├── GitDiffParser.java │ ├── DiffModel.java │ └── ChangedLine.java ├── review │ ├── RuleBasedRiskScanner.java │ ├── AiReviewService.java ← 接口 │ ├── StubAiReviewService.java ← Stub 实现 │ ├── CodeReviewService.java │ ├── ReviewFinding.java │ ├── ReviewResult.java │ └── ReviewCommentFormatter.java └── webhook ← 本讲新增 ├── GitWebhookRequest.java └── GitWebhookController.java

子模块(后续扩展):

git-webhook-adapter/ ← Webhook 签名校验、平台适配 diff-analysis-service/ ← 规则引擎 + AI Review 服务化 review-comment-publisher/ ← 评论发布到 GitHub / Gitee

第一层:规则扫描

本讲Demo实现了三个规则。

规则一:空指针风险

扫描逻辑:

如果新增代码调用了 request.getXxx() 并且没有出现 request == null 或 request != null → 标记空指针风险

规则二:库存校验缺失

扫描逻辑:

如果新增代码中出现 TODO 且包含 stock 关键词 → 标记库存校验缺失

这个规则很朴素,但它表达了一个重要原则:Review不仅要关注代码写了什么,还要关注代码应该写但没写什么。

规则三:必填参数无校验

扫描逻辑:

如果新增代码提取了 userId、productId 等业务参数 但没有出现对应的 null 判断或 StringUtils.isEmpty → 标记参数校验缺失

完整的规则维度:

维度检测内容风险等级
空指针风险request.getXxx() 无判空MEDIUM
参数校验缺失业务参数无 null/empty 检查MEDIUM
SQL 注入风险字符串拼接 SQL 语句HIGH
事务边界写库操作无 @TransactionalHIGH
敏感字段暴露日志打印手机号/身份证HIGH
异常吞没catch 块只有 log 无 rethrowLOW

当前Demo实现了前三个。后续规则可以通过扩展RuleBasedRiskScanner#scan逐个加入,不影响现有逻辑。

第二层:AI分析(预留)

AiReviewService接口定义:

publicinterfaceAiReviewService{/** * 基于规则扫描结果,生成 AI 补充分析。 * 当前 Stub 实现透传原有 finding,不修改。 */List<ReviewFinding>enrich(List<ReviewFinding>findings,DiffModeldiff);}

这个设计有几个好处:

1. 管道代码(CodeReviewService)不感知是 Stub 还是真实模型 2. 规则扫描的结果是 AI 分析的输入,两层不互相替代 3. 后续接入 Spring AI 只需替换一个实现类 4. 即使 AI 不可用,规则扫描仍然独立工作

这和第4讲"事实层vs表达层"的分工一致:规则负责确定性的事实检测,AI负责非确定性的语义表达。

运行效果

运行Demo后输出:

### AI Review 风险等级:MEDIUM #### 1. 可能的空指针风险 - 文件:`OrderController.java` - 位置:第 2 行 - 原因:新增代码直接读取 request 字段,但没有判断 request 是否为空。 - 建议:在进入业务逻辑前增加请求对象校验。 #### 2. 参数校验缺失 - 文件:`OrderController.java` - 位置:第 3 行 - 原因:新增代码提取了 userId、productId 业务参数,但没有做非空或格式校验。 - 建议:在 Service 入口或 Controller 层增加必填参数校验。 #### 3. 库存校验缺失 - 文件:`OrderController.java` - 位置:第 7 行 - 原因:新增代码留下库存校验 TODO,创建订单前可能没有真实校验库存。 - 建议:在 Service 层增加库存检查,Controller 不承载业务规则。

企业避坑

第一,AI Review不要自动改代码。

本讲只输出Markdown评论,不生成Patch,不自动提交。AI在Review流程里的角色是"建议者",不是"执行者"。

第二,高风险问题必须进入人工确认。

涉及支付、退款、库存、权限的改动,不能让AI自动判断通过。规则扫描标记HIGH等级后,必须有人在合并前确认。

第三,规则扫描不能丢。

空指针、SQL注入、敏感字段、事务边界这些问题,应该有确定性规则兜底。不能因为有了AI就把规则引擎撤掉。两者是互补关系,不是替代关系。

第四,Review结果必须结构化。

至少要包含:文件、行号、风险等级、风险类型、原因、建议。结构化输出方便接入GitHub/Gitee评论API,也方便后续统计分析。

第五,不要只扫描新增行。

真实Review需要关注上下文行和删除行的语义。比如删掉了一个null判断,只靠"+"行看不出来。

第六,Review要和CI流水线集成。

单独跑一个Review脚本价值有限。更好的嵌入点是:PR创建 → Webhook触发 → Review管道 → 评论回写PR。

从Demo到落地,还差什么

Webhook真实接入GitHub/Gitee:当前Demo用本地sample.diff模拟输入,真实项目需要GitWebhookController接收平台Webhook,校验签名,拉取Diff,再触发Review管道。

规则配置化:当前规则硬编码在RuleBasedRiskScanner里。企业场景需要把规则抽成配置文件(YAML或JSON),让不同项目、不同团队自定义规则集合和风险等级。

AI分析接入Spring AI:当前StubAiReviewService只做透传。接入真实模型后,AI需要基于Diff上下文解释风险原因、补充业务场景——但这些都是在规则扫描已有结果的前提下做增强。

上下文行分析:当前只扫描新增行。真实diff的上下文行和删除行也需要纳入分析,否则会漏掉"删掉了一个null判断"这类问题。

Review结果回写Git平台:当前只输出到控制台。落地时需要把结构化Review结果以行级评论的形式发布到PR对应位置。

高危变更自动升级:涉及支付、退款、权限模块的变更,应该自动将Review等级提升为HIGH并通知指定Reviewer。

小结

规则扫描负责确定性检测 AI 分析负责语义理解 两层互补,不互相替代

从第4讲的"读懂老项目"到第5讲的"审查代码变更",这个系列正在从"理解系统"走向"保护系统"。

下一步,第6讲会把企业文档接入RAG知识库——让AI不只是理解代码,还能回答业务问题。

AI Code Review 的目标不是替代 Reviewer,而是让 Reviewer 把精力从找低级错误中解放出来,去关注更重要的设计决策。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/20 14:01:47

70B大模型多卡推理实战:张量并行TP=4配置与NCCL通信避坑指南

1. 项目概述&#xff1a;为什么70B模型单卡装不下&#xff0c;又为什么非得上多卡&#xff1f;“70B模型单卡装不下”——这句话在2024年的大模型工程圈里&#xff0c;已经不是问题&#xff0c;而是共识。它背后藏着三重硬约束&#xff1a;显存墙、计算带宽墙和通信延迟墙。我去…

作者头像 李华
网站建设 2026/6/20 13:58:57

网盘下载效率革命:智能直链解析工具重塑文件获取体验

网盘下载效率革命&#xff1a;智能直链解析工具重塑文件获取体验 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云…

作者头像 李华
网站建设 2026/6/20 13:58:47

C++迭代器与范围编程

C迭代器与范围编程迭代器是STL中连接容器和算法的桥梁。C20引入的范围库提供了更简洁的遍历方式&#xff0c;结合视图可以高效处理数据序列。迭代器类别决定其能力&#xff1a;输入、输出、前向、双向和随机访问。#include #include #include #include #include #includevoid i…

作者头像 李华