自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何防止接口重復(fù)提交?

開(kāi)發(fā) 前端
對(duì)于下單流量不算高的系統(tǒng),可以采用這種請(qǐng)求唯一ID+數(shù)據(jù)表增加唯一索引約束的方式,來(lái)防止接口重復(fù)提交!

一、摘要

對(duì)于投入運(yùn)營(yíng)的軟件系統(tǒng),最近小編在巡檢項(xiàng)目數(shù)據(jù)庫(kù)的時(shí)候,發(fā)現(xiàn)某些表存在不少的重復(fù)數(shù)據(jù),對(duì)于這樣的臟數(shù)據(jù),初步分析大致的來(lái)源有以下可能:

1.由于用戶(hù)誤操作,多次點(diǎn)擊表單提交按鈕

2.由于網(wǎng)速等原因造成頁(yè)面卡頓,用戶(hù)重復(fù)刷新提交頁(yè)面

3.黑客或惡意用戶(hù)使用 postman 等網(wǎng)絡(luò)工具,重復(fù)惡意提交表單

這些情況都可能會(huì)導(dǎo)致表單重復(fù)提交,造成數(shù)據(jù)重復(fù),比如訂單表,重復(fù)提交訂單數(shù)據(jù)所造成的問(wèn)題,可能不僅僅是數(shù)據(jù)上的混亂,也會(huì)造成業(yè)務(wù)混亂。

那么問(wèn)題來(lái)了,我們?cè)撊绾畏乐褂脩?hù)重復(fù)提交數(shù)據(jù)呢?

方案實(shí)踐如下!

二、方案實(shí)踐

下面我們以防止重復(fù)提交訂單為例,向大家介紹最簡(jiǎn)單的、成本最低的解決辦法。

我們先來(lái)看一張圖,這張圖就是本次方案的核心流程圖。

圖片

實(shí)現(xiàn)的邏輯,流程如下:

1.當(dāng)用戶(hù)進(jìn)入訂單提交界面的時(shí)候,調(diào)用后端獲取請(qǐng)求唯一ID,并將唯一ID值埋點(diǎn)在頁(yè)面里面

2.當(dāng)用戶(hù)點(diǎn)擊提交按鈕時(shí),后端檢查這個(gè)唯一ID是否用過(guò),如果沒(méi)有用過(guò),繼續(xù)后續(xù)邏輯;如果用過(guò),就提示重復(fù)提交

3.最關(guān)鍵的一步操作,就是把這個(gè)唯一ID 存入業(yè)務(wù)表中,同時(shí)設(shè)置這個(gè)字段為唯一索引類(lèi)型,從數(shù)據(jù)庫(kù)層面做防止重復(fù)提交

防止重復(fù)提交的大體思路如上,實(shí)踐代碼如下!

2.1、給數(shù)據(jù)庫(kù)表增加唯一鍵約束

以訂單表為例,新增一個(gè)request_id字段,并設(shè)置為唯一約束,結(jié)構(gòu)如下:

CREATE TABLE tb_order (
id bigint(20) unsigned NOT NULL,
order_no varchar(100) NOT NULL,
....
request_id varchar(36) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY uniq_request_id (request_id) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2.2、編寫(xiě)獲取請(qǐng)求唯一ID的接口

@RestController
@RequestMapping("api")
public class CommonController {

/**
* 獲取getRequestId
* @return
*/
@RequestMapping("getRequestId")
public ResResult getRequestId(){
String uuid = UUID.randomUUID().toString();
return ResResult.getSuccess(uuid);
}
}

2.3、業(yè)務(wù)提交的時(shí)候,檢查唯一ID

@RestController
@RequestMapping("order")
public class OrderController {

@Autowired
private OrderService orderService;

/**
* 下單
* @param request
* @return
*/
@PostMapping(value = "order/confirm")
public ResResult confirm(@RequestBody OrderConfirmRequest request){
//調(diào)用訂單下單相關(guān)邏輯
if(StringUtils.isEmpty(request.getRequestId())){
return ResResult.getSysError("請(qǐng)求ID不能為空!");
}
if(request.getRequestId().length() != 36){
return ResResult.getSysError("請(qǐng)求ID格式錯(cuò)誤!");
}
//檢查當(dāng)前請(qǐng)求唯一ID,是否已經(jīng)存在,如果存在,再提交就是重復(fù)下單
Order source = orderService.queryByRequestId(request.getRequestId());
if(Objects.nonNull(source)){
return ResResult.getSysError("當(dāng)前訂單已經(jīng)提交成功,請(qǐng)勿重復(fù)提交");
}
orderService.confirm(request);
return ResResult.getSuccess();
}
}

如果是并發(fā)請(qǐng)求也不用擔(dān)心,因?yàn)閿?shù)據(jù)庫(kù)表已經(jīng)設(shè)置了唯一索引,尤其只有一條有效數(shù)據(jù)會(huì)插入成功,可以防止重復(fù)的數(shù)據(jù)產(chǎn)生。

三、小結(jié)

對(duì)于下單流量不算高的系統(tǒng),可以采用這種請(qǐng)求唯一ID+數(shù)據(jù)表增加唯一索引約束的方式,來(lái)防止接口重復(fù)提交!

雖然簡(jiǎn)單粗暴,但是十分有效!

可能有的人會(huì)問(wèn),看上面的代碼生成請(qǐng)求唯一 ID 很簡(jiǎn)單,為啥不直接前端生成一個(gè)請(qǐng)求唯一ID,然后提交呢?

之所以把獲取請(qǐng)求唯一ID的生成規(guī)則放在后端,好處就是生成規(guī)則可以自己定義,也并不一定要用uuid來(lái)生成,也可以用雪花算法,或者自己設(shè)計(jì)一套計(jì)算規(guī)則,保證當(dāng)前業(yè)務(wù)提交時(shí)請(qǐng)求ID是唯一的,比如事先生成唯一的訂單號(hào),作為請(qǐng)求唯一ID,然后再提交,規(guī)則放在后端來(lái)生成,會(huì)更加靈活!

責(zé)任編輯:武曉燕 來(lái)源: Java極客技術(shù)
相關(guān)推薦

2022-11-15 07:39:48

2022-11-17 07:43:13

2024-06-06 08:46:37

2023-06-05 08:22:20

2013-11-13 14:39:53

表單提交開(kāi)發(fā)

2013-11-13 11:01:14

表單表單重復(fù)提交表單策略

2024-06-21 09:19:45

代碼接口重復(fù)請(qǐng)求開(kāi)發(fā)

2020-07-17 07:59:55

數(shù)據(jù)

2010-11-23 16:56:04

mysql表單

2022-05-25 09:55:40

數(shù)據(jù)重復(fù)提交Java

2024-08-05 09:29:00

前端接口請(qǐng)求

2024-05-28 09:26:46

2009-06-05 10:37:52

struts2 國(guó)際化表單

2009-08-24 10:47:45

C#接口重實(shí)現(xiàn)

2024-02-19 00:00:00

接口圖形驗(yàn)證碼

2024-12-16 00:54:05

2024-09-02 11:05:49

2021-02-28 07:43:28

請(qǐng)求提交方案

2021-04-28 14:31:35

Dubbo接口日志

2025-04-27 01:22:00

QPS高并發(fā)MySQL
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)