springboot 防止重復(fù)請(qǐng)求防止重復(fù)點(diǎn)擊的操作
利用 springboot + redis 實(shí)現(xiàn)過濾重復(fù)提交的請(qǐng)求,業(yè)務(wù)流程如下所示,首先定義一個(gè)攔截器,攔截需要進(jìn)行過濾的URL,然后用 session + URL 作為唯一 key,利用 redis setnx 命令,來判斷請(qǐng)求是否重復(fù),如果 key set 成功,說明非重復(fù)請(qǐng)求,失敗則說明重復(fù)請(qǐng)求;

URL 攔截器可以使用 spring 攔截器,但使用 spring,每個(gè)需要過濾的新 URL 都需要添加配置,因此這里使用 AOP 注解 的形式來實(shí)現(xiàn),這樣更直觀一點(diǎn);
首先,定義注解:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface AvoidRepeatRequest {
/** 請(qǐng)求間隔時(shí)間,單位秒,該時(shí)間范圍內(nèi)的請(qǐng)求為重復(fù)請(qǐng)求 */
int intervalTime() default 5;
/** 返回的提示信息 */
String msg() default "請(qǐng)不要頻繁重復(fù)請(qǐng)求!";
}然后定義 AOP,實(shí)現(xiàn)重復(fù)請(qǐng)求過濾功能:
@Component
@Aspect
@Order(100)
public class FilterRepeatRequest {
private static final String SUFFIX = "REQUEST_";
@Autowired
private RedisTemplate redisTemplate;
// 定義 注解 類型的切點(diǎn)
@Pointcut("@annotation(com.common.ann.AvoidRepeatRequest)")
public void arrPointcut() {}
// 實(shí)現(xiàn)過濾重復(fù)請(qǐng)求功能
@Around("arrPointcut()")
public Object arrBusiness(ProceedingJoinPoint joinPoint) {
// 獲取 redis key,由 session ID 和 請(qǐng)求URI 構(gòu)成
ServletRequestAttributes sra = (ServletRequestAttributes)
RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = sra.getRequest();
String key = SUFFIX + request.getSession().getId() + "_" + request.getRequestURI();
// 獲取方法的 AvoidRepeatRequest 注解
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
AvoidRepeatRequest arr = method.getAnnotation(AvoidRepeatRequest.class);
// 判斷是否是重復(fù)的請(qǐng)求
if (!redisTemplate.opsForValue().setIfAbsent(key, 1, arr.intervalTime(), TimeUnit.SECONDS)) {
// 已發(fā)起過請(qǐng)求
System.out.println("重復(fù)請(qǐng)求");
return arr.msg();
}
try {
// 非重復(fù)請(qǐng)求,執(zhí)行業(yè)務(wù)代碼
return joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
return "error";
}
}
}
測(cè)試使用:
@RestController
public class TestAop {
// 使用 AvoidRepeatRequest 注解的請(qǐng)求,表明需要進(jìn)行重復(fù)請(qǐng)求判斷
@AvoidRepeatRequest(intervalTime = 6, msg = "慢點(diǎn),兄弟")
@GetMapping("test/aop")
public String test() {
return "test aop";
}
}到此這篇關(guān)于springboot 防止重復(fù)請(qǐng)求防止重復(fù)點(diǎn)擊的操作的文章就介紹到這了,更多相關(guān)springboot 重復(fù)請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot?使用AOP?+?Redis?防止表單重復(fù)提交的方法
- SpringBoot+Redis使用AOP防止重復(fù)提交的實(shí)現(xiàn)
- SpringBoot整合redis+Aop防止重復(fù)提交的實(shí)現(xiàn)
- SpringBoot攔截器實(shí)現(xiàn)項(xiàng)目防止接口重復(fù)提交
- SpringBoot中防止接口重復(fù)提交的有效方法
- SpringBoot利用Redis實(shí)現(xiàn)防止訂單重復(fù)提交的解決方案
- SpringBoot整合ShedLock解決定時(shí)任務(wù)防止重復(fù)執(zhí)行的問題
- springboot基于注解實(shí)現(xiàn)去重表消息防止重復(fù)消費(fèi)
相關(guān)文章
Java開發(fā)者結(jié)合Node.js編程入門教程
這篇文章主要介紹了Java開發(fā)者結(jié)合Node.js編程入門教程,我將先向您展示如何使用Java EE創(chuàng)建一個(gè)簡(jiǎn)單的Rest服務(wù)來讀取 MongoDB數(shù)據(jù)庫(kù)。然后我會(huì)用node.js來實(shí)現(xiàn)相同的功能,需要的朋友可以參考下2014-09-09
springboot mybatis調(diào)用多個(gè)數(shù)據(jù)源引發(fā)的錯(cuò)誤問題
這篇文章主要介紹了springboot mybatis調(diào)用多個(gè)數(shù)據(jù)源引發(fā)的錯(cuò)誤問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
Mapper類中存在名稱相同的方法重載報(bào)錯(cuò)問題
這篇文章主要介紹了Mapper類中存在名稱相同的方法重載報(bào)錯(cuò)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
解決mybatis-plus-boot-starter與mybatis-spring-boot-starter的錯(cuò)誤問題
本文主要講述了在使用MyBatis和MyBatis-Plus時(shí)遇到的綁定異常問題,通過排查和總結(jié),作者發(fā)現(xiàn)使用MyBatis-Plus?Boot?Starter可以解決這個(gè)問題,文章詳細(xì)對(duì)比了MyBatis-Plus?Boot?Starter和MyBatis?Spring?Boot?Starter的功能和使用場(chǎng)景2025-01-01

