處理重複請求的心得

2021-10-24 07:47:16 字數 3470 閱讀 1133

基於spring boot、redis template我寫了乙個防止重複請求的控制,直接貼**。

自定義註解、列舉類

@target(elementtype.method)

@retention(retentionpolicy.runtime)

public @inte***ce nonrepeat ::

* 預設根據 token

* 支援 spel 取值非string型別會序列化為json,json.tojsonstring

* @return

*/string lockkey() default "";

/*** 是否在執行結束後釋放鎖

* @return

*/boolean releaseafterreturn() default true;

} /**

* 重複請求列舉

* token 防止當前登入使用者重複請求,防止重複處理

* final 指定key 當前controller只能有乙個人訪問(使用場景不多)

* sp_el 根據入參 根據controller引數校驗重複處理

* @author gary.wang

* @since 2019/11/16 16:50

**/public enum nonrepeatenum

*** 處理

@aspect

@component

public class nonrepeataspect

expression exp = parser.parseexpression(nonrepeat.lockkey());

standardevaluationcontext ctx = new standardevaluationcontext();

ctx.setrootobject(pjp.getargs());

object value = exp.getvalue(ctx);

if (value instanceof string) else

break;

case token:

//自定義userlocal,從threadlocal中獲取使用者的token,根據自己專案取token的方法自己改改

lockkey = userlocal.user.gettoken();

break;

default:

throw new nullpointerexception("not find this policy");

}object result;

string classname = pjp.gettarget().getclass().getname();

string methodname = pjp.getsignature().getname();

lockkey = string.format(redisconstants.redis_repeat_lock, classname, methodname).concat(lockkey);

//獲取鎖,這行**自行封裝,可以直接用jedis.setnx

redislock redislock = new redislock(redistemplate, lockkey, expiration.seconds(nonrepeat.locktime()));

if (redislock.getlock()) else

if (nonrepeat.releaseafterreturn())

return result;

}

redislock 可以在其他場景用,釋放鎖可以使用try with resource特性,不需要釋放鎖的場景可以不使用

@data  //lombok

@allargsconstructor

public class redislock implements closeable

/*** 獲取鎖

*/public boolean getlock()

return redistemplate.execute((rediscallback) connection -> :{}:{}:{}:{}",locked,this.lockkey,this.lockvalue,this.expiration.gettimeunit(),this.expiration.getexpirationtime());

return locked;

});}

//忽略該方法,本文中沒有使用到 try with resource場景

@override

public void close() :{}:releasetime:{}:delflag:{}", this.lockkey, this.lockvalue, releasetime, delflag);

}}

作用於controller,service

1:預設通過token校驗重複請求

//lockkey=repeat:com.***.testcontroller:testrepeat:使用者token

@nonrepeat(locktime=60)

2:一般用於全域性的重複請求校驗

//lockkey=repeat:com.***.testcontroller:testrepeat:send_mail

@nonrepeat(locktime=60,lockkeypolicy = nonrepeatenum.final,lockkey="send_mail")

3:通過傳入引數 支援sp_el寫法

//lockkey=repeat:com.***.testcontroller:testrepeat:第二個引數的name屬性(這裡需要注意,不同的web容器獲取引數的下標可能不一樣)

@nonrepeat(locktime=60,lockkeypolicy = nonrepeatenum.sp_el,lockkey = "[1].name")

public responseresult> testrepeat(@requestparam testqo qo,

@requestbody testqo q1) throws biz***ception

//lockkey=repeat:com.***.testcontroller:testrepeat:第乙個引數

@nonrepeat(locktime=60,lockkeypolicy = nonrepeatenum.sp_el,lockkey = "[0]")

public responseresult> testrepeat(@requestparam string phonenumber,

@requestparam string username) throws biz***ception

如何處理重複請求 併發請求的

你可能會想到的是,只要請求有唯一的請求編號,那麼就能借用redis做這個去重 只要這個唯一請求編號在redis存在,證明處理過,那麼就認為是重複的 string key req12343456788 請求唯一編號 long expiretime 1000 1000毫秒過期,1000ms內的重複請求會...

後端處理高併發狀態的多次重複請求

相信做web的,都有可能遇到有多次重複請求傳送到後端的情況。而這些重複請求,可能大都是由於在網路較差的情況下,使用者多次連續點選。最後導致後端面臨處理大量重複請求的境地。阻止這些情況發生的方法有很多。比如在前端,可以設定當使用者點選按鈕之後,禁用按鈕直到有結果返回。如果是用ajax傳送請求,那麼在傳...

請求重複和說明

請求重複和說明。如果您沒有聽見或理解某人的話,您可以請求重複 a can you repeat that?您能再說一遍嗎?b i really don t like cooking.我真不喜歡做飯。a oh,right.哦,對啊。如果您希望某人說明他的意思,您可以使用以下表達 a it s real...