温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java API接口怎么防重

发布时间:2026-10-02 11:55:06 来源:亿速云 阅读:95 作者:小樊 栏目:编程语言

在 Java 里,“API 接口防重”通常指防止同一请求被重复提交/重复执行(防重复调用、防并发重复、防幂等失效)。常见场景包括:

  • 表单重复提交
  • 网络重试导致重复请求
  • 并发请求同时进来
  • 分布式系统下的重复消费

下面按常见方案 + Java 示例系统讲一下。


一、前端 + 后端配合(基础防重)

1. 前端防重复点击

  • 按钮置灰
  • 请求未完成不允许再次点击

只能防“手抖”,不能防恶意或重试


二、Token 机制(防表单重复提交)

思路

  1. 进入页面时后端生成 token
  2. 提交时携带 token
  3. 后端校验 token 并立即删除
  4. 重复提交 token 已失效

Java 示例(Spring Boot)

// 生成 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 / 分布式


三、唯一请求标识(RequestId 防重)

思路

  • 客户端生成 requestId
  • 服务端用 requestId 做唯一判断
  • 通常结合 Redis

Java 示例(Redis)

@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 "重复下单";
}

✅ 最可靠
❌ 只能防“数据重复”


五、分布式锁(高并发防重)

Redis 分布式锁

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);
}

✅ 高并发
✅ 分布式


六、接口幂等设计(推荐)

幂等方案组合

  • RequestId + Redis
  • 数据库唯一索引
  • 状态机(已支付不可再支付)

七、方案选择建议

场景 推荐方案
表单提交 Token
API 接口 RequestId + Redis
支付/下单 RequestId + 数据库唯一
高并发 分布式锁
最终保障 数据库约束

如果你愿意,可以告诉我:

  • 用的是 Spring Boot / Spring Cloud
  • 是否 分布式
  • 具体接口(下单 / 支付 / 登录)

我可以给你一套可直接用的完整防重方案。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手