客户端拼 JSON 时把 amount 写了两遍,一个 19900 一个 0,Jackson 默认取最后一个,订单实付变成 0 元,库存照扣,财务第二天才发现。乍看像缓存或者权限的锅,追下去往往不是。
ObjectMapper m = new ObjectMapper(); m.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION); curl -i -X POST http://127.0.0.1:8080/api/orders -d @dup_amount.json
追下去是这么回事:JSON 规范没有禁止重复键,解析器按流式读取时后一个覆盖前一个,不会报错。DTO 里也没开严格重复键检测。金额这种字段被覆盖后,日志里只留下最终值,排查时看不到前一个。
「同名 key 覆盖」这类改动最怕改一半,回滚脚本先准备好,再动生产。接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。
偶发问题先统计频率,一小时几次和一天一次,查法完全不同。改完顺手把文档补一句,省得下次自己重新推一遍。
具体做法是,打开 Jackson 的 STRICT_DUPLICATE_DETECTION 让重复键直接报错;网关层对请求体做一次重复键检查 或限定 body 大小和结构;金额以服务端计算结果为准 不直接采信请求里的值;构造 duplicate key 的请求验证返回 400。
验收就看一点,重复键请求返回 400 解析异常里带出重复的字段名 amount。
