Java實(shí)現(xiàn)冪等性校驗(yàn)的示例代碼
我們?cè)谧鰓eb應(yīng)用的時(shí)候通常會(huì)遇到前端提交按鈕重復(fù)點(diǎn)擊的場(chǎng)景,在某些新增操作上就需要做冪等性限制來保證數(shù)據(jù)的可靠性。下面來用java aop實(shí)現(xiàn)冪等性校驗(yàn)。
一:首先我們需要一個(gè)自定義注解
package com.yuku.yuku_erp.annotation;
import java.lang.annotation.*;
/**
* @author 名一
* @ClassName IdempotentAnnotation
* @description: 用來標(biāo)記需要校驗(yàn)冪等性的接口
* @datetime 2024年 02月 03日 14:48
* @version: 1.0
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IdempotentAnnotation {
String idempotentType();
}二:創(chuàng)建一個(gè)冪等校驗(yàn)的切面類
package com.yuku.yuku_erp.aop;
import com.yuku.yuku_erp.annotation.IdempotentAnnotation;
import com.yuku.yuku_erp.constant.RedisKeyConstant;
import com.yuku.yuku_erp.exception.MyException;
import com.yuku.yuku_erp.utils.RedisShardedPoolUtil;
import com.yuku.yuku_erp.utils.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* @author 名一
* @ClassName CheckIdempotentAop
* @description: 冪等性校驗(yàn)
* @datetime 2024年 02月 03日 14:59
* @version: 1.0
*/
@Slf4j
@Aspect
@Component
public class CheckIdempotentAop {
@Pointcut("execution(* com.yuku.yuku_erp.controller..*.*(..))")
public void checkCut(){
}
@Before("checkCut()")
public void checkIdempotent(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
if (method.isAnnotationPresent(IdempotentAnnotation.class)){
IdempotentAnnotation annotation = method.getAnnotation(IdempotentAnnotation.class);
String idempotentType = annotation.idempotentType();
String idempotentToken = TokenUtil.getRequest().getHeader("idempotentToken");
String idemToken = idempotentType + idempotentToken;
log.info("checkIdempotent idempotentType:{}, idempotentToken:{}", idempotentType, idempotentToken);
Boolean flag = RedisShardedPoolUtil.sismember(RedisKeyConstant.IDEMPOTENT_TOKEN_LIST, idemToken);
if (!flag){
log.error("checkIdempotent error idempotentType:{}, idempotentToken:{}, flag:{}", idempotentType, idempotentToken, flag);
throw new MyException("該接口已提交過,請(qǐng)不要重復(fù)提交");
}
RedisShardedPoolUtil.delSetByValue(RedisKeyConstant.IDEMPOTENT_TOKEN_LIST, idemToken);
log.info("checkIdempotent idempotentType:{}, idempotentToken:{}, flag:{}", idempotentType, idempotentToken, flag);
}
}
}三:在需要切面的接口上使用冪等校驗(yàn)注解
@IdempotentAnnotation(idempotentType = "checkIdempotentToken")
@GetMapping("/checkIdempotentToken")
@ApiOperation(value = "校驗(yàn)冪等性示例")
public CommonResult<String> checkIdempotentToken(){
return CommonResult.success();
}到此冪等校驗(yàn)就完成了
四:方法補(bǔ)充
除了上文的方法,小編還為大家整理了其他實(shí)現(xiàn)冪等校驗(yàn)的方法,希望對(duì)大家有所幫助
1.唯一標(biāo)識(shí)符校驗(yàn)
一種簡(jiǎn)單的方式是使用唯一標(biāo)識(shí)符來校驗(yàn)請(qǐng)求的冪等性,每次請(qǐng)求時(shí),客戶端生成一個(gè)唯一的標(biāo)識(shí)符,并將其作為請(qǐng)求的一部分發(fā)送給服務(wù)器。服務(wù)器在接收到請(qǐng)求后先檢查該標(biāo)識(shí)符是否已經(jīng)存在,如果存在則認(rèn)為是重復(fù)請(qǐng)求,直接忽略;如果不存在,則執(zhí)行相應(yīng)的業(yè)務(wù)邏輯,并將標(biāo)識(shí)符保存到一個(gè)冪等性校驗(yàn)表中
下面是一個(gè)使用 UUID 實(shí)現(xiàn)的示例代碼:
// 生成唯一標(biāo)識(shí)符
String requestId = UUID.randomUUID().toString();
// 發(fā)送清求
HttpResponse response = httpClient.execute(request);
// 檢查響應(yīng)結(jié)果
if (response.getStatusLine().getStatusCode() == 200){
// 保存標(biāo)識(shí)符到冪等性校驗(yàn)表
idempotentTable.put(requestId, true);
}2. Token 校驗(yàn)
另一種方式是使用 Token 來校驗(yàn)請(qǐng)求的冪等性。服務(wù)器在第一次收到請(qǐng)求時(shí),在響應(yīng)中返回一個(gè)唯一的 Token 給客戶端,客戶端在下次請(qǐng)求時(shí)將該 Token 作為請(qǐng)求的一部分發(fā)送給服務(wù)器。服務(wù)器在接收到請(qǐng)求后,先檢查該 Token 是否有效,如果有效則執(zhí)行相應(yīng)的業(yè)務(wù)邏輯,并將 Token 標(biāo)記為已使用;如果無效則忽略該請(qǐng)求。
下面是一個(gè)使用 Token 實(shí)現(xiàn)的示例代碼:
// 發(fā)送第一次詩(shī)求,并獲 Token
HttpResponse response1 = httpClient.execute(request);
String token = response1.getFirstHeader("Token").getValue();
// 發(fā)送第二次詩(shī)求,并附 Token
request.addHeader("Token",token);
HttpResponse response2 = httpClient.execute(request);
// 檢查響應(yīng)結(jié)果
if (response2.getStatusLine().getstatusCode() == 200) {
// 標(biāo)記 Token 為已使用
tokenService.markAsUsed(token);
}到此這篇關(guān)于Java實(shí)現(xiàn)冪等性校驗(yàn)的示例代碼的文章就介紹到這了,更多相關(guān)Java冪等性校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何解決項(xiàng)目中java heap space的問題
這篇文章主要介紹了如何解決項(xiàng)目中java heap space的問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
java隨機(jī)數(shù)生成具體實(shí)現(xiàn)代碼
這篇文章主要為大家分享了java隨機(jī)數(shù)生成具體實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-04-04
SpringBoot接受前臺(tái)參數(shù)的6種方式以及統(tǒng)一響應(yīng)代碼示例
這篇文章主要給大家介紹了關(guān)于SpringBoot接受前臺(tái)參數(shù)的6種方式以及統(tǒng)一響應(yīng)的相關(guān)資料,前端負(fù)責(zé)展示頁(yè)面和用戶交互,而后端則負(fù)責(zé)處理業(yè)務(wù)邏輯和數(shù)據(jù)存儲(chǔ),在這種架構(gòu)下前端需要將用戶輸入的數(shù)據(jù)發(fā)送給后端進(jìn)行處理,需要的朋友可以參考下2023-12-12
Java中HttpServletResponse響應(yīng)中文出現(xiàn)亂碼問題
這篇文章主要介紹了Java中HttpServletResponse響應(yīng)中文出現(xiàn)亂碼問題的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
java實(shí)現(xiàn)簡(jiǎn)單日期計(jì)算功能
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單日期計(jì)算功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
java版簡(jiǎn)單的猜數(shù)字游戲?qū)嵗a
猜數(shù)字游戲是一款經(jīng)典的游戲,該游戲說簡(jiǎn)單也很簡(jiǎn)單,說不簡(jiǎn)單確實(shí)也很難,那么下面這篇文章主要給大家介紹了java版簡(jiǎn)單的猜數(shù)字游戲的相關(guān)資料,文中給出了詳細(xì)的實(shí)現(xiàn)分析和示例代碼供大家參考學(xué)習(xí),需要的朋友們下面來一起看看吧。2017-05-05
Spring Boot日志收集及鏈路追蹤實(shí)現(xiàn)示例
這篇文章主要為大家介紹了Spring Boot日志收集及鏈路追蹤實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12

