基於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...