我承认这个标题有点挑衅,但我确实被一个问题困扰了很久:技术负责人的时间,到底有多少应该花在给人看代码上?与其开会扯皮,不如让 AI 先把一遍,自己专注看最关键的逻辑。为此我花了一周,用 OpenAI 的 Codex 命令行工具,分六轮扫完了 6 个形态完全不同的 Java 商城系统。目标很简单:它能不能替我完成“代码体检”的第一遍粗筛?能不能避免我熬夜看一晚上低质代码?
结果,比我预想的要微妙:Codex 确实扒出了一批真问题——SQL 注入、支付回调没验签、库存超卖、多商户数据越权,一个没落下;但同时也在若干场景给出“听起来很专业,实际站不住”的建议,甚至会在没看过完整业务上下文时强行输出结论。这篇文章想跟你分享的不是那种“AI 太强了”或“AI 没用”的一刀切结论,而是 6 个商城里每一站的真实记录:提示词怎么给、Codex 回复了什么、我人工复核后坐实了几个、判断错了几个。如果你正在犹豫要不要在团队评审流程里引入 AI 审计,这篇实测大概能帮你少走不少弯路。
1. 为什么要拿商城系统当试验田
1.1 商城项目在技术体检里属于“硬骨头”
先解释一下为什么选择 Java 商城,而不是随便拉个简单的 CRUD 项目。要验证一个工具能不能看代码,至少要给它一个足够复杂的样本。商城系统的核心链路天然就带着一堆问题:商品、库存、SKU 的组合与缓存设计,订单创建、状态机流转、库存回滚,支付回调、退款、账单对账,会员、权限、地址、发票,秒杀活动、优惠券,再加上搜索、排序、分页。这些模块拼在一起,足以模拟现实工作的复杂度。
一个典型商城项目动辄几十个实体类、上百个接口,恰恰是技术负责人做 Code Review 时最不愿意从头到尾过一遍的类型:逻辑重复、参数校验松散、异常吞掉、事务边界不清,全都能在里面找到典型样本。用 AI 去扫,正好能测试它“阅读不熟悉项目的速度”和“发现问题准确率”这两项硬指标。
另一个关键因素是生态跨度。Java 是老牌企业级语言,开源的商城项目多、质量层级差异很大,既有老掉牙的 SSM 架构,也有 2025 年新起的 Spring Cloud Alibaba 微服务。想测工具的上限和下限,这个样本面比单一技术栈要可靠得多。
1.2 这次选用的六套 Java 商城形态
列一下审计对象清单,这 6 套系统基本是不同时期、不同团队风格的“缩影”:
- 传统 SSM 单机商城:JSP + Spring MVC + MyBatis,经典老代码,特征是大 SQL 拼字符串、连接池复用率低、表结构反范式严重。
- Spring Boot + MyBatis 单体商城:典型电商 CRUD + 订单系统,用 Redis 做简单缓存,但支付回调部分几乎是“裸奔”的。
- 基于若依框架二次开发的商城:后台权限系统 + 商城功能的混搭,出问题的地方往往在权限与业务接口之间的灰色地带。
- Spring Cloud Alibaba 微服务商城:拆了订单、商品、支付三个服务,用 Nacos 做注册中心,典型的“为了微服务而微服务”的项目。
- 高并发秒杀商城:加了 Redis 预减库存和 MQ 异步下单,架构最带“现代感”,但细节上踩了缓存一致性和幂等的大坑。
- 多商户跨境商城:多租户 + 多语言 + 多币种,涉及商户间行级权限与数据隔离,对查询条件的约束要求极高。
这 6 套系统的选择本身就决定了测试结论的走向。先把话说在前头:Codex 在不同架构下的表现差异很大,但“代码层面的细节问题”确实查得准,“架构层面的合理性判断”常常跑偏。
2. Codex 上岗:环境准备、边界设定与提示词设计
2.1 Codex CLI 的基础安装与接入
先说环境。Codex CLI 是 OpenAI 推出的智能编码工具,通过命令行交互,可以直接在本地仓库目录里运行。我这次用的是标准发布方式,安装步骤并不复杂:
- 确认本机 Node.js 版本在 18 以上,过低会在运行时直接报错,建议用 nvm 管理 Node 版本。
- 用包管理器全局安装 Codex CLI,也可以使用官方提供的安装包。
- 登录 OpenAI 账号并拿到 API Key,在 Codex 的配置文件里填入鉴权信息。
- 进入交互模式后,输入
codex --help可以查看可用子命令。
这套动作我在三台机器上重复过,第一次最容易卡在“配置文件写错导致鉴权失败”上。给出一个实测经验:出错时先看日志提示的具体字段名,最常见的是OPENAI_API_KEY没读取到,直接检查环境变量和配置文件是否对齐就行,通常五分钟内能排查完,不用瞎猜别的原因。
初始化完成后,还有一件容易被忽略的事。Codex 在每轮对话开始前会把工作目录里的文件索引加载进上下文,所以对大型仓库最好做“范围裁剪”,别让它一次性把整个项目塞进去。否则回答质量会明显下滑,甚至会把另一个模块的代码误认为当前模块来给建议。
2.2 给 Codex 划“管什么”和“不管什么”
这一点是整个实验里最有价值的收获。Codex 就像一个经验丰富但完全不认识你业务的外聘顾问,你不把上下文讲清楚,它的回答会非常“正确”,但落不了地。
每次审计开始前,我会先在对话里立几条边界:
- “把每个模块当成独立项目看,不要跨模块臆测业务规则”
- “只标记有代码证据的问题,不要给泛泛的架构意见”
- “改进建议必须给出具体文件路径和行号范围”
- “发现不确定的地方,用 [待核实] 标注,不要硬编结论”
我专门对比过给边界和不给边界两种方式的差异。不给边界时,Codex 的输出基本都是“要注重代码规范、要优化性能”这类模板化废话,听着都对,实际没用;给了边界之后,它才真正收敛到逐行扫逻辑,开始讨论事务、锁、参数校验这些具体细节。原因也不难理解,不给边界时它默认你要的是综合报告,给了边界后才把它锁死成“代码审计”这一种任务模式。
2.3 技术负责人视角的审计清单
作为技术负责人,我关心的问题清单基本等价于平时 Code Review 会反复强调的那几类。把它们写进提示词,就构成了 Codex 的检查维度:
| 维度 | 具体关注点 | 典型代码特征 |
|---|---|---|
| 事务一致性 | 跨表更新是否包含在同一事务内 | 缺少 @Transactional 或在 catch 里吞异常 |
| 并发安全 | 库存扣减、订单号生成等关键路径 | check-then-act、先查后改没有锁 |
| 安全边界 | 支付回调、权限判断、SQL 拼接 | 回调不验签、接口不加权限注解 |
| 数据隔离 | 多商户/多租户场景的越权 | 查询条件里没有商户 id 过滤 |
| 可维护性 | 重复代码、硬编码、魔法值 | 大量魔法数字、重复的校验逻辑 |
这张清单给出去之后,Codex 的返回会明显比“帮我看看这里有没有 bug”聚焦得多。后面每一轮,我都直接复用同一张清单,观察它在不同架构里抓问题的侧重点。
3. 六场审计的实录与关键发现
3.1 第一站:传统 SSM 单体商城,开场就是一把“拼 SQL”
这一站用的是最老派的组合:JSP 页面、Spring、MyBatis,SQL 全手工写。Codex 加载完项目结构之后,第一个高置信度的报警落在商品搜索方法里:
String sql = "SELECT * FROM product WHERE name LIKE '%" + keyword + "%'"; return jdbcTemplate.query(sql, rowMapper);这段代码一句话评价:从头到尾都是洞。keyword 直接拼进 SQL,既没转义也没参数化,一旦用户输入进入,SQL 注入几乎是必然的。更值得说的是,Codex 给出的修复建议是把它改造成 MyBatis 的<bind>+ 参数占位符,而不是简单加个正则过滤器——这个判断是靠谱的,因为它顺着调用链看到了ProductService层也没做二次清洗。
另一个点也很有意思。它在 30 多个 Mapper 文件里扫出了统计口径不一致:订单状态字段有的用int、有的用String,导致状态判断时出现if(order.getStatus() == 2)这样连类型都对不上的写法。这种问题真要人眼逐个翻 SQL 文件,半小时起步,Codex 一轮就拉出来了。
3.2 第二站:Spring Boot + MyBatis 单体商城,活生生的“信任边界”教材
第二个项目要现代很多,Spring Boot 2.x + MyBatis-Plus,Redis 做了缓存,接口风格也基本 RESTful。Codex 在这里抓到的核心问题几乎全集中在支付回调附近。
回调接口大概长这样:
@PostMapping("/callback/pay") public String payCallback(HttpServletRequest request) { String orderId = request.getParameter("orderId"); String amount = request.getParameter("amount"); orderService.markPaid(orderId, new BigDecimal(amount)); return "success"; }Codex 在回复里直接点评:回调入口连基本验签都没有,拿着订单号和金额就直接改订单状态,等于在业务层敞开门做生意。攻击者只要构造一个 POST 请求,传任意金额和订单号,订单就会被标记成已支付。人工复核时我连测了三遍:模拟请求、改数据库后置、再测金额不一致比对,确认只要回调参数是“订单号 + 金额”,就能把状态改掉。没有签名校验,没有商户平台对账,资金风险跑不掉。
Codex 的修复建议也分了两层:对外回调接口先加验签拦截;已支付金额以支付平台回执为准,不信任前端传进来的任何数值。前者是常规操作,后者才是真正有价值的经验判断,和评审老师傅给的意见几乎一致。
3.3 第三站:基于若依框架二次开发的商城,权限链路过关不严
基于若依这类 Java 快速开发框架二次开发的商城,在真实项目里非常普遍。Codex 在这个项目上抓得最深的是权限配置链条。
若依的权限模型依赖@PreAuthorize("@ss.hasPermi('product:add')")这类注解。商城接入框架后,商品、订单、会员列表等核心接口确实加了注解,但 Codex 顺着 Controller 一路扫到 Service 层,发现两个问题:第一,部分只规划给管理员的操作接口用了@Anonymous放行注解,而注释里写的是“登录后可访问”,等于直接变成了完全公开;第二,在导出订单 Excel 的接口里,查询条件没有强制加上“当前商户”或“当前用户”的过滤,这意味着同租户下不同管理员能互相导出对方订单。
这个发现的含金量在于:Codex 不是只看单个注解有没有加,而是把注解和查询条件两件事关联起来,找出了“注解过了,但数据范围没收敛”的组合漏洞。这种跨两个层面的问题,靠人肉看容易漏,靠传统静态扫描工具又会因为缺少语义理解产生大量误报,它恰好卡在了正确的粒度上。
3.4 第四站:Spring Cloud 微服务商城,拆出来的分布式事务
第四个是 Spring Cloud Alibaba 套件构建的微服务商城,订单、商品、库存、支付四个服务独立部署。Codex 在这里的表现有高光也有翻车。
高光的部分是,它快速定位到了“下单”链路里跨服务调用带来的问题。下单接口先调库存服务扣减库存,再调订单服务创建订单,两个服务各自在自己的本地事务里。如果订单服务失败,库存已经扣了,这里没有补单或者回滚机制。Codex 给出的常规建议是引入分布式事务(比如 Seata),但紧接着又说了句让我眼前一亮的判断:“如果目前单量不大,最好别急着上 Seata,先看看能不能改成‘订单先落库、后台异步对账扣库存’的模式,重构成本更低。”这种结合复杂度的务实取舍,是我第一次在 AI 输出里看到。
翻车的地方也有。它一度把“消息表没建索引”当成核心风险,排到报告第二高优。人工核了一下,这张表一天只有几万条记录,加不加索引对查询影响并不大,真正的瓶颈在 N+1 查询。Codex 对“数据量感知”是缺失的,它没有访问权重和实际流量数据,只能按照普适经验判断。这种“正确但错位”的建议,恰恰说明了为什么 AI 还不能直接拍板。
3.5 第五站:秒杀会场的并发库存,锁与缓存的博弈
这是 6 个项目里并发结构最复杂的一个。秒杀场景用 Redis 预减库存、MQ 异步处理订单,但 Codex 一轮就抓到两个致命细节。
第一个是预减库存的前置判断。原始代码先查 Redis 的库存 key,判断是否大于 0,再执行 decrement。Codex 指出这相当于get和decr之间有一个时间窗口,并发下天然存在竞态条件,要么用 Lua 脚本原子操作,要么用DECR后检查返回值是否小于 0 再做业务语义判断。它的建议是脚本原子化,我复核后觉得这是最直接、最不容易出怪的改法。
第二个细节藏在 MQ 消费端:消费订单消息时本意是幂等,但代码只在库表加了一个业务字段做唯一索引,而且实现方式是“先查后插”,并发重复消息照样会撞库。Codex 给出的方案是从 Redis 里做消费幂等标记,再配合唯一索引双保险。这番话放在开发者日常里是非常成熟的提法,说明它确有相当程度的后端并发经验。
3.6 第六站:多商户跨境商城,行级权限与租户隔离
最后一个选的是多商户跨境商城,SKU 带多语言、多币种、仓库、运费模板,一眼看非常“国际化”。Codex 在这一站的报告,几乎全在讲数据隔离。
最典型的例子是订单列表查询接口。开发者在 Mapper 里写的是SELECT * FROM orders WHERE user_id = #{userId},却漏了“商户维度”的过滤。在多商户环境下,同一用户在不同商户分别下单,数据库里 user_id 是同一个,没有merchant_id条件,订单列表就会把别的商户数据也展示出来。Codex 给出的建议是所有订单查询 SQL 反过来先带merchant_id,再考虑user_id,相当于在最外层加固一道“数据围栏”。
多语言场景它也有发现:同一个 SKU 在多个语言环境里出现了language_id外键缺失,导致前台渲染时偶尔读到空的标题。这类问题根源在表设计阶段就埋下了,后端 CRUD 逻辑再成熟也没法兜底。Codex 能从一个 SQL 文件里推出字段关系,说明它对常见商城数据模型的学习积累确实够深。
4. Codex 哪些发现是“硬通货”,哪些是幻觉
4.1 经人工复核之后可以坐实的典型问题
把六轮输出里被人工验证为真问题的筛选出来,大致可以分成三类。
安全性问题 3 个:SQL 注入、支付回调未验签、权限放行配置错误。
一致性问题 4 个:事务边界缺漏、库存竞态、消息幂等缺失、跨服务无补偿。
数据隔离问题 2 个:多商户订单不带merchant_id、语言外键缺失导致展示错乱。
整体上,在“能不能查出问题”这件事上,Codex 是及格的。而且它不只是查代码,还能顺着调用链把关联问题串成一类,比如把一个接口的 SQL 注入背后关联到调用它的前端接口组,这种挖掘方式对技术负责人来说很省时间。
4.2 AI 的误报和“过度设计”式建议
有收获就一定有打脸。Codex 有三个比较典型的误报场景,我认为这套反思比成果更有参考价值。
第一个是“经验式误报”:它把老项目里手动关闭 Connection、且写在很深的嵌套 try-catch 里的模式判为“连接泄漏风险”。人工 review 后发现,这个项目使用连接池,底层会自动回收关闭资源,代码虽然丑,真正泄漏的概率并不高。这类问题它感知不到池化层之外的运维上下文。
第二个是“标准化误报”:一个项目大量使用 Lombok,Codex 指出“过度依赖注解降低了可读性”。建议本身没错,但实际团队已经统一用 Lombok,并且有代码规范文件约定,这个建议等于无效。AI 给的“最佳实践”需要人翻译成“当前团队的最佳实践”。
第三个是“无流量语境的误报”,就是 3.4 里那个加索引问题。它按照教科书把没有索引的大表排成高优,实际上那个表读写量很小,根本不构成风险。技术负责人最烦的就是这种“正确但不分优先级”的建议,如果全盘采纳,开发工时能被拖垮。
4.3 人工二次验证的正确打开方式
因此我强烈建议:别把 Codex 的输出直接贴到周报,或者直接指派给开发。我的做法是把 Codex 的输出按文件定位之后,先让对应模块的 Owner 自己打开代码复核一遍,整个过程只花 10 到 20 分钟。确认坐实后,再进入正常缺陷管理流程。
凡是跟金额、状态流转、权限相关的结论,必须人工做一次脆弱性验证。比如拿 Postman 模拟支付回调,用并发脚本压一把库存扣减。Codex 能快速给出“哪里可疑”,但它给不出“这个问题在现网到底能不能被打穿”的答案,这部分从来都得靠真实请求和流量来确认。
5. 它到底能替技术负责人做到哪一步
5.1 能替你干的活:第一遍全量扫描
如果说“Codex 是技术负责人的平替”,那是不现实的。但目标如果只是“把一万行代码的第一遍粗审交出去”,它是够格的。
具体来说,它能稳定做这几件事:
- 在陌生仓库里按模块生成“问题地图”,带文件路径和行号
- 按模板维度(事务、并发、安全、数据隔离)归类问题
- 给出具备工程常识的修复建议,多数能直接落地
- 对重复代码、命名不当、字段类型混乱这类“阅读体验”问题,它比人细致得多
这相当于把技术负责人最耗精力的“逐行点检”外包给 AI,自己只保留两个决策环节:哪些问题必须马上修,哪些可以进排期,哪些建议直接丢弃。决策权还在人手里,但机械劳动量骤降。
5.2 必须由人来拿主意的地方
接下来是全文我最想强调的部分。Codex 以下这些能力还远不够:
它不理解业务指标。“活动期间订单量波动”到底是不是问题,它没有上下文。它不能判断团队的技术债容忍度。一个老项目里大量字符串拼接 SQL,该不该花一周重构?问 Codex,它永远会说“必须重构”;问技术负责人,可能要结合发布计划和团队排期给出“先做防御式参数校验,重构放到 Q3”的答案。它更不会争取资源。发现问题不难,难的是把人力和排期争取过来。技术负责人的核心能力从来不只是“发现”,而是“排序”和“推动”,这两点没有任何代码可以替代。
5.3 落地到日常评审流程的推荐姿势
基于这 6 轮实测,我给团队的实际建议是:把 Codex 作为“PR 前置扫描员”接入流水线,不替代人工 Code Review。具体做法是,在 PR 合入前让 Codex 跑一次增量文件扫描,输出“高风险 / 中风险 / 低风险”三类标记,开发先消化标记再交给 Reviewer 抽查。这样人工 Reviewer 的注意力就能集中在业务正确性和架构演进路径上,被低级安全问题打断的概率会明显下降。
6. 几个我复现时最在意的实操细节
6.1 分片审计比一把梭更靠谱
第一轮我试图让 Codex 一次扫完整个项目,结果它在 20 分钟后就明显开始丢失上下文,后续回答质量直线下滑。第二轮开始改成按模块分片:先商品、再订单、再支付、再权限,每个模块单独开一轮对话,中间把上一轮的结论粘到下一轮当上下文锚点。实测下来,准确率提升非常明显。
原因在于 Codex 的上下文窗口是有限的,项目文件一多,它就只能“看最新的、忘最早的”。分片之后每个模块的体积变小,它的注意力更集中,结构化输出也稳定很多。
6.2 提示词里给足“角色”和“验收标准”
最好的提示词不是简单一句“帮我检查 bug”,而是要给它明确的任务边界和输出格式,我后面几轮固定用这个模板:
你是 Java 技术负责人,做一轮 Code Review。先通读文件,再逐项回答下面的清单 1-6。对每个问题输出:文件路径、行号、风险等级、一句话修复建议。找不到明确证据的问题,单独放到“存疑清单”。
复盘后发现,凡是给了“输出格式模板”的提示词,Codex 的结果结构化程度直接翻倍,人工复核的浪费也少了一大半。这听起来很简单,但真的有不少人只输入“看看代码”就期待它能指出所有问题,最后失望而归,问题根源往往在提示词太含糊,而不是工具本身。
6.3 别让 Codex 直接改代码
最后一点经验:审计归审计,自动修改归自动修改,两者别混用。让 Codex 输出问题和修复建议,非常安全;一旦授权它自动改代码,很容易把大量无关重构混进来,或者按“最佳实践”改出一套项目里从来没有过的规范体系。我的做法是,听它的改行建议,但具体代码变动必须由原生开发者执行和测试,避免 AI 改坏业务逻辑、把某个坑埋得更深。
如果用一句话总结这 6 轮实测的体会,我会说:Codex 是一个很能干的“第一遍粗审工具”,技术负责人交给它的扫描工作越多,自己就能省出越多时间做更高级的判断。至于标题那个问题——“它到底能替技术负责人做到哪一步”,我的答案是:它能替你完成“用眼睛看代码”的部分,但“决定改不改、怎么改、什么时候改”这部分,必须留在人手里。