spring boot 中 token 实现幂等性的核心是“发一次、验一次、删一次”:客户端先调用接口获取唯一 uuid token 并存入 redis(key 为 idempotent:token:{uuid},设 5–10 分钟过期),再携 token(建议 header 传递)调用业务接口;服务端校验 token 存在后原子性删除,再执行业务逻辑,确保 token 仅使用一次。

Spring Boot 中用 Token 机制实现 REST 接口幂等性,核心是“发一次、验一次、删一次”——客户端先领 Token,再带着它调用业务接口,服务端校验通过后立即删除,确保该 Token 只能成功使用一次。
Token 生成与发放
提供一个独立的获取 Token 接口,每次调用都生成全新、全局唯一的字符串(推荐 UUID),并存入 Redis,设置合理过期时间(如 5–10 分钟):
- Key 建议格式:idempotent:token:{uuid},便于清理和监控
- Value 可设为任意占位值(如 "1"),重点在 key 的存在性
- 过期时间要覆盖业务最长处理耗时 + 客户端重试窗口,避免误判失效
业务接口的 Token 校验拦截
在真正执行业务逻辑前,检查请求中携带的 Token 是否仍存在于 Redis:
- 建议从 HTTP Header(如
Idempotent-Token)读取,比参数更规范、不易被 URL 缓存或日志泄露 - 用
redisTemplate.hasKey(key)判断是否存在;若不存在,直接返回失败(如 400 或自定义错误码) - 若存在,必须用
redisTemplate.delete(key)原子性删除 —— 这步不能省,否则并发请求可能同时通过校验 - 删除成功后再执行业务逻辑;若删除失败(极少见),也应拒绝处理,防止重复
配套保障要点
Token 机制看似简单,但几个细节决定成败:
- 客户端必须配合重试策略:获取 Token 后,应在有效期内完成业务请求;失败时不盲目重领新 Token,而应重试原 Token(除非明确服务端已处理并删除)
- 避免 Token 泄露或复用:不建议把 Token 拼在 URL 里;前端需保证提交按钮禁用、防连续点击;移动端注意本地缓存清理
- 异常场景兜底:如业务逻辑抛异常导致未执行完,Token 已被删,此时应记录日志并支持人工对账,而不是尝试“回滚 Token”(违背幂等设计初衷)
- 不依赖单点 Redis 故障:Redis 不可用时,可降级为日志告警+允许部分重复(需业务可容忍),或引入本地缓存(如 Caffeine)做短时兜底(仅限低并发单实例)
代码片段示意(关键逻辑)
Controller 中无需侵入业务代码,可封装成 AOP 切面或自定义注解(如 @Idempotent),但底层仍是:











