Java中实现接口幂等性的一个常见方法

1、幂等性

对同一个接口的多次请求,返回的结果相同,叫做接口的幂等性。由于相同条件下查询操作返回的结果总是相同的,所以查询操作具有天然的幂等性,而新增、更新、删除等操作重复执行可能会返回不同的结果,故不具备幂等性。

2、场景

在一条审批链中,有多个业务人员和一个管理人员,业务人员需要处理待办任务并交由管理人员审批通过,所有的业务人员看到的待办任务列表都是相同的,任一待办任务可由任一业务人员处理。待办任务处理完毕后,其审批人变为管理人员,不会在出现在业务人员的待办任务列表。

  • 问题一:
    业务员小明在浏览器中开了两个Tab页,然后在其中一个里面对待办任务A进行了处理,任务A的审批人进行了更新,数据库更新了1条记录,返回提交成功的通知,当前Tab页的任务列表刷新,任务A消失。此时小明参加了一个15分钟的紧急会议,随手关闭了当前Tab页。浏览器会话可以保持30分钟,会议结束后,小明继续处理待办任务,此时在另外一个没有刷新的Tab页中看到了任务A,健忘的小明继续对其进行处理,提交表单后,数据库更新了0条记录,返回提交失败的消息。
  • 问题二:
    由于所有业务员看到的任务列表是一样的,某天,小明和小红同时打开页面对同一任务B进行了处理,小明先于小红30秒提交了表单,小明的页面返回了提交成功的通知。此时数据库中任务的审批人已经更新,小红的页面返回提交失败的消息通知。
3、解决方案
1、分析
  • 上述场景中的问题都是由于重复发送了提交表单的请求(更新操作),虽然没有造成脏数据,但是业务人员在处理时会造成混乱,而且如果换成插入操作的场景的话后台还可能发生错误。对于发送的请求,后台应该判断其是否是重复发送的,如果重复提交应该返回通知请勿重复提交,这种判断的依据我们称之为幂等标识
  • 如何判断请求是否重复提交呢?上述场景中处理过的任务审批人都会变成管理人员,我们可以将任务记录的审批人是否是管理人员作为幂等标识。但是为了将其与具体的业务分离开来,可以在系统建一张表存储幂等标识,由前端根据业务数据主键生成一个幂等标识,这样后端获取到请求时就能查表知道是否是重复提交的请求了。
  • 对于问题二还存在一种情况,小红在提交表单时,如果小明的请求还未处理完,即幂等标识还未存入数据库,这时就没办法查幂等标识表判断请求是否重复了。此时就要使用锁机制使得小红的请求等待小明的请求处理完毕后再接着处理,这样就能顺利拿到幂等标识了。
2、步骤

1、在客户端生成幂等标识。
2、将幂等标识作为请求参数之一发送给服务器。
3、服务器收到请求后,先检查数据库中是否已经有相同的幂等标识。如果有,则直接返回响应,标识请求已经被处理过;如果没有,则执行请求并将幂等标识保存到数据库中。
4、在请求处理完成后,服务器返回响应给客户端。
相关入库操作的代码块需要加锁

4、代码示例
@PostMapping("/submitForm")
public ResponseEntity<Void> submitForm(@RequestParam("idempotentId") String idempotentId) {
    // 使用悲观锁
    synchronized (this) {
        // 检查数据库中是否已经有相同的幂等性标识
        boolean exists = idempotentRepository.existsById(idempotentId);
        if (exists) {
            // 如果已经有相同的幂等性标识,则直接返回响应
            return ResponseEntity.ok().build();
        }
        // 执行请求
        // ...
        // 将幂等性标识保存到数据库中
        Idempotent idempotent = new Idempotent();
        idempotent.setId(idempotentId);
        idempotentRepository.save(idempotent);
        // 返回响应
        return ResponseEntity.ok().build();
    }
}

以上。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值