- 冪等性
- 什么場景下需要用到冪等
- 冪等的實現(xiàn)原理
-
冪等的代碼實現(xiàn)
- 冪等的使用
冪等性
今天我們來談?wù)勈裁词?code style="font-size:14px;padding:2px 4px;margin-right:2px;margin-left:2px;color:rgb(30,107,184);background-color:rgba(27,31,35,.05);font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;">冪等性?
引用百度百科
的解析如下:
?
冪等(idempotent、idempotence)是一個數(shù)學(xué)與計算機學(xué)概念,常見于抽象代數(shù)中。
在編程中一個冪等操作的特點是其任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同。冪等函數(shù),或冪等方法,是指可以使用相同參數(shù)
重復(fù)執(zhí)行
,并能獲得相同結(jié)果
的函數(shù)。這些函數(shù)不會影響系統(tǒng)狀態(tài),也不用擔(dān)心重復(fù)執(zhí)行會對系統(tǒng)造成改變。例如,“setTrue()”函數(shù)就是一個冪等函數(shù),無論多次執(zhí)行,其結(jié)果都是一樣的.更復(fù)雜的操作冪等保證是利用唯一交易號(流水號)實現(xiàn)。?
這解析,確實有點長
了,大家話看看就行了!!!(●'?'●)
那對于我們程序員
來說,我們關(guān)心的更多是下面這些問題:
?
什么地方,什么場景下需要用到冪等?
冪等,我們需要怎么做,如何實現(xiàn)冪等呢?
?
基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
- 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 視頻教程:https://doc.iocoder.cn/video/
什么場景下需要用到冪等
- 前端表單重復(fù)提交問題
- 用戶訂單支付問題
- 銀行業(yè)務(wù)辦理取號問題
- 用戶惡意進行調(diào)接口問題
- 接口超時重復(fù)提交問題
- MQ消息進行重復(fù)消費
- ...
當(dāng)然了,還有很多場景會用到冪等
,這里咱們就不一一列舉出來了。
那我們要如何設(shè)計一個冪等功能呢,而且還是代碼非侵入式
?
代碼非侵入式
的意思,就是,我們的業(yè)務(wù)邏輯代碼,不需要處理冪等
校驗的邏輯。
業(yè)務(wù)功能不處理?那交給誰處理呢?別著急,聽哥們一一道來。^_^
這里,要實現(xiàn)代碼非侵入式
的冪等校驗,我們就要使用到切面
編程了(@Aspect
)
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
冪等的實現(xiàn)原理
在系統(tǒng)中一些接口
需要增加冪等
處理,冪等
的概念是一個業(yè)務(wù)請求只能執(zhí)行一次。類似銀行業(yè)務(wù)辦理,首先需要取一個號,然后用戶使用這個號去柜臺辦理業(yè)務(wù)。這個號只能使用一次,如果過期或者已辦理這個號就無效了。
我們的冪等
也是使用這種原理。
?
- 1.首先客戶端調(diào)用通過我們的系統(tǒng)獲取一個號,我們稱之為
冪等號
,這個號已經(jīng)存在我們的系統(tǒng)中。- 2.客戶端使用這個號,調(diào)用我們的接口。
- 3.我們系統(tǒng)判斷這個號在我們的系統(tǒng)中已經(jīng)存在,如果存在則允許業(yè)務(wù)辦理,如果不存在,則表示這是一個非法的號,我們直接拋出異常。
- 4.當(dāng)業(yè)務(wù)處理完成,我們會將這個號從我們的系統(tǒng)中刪除掉。
?
好了,這實現(xiàn)步驟
,也是十分清晰了呀!!!^_^
那么我們下面就來看代碼如何實現(xiàn)了
冪等的代碼實現(xiàn)
- 定義一個冪等處理接口
publicinterfaceIdempotence{
/**
*檢查是否存在冪等號
*@paramidempotenceId冪等號
*@return是否存在
*/
booleancheck(StringidempotenceId);
/**
*記錄冪等號
*@paramidempotenceId冪等號
*/
voidrecord(StringidempotenceId);
/**
*記錄冪等號
*@paramidempotenceId冪等號
*@paramtime過期時間
*/
voidrecord(StringidempotenceId,Integertime);
/**
*刪除冪等號
*@paramidempotenceId冪等號
*/
voiddelete(StringidempotenceId);
}
- 定義一個冪等處理接口實現(xiàn)類
@Component
publicclassRedisIdempotenceimplementsIdempotence{
@Autowired
privateRedisRepositoryredisRepository;
@Override
publicbooleancheck(StringidempotenceId){
returnredisRepository.exists(idempotenceId);
}
@Override
publicvoidrecord(StringidempotenceId){
redisRepository.set(idempotenceId,"1");
}
@Override
publicvoidrecord(StringidempotenceId,Integertime){
redisRepository.setExpire(idempotenceId,"1",time);
}
@Override
publicvoiddelete(StringidempotenceId){
redisRepository.del(idempotenceId);
}
}
?
這個實現(xiàn)類,咱們就用
redis
存儲這個冪等號
實現(xiàn)4個方法:檢查是否存在冪等號
記錄冪等號
記錄冪等號(帶過期時間)
刪除冪等號
?
- 冪等工具類
@Component
publicclassIdempotenceUtil{
@Autowired
privateRedisRepositoryredisRepository;
/**
*生成冪等號
*@return
*/
publicStringgenerateId(){
Stringuuid=UUID.randomUUID().toString();
StringuId=Base64Util.encode(uuid).toLowerCase();
redisRepository.setExpire(uId,"1",1800);
returnuId;
}
/**
*從Header里面獲取冪等號
*@return
*/
publicStringgetHeaderIdempotenceId(){
ServletRequestAttributesattributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequestrequest=attributes.getRequest();
StringidempotenceId=request.getHeader("idempotenceId");
returnidempotenceId;
}
}
?
這個工具類,提供兩個方法。
1.生成一個冪等號,咱們就用uuid
2.從Header里面獲取冪等號
?
- 定義一個注解
/**
*接口增加冪等性
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public@interfaceIdempotenceRequired{
}
- 切面
@Aspect
@Slf4j
@Component
publicclassIdempotenceSupportAdvice{
@Autowired
privateIdempotenceidempotence;
@Autowired
IdempotenceUtilidempotenceUtil;
/**
*攔截有@IdempotenceRequired注解的方法。
*/
@Pointcut("@annotation(xxx.xxx.IdempotenceRequired)")
publicvoididempotenceMethod(){}
@AfterThrowing(value="idempotenceMethod()()",throwing="e")
publicvoidafterThrowing(Throwablee){
if(!(einstanceofIdempotencyException)){
//從HTTPheader中獲取冪等號idempotenceId
StringidempotenceId=idempotenceUtil.getHeaderIdempotenceId();
idempotence.record(idempotenceId,1800);
}
}
@Around(value="idempotenceMethod()")
publicObjectaround(ProceedingJoinPointjoinPoint)throwsThrowable{
//從HTTPheader中獲取冪等號idempotenceId
StringidempotenceId=idempotenceUtil.getHeaderIdempotenceId();
if(StringUtils.isEmpty(idempotenceId)){
//不存在冪等號則不進行額外操作
returnjoinPoint.proceed();
}
//前置操作冪等號是否存在
booleanexisted=idempotence.check(idempotenceId);
if(!existed){
thrownewIdempotencyException("{success:false,message:"操作重復(fù),請重新輸入冪等號重試!",data:-2}");
}
//刪除冪等號
idempotence.delete(idempotenceId);
Objectresult=joinPoint.proceed();
returnresult;
}
}
- 定義個controller
@RequestMapping("/idempotence")
publicclassIdempotenceController{
/**
*生成冪等號
*@return
*/
@GetMapping("/generateId")
publicJsonResultgenerateId(){
IdempotenceUtilidempotenceUtil=SpringUtil.getBean(IdempotenceUtil.class);
StringuId=idempotenceUtil.generateId();
returnJsonResult.success("成功生成!").setData(uId);
}
}
好了,實現(xiàn)的代碼,就是這些了,理解
起來也是比較簡單
,沒有過多復(fù)雜的邏輯。
接下來,就是如何使用的問題
了,
這個使用,也是十分的簡單啦!!!
冪等的使用
「服務(wù)端:」
不是所有的方法都需要切面攔截 ,只有 IdempotenceRequired
注解的方法才會被攔截。
例如下面接口:
@IdempotenceRequired
@PostMapping("/getUsers")
publicJsonResultgetUsers(){
//執(zhí)行正常業(yè)務(wù)邏輯
...
}
在開發(fā)冪等
接口時,只需要在方法上簡單增加一個 IdempotenceRequired
注解即可。
這基本上就是代碼非侵入式
了呀!!!
「客戶端:」
服務(wù)端處理好后,在客戶端訪問接口的時候需要執(zhí)行以下步驟:
?
- 需要先獲取
冪等號
- 然后將
冪等號
添加到請求頭中?
-
1.獲取
冪等號
http://服務(wù)地址/idempotence/generateIdhttp://xn--zfry9hnb732h/idempotence/generateId

- 2.請求調(diào)用
?
往header中添加冪等號
?

好了,到這里冪等的實現(xiàn),就已經(jīng)完成了!!!^_^
那我們就可以愉快的編寫代碼了!!!^_^
審核編輯 :李倩
-
JAVA
+關(guān)注
關(guān)注
20文章
2985瀏覽量
106942 -
編程
+關(guān)注
關(guān)注
88文章
3683瀏覽量
94885 -
代碼
+關(guān)注
關(guān)注
30文章
4888瀏覽量
70274
原文標(biāo)題:推薦一種非侵入式冪等性的Java實現(xiàn)
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
論非接觸式液位傳感器在電池液液位檢測中的技術(shù)實踐與創(chuàng)新

?非侵入式路面狀況傳感器的技術(shù)優(yōu)勢
一種新型的非晶態(tài)NbP半金屬薄膜

加州理工學(xué)院:研究一種無創(chuàng)監(jiān)測女性激素的可穿戴生物傳感器

一種可以提升動態(tài)血糖監(jiān)測均勻性和精確度的導(dǎo)電油墨
使用TMS320C31在通信網(wǎng)絡(luò)中實現(xiàn)在線非侵入式測量設(shè)備

CGQ-24霍爾傳感器是一種什么類型的傳感器
非接觸式測量傳感器有哪些特點
華納云:java web和java有什么區(qū)別java web和java有什么區(qū)別

評論