在 Java 里,“API 接口防重”通常指防止同一请求被重复提交/重复执行(防重复调用、防并发重复、防幂等失效)。常见场景包括:
下面按常见方案 + Java 示例系统讲一下。
只能防“手抖”,不能防恶意或重试
token// 生成 token
@GetMapping("/token")
public String getToken(HttpSession session) {
String token = UUID.randomUUID().toString();
session.setAttribute("submitToken", token);
return token;
}
// 提交接口
@PostMapping("/submit")
public String submit(@RequestParam String token, HttpSession session) {
String sessionToken = (String) session.getAttribute("submitToken");
if (sessionToken == null || !sessionToken.equals(token)) {
return "重复提交";
}
session.removeAttribute("submitToken");
// 业务逻辑
return "成功";
}
✅ 适合:表单、页面提交
❌ 不适合:纯 API / 分布式
requestIdrequestId 做唯一判断@Autowired
private StringRedisTemplate redisTemplate;
public boolean isDuplicate(String requestId) {
Boolean success = redisTemplate.opsForValue()
.setIfAbsent("req:" + requestId, "1", Duration.ofMinutes(5));
return success == null || !success;
}
接口使用:
@PostMapping("/pay")
public String pay(@RequestHeader("Request-Id") String requestId) {
if (isDuplicate(requestId)) {
return "重复请求";
}
// 业务
return "成功";
}
✅ 适合:API、支付、写操作
✅ 分布式友好
ALTER TABLE order ADD UNIQUE (user_id, order_no);
Java:
try {
orderMapper.insert(order);
} catch (DuplicateKeyException e) {
return "重复下单";
}
✅ 最可靠
❌ 只能防“数据重复”
public boolean tryLock(String key) {
return redisTemplate.opsForValue()
.setIfAbsent(key, "1", Duration.ofSeconds(10));
}
使用:
String lockKey = "order:lock:" + userId;
if (!tryLock(lockKey)) {
return "操作频繁";
}
try {
// 业务
} finally {
redisTemplate.delete(lockKey);
}
✅ 高并发
✅ 分布式
| 场景 | 推荐方案 |
|---|---|
| 表单提交 | Token |
| API 接口 | RequestId + Redis |
| 支付/下单 | RequestId + 数据库唯一 |
| 高并发 | 分布式锁 |
| 最终保障 | 数据库约束 |
如果你愿意,可以告诉我:
我可以给你一套可直接用的完整防重方案。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。