java后端如何實現(xiàn)防止接口重復(fù)提交
java后端防止接口重復(fù)提交
利用redis實現(xiàn)防止前端重復(fù)點擊按鈕重復(fù)提交。
解釋:
此方法是利用AOP+Redis實現(xiàn)防止接口重復(fù)請求
在需要防止重復(fù)提交的方法上,添加CheckRepeatCommit 注解。
此注解額,有兩個屬性,channel屬性是當(dāng)前訪問的系統(tǒng),redis中key的前綴。
可不填。
expireTime 屬性,是添加了此注解的方法多久之內(nèi)不允許同一用戶重復(fù)請求,默認(rèn)3秒。
防止重復(fù)提交的原理就是:
在每次請求加了CheckRepeatCommit注解的接口時,都會利用AOP在redis中保存一個從1開始的自增數(shù)字,并設(shè)置此KEY的過期時間,當(dāng)后續(xù)同一個用戶再次請求時,判斷此自增數(shù)字是否已存在并>=1,如果已存在并>=1,拋出異常。
話不多說,直接上代碼
自定義注解
import java.lang.annotation.*; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CheckRepeatCommit { String channel() default "APP"; int expireTime() default 3; }
定義切面
import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.concurrent.TimeUnit; @Component @Aspect @Slf4j public class CheckRepeatCommitAspect { @Autowired private RedisTemplate<String, String> redisTemplate; @Pointcut("@annotation(com.upbim.twin.park.common.annotation.CheckRepeatCommit)") private void checkRepeatCommit() { } @Around("checkRepeatCommit()") public Object checkRepeatCommit(ProceedingJoinPoint joinPoint) throws Throwable { String methodName = joinPoint.getSignature().getName(); Object target = joinPoint.getTarget(); //得到攔截的方法 Method method = getMethodByClassAndName(target.getClass(), methodName); log.info("驗證是否重復(fù)提交:" + "調(diào)用方法:" + method); //請求的方法名 String className = joinPoint.getTarget().getClass().getName(); String channel = ""; String bizKey = method.getName(); int expireTime = 0; // 獲取當(dāng)前請求方法的注解,根據(jù)注解配置獲取參數(shù) CheckRepeatCommit checkRepeatCommit = method.getAnnotation(CheckRepeatCommit.class); String userNo = SysUserContextHolder.getSysUser().getUserNo(); String key; if (checkRepeatCommit != null) { //注解上的描述 channel = checkRepeatCommit.channel(); expireTime = checkRepeatCommit.expireTime(); key = getRepeatCommitLock(channel, className, bizKey, userNo, expireTime); if (StringUtils.isBlank(key)) { throw new SystemException(ResultEnum.RE_COMMIT); } } return joinPoint.proceed(); } /** * 根據(jù)類和方法名得到方法 */ public Method getMethodByClassAndName(Class c, String methodName) { Method[] methods = c.getDeclaredMethods(); for (Method method : methods) { if (method.getName().equals(methodName)) { return method; } } return null; } public String getRepeatCommitLock(String channel, String module, String bizKey, String userNo, int expireTime) { if (StringUtils.isEmpty(module) || StringUtils.isEmpty(bizKey)) { throw new ParamException(ResultEnum.PARAMETER_CHECK_ERROR, "getRepeatCommitLock{} 參數(shù)不能為空!"); } String redisKey = channel + StrUtil.COLON + module + StrUtil.COLON + bizKey + StrUtil.COLON + userNo; long count = redisTemplate.opsForValue().increment(redisKey, 1); if (count == 1) { if (expireTime == 0) { expireTime = 60; } redisTemplate.expire(redisKey, expireTime, TimeUnit.SECONDS); return redisKey; } else { return null; } } }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot+Redis執(zhí)行l(wèi)ua腳本的方法步驟
這篇文章主要介紹了SpringBoot+Redis執(zhí)行l(wèi)ua腳本的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Java swing實現(xiàn)酒店管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java swing實現(xiàn)酒店管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-02-02java.lang.UnsupportedClassVersionError異常正確解決方法
java.lang.UnsupportedClassVersionError異常通常發(fā)生在嘗試在較低版本的Java虛擬機(jī)上運行使用更高版本的Jav 編譯器編譯的類文件時,下面就來介紹一下解決方法,感興趣的可以了解一下2024-05-05SpringCloud實現(xiàn)灰度發(fā)布的方法步驟
本文主要介紹了SpringCloud實現(xiàn)灰度發(fā)布的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05微服務(wù)架構(gòu)設(shè)計RocketMQ進(jìn)階事務(wù)消息原理詳解
這篇文章主要介紹了為大家介紹了微服務(wù)架構(gòu)中RocketMQ進(jìn)階層面事務(wù)消息的原理詳解,有需要的朋友可以借鑒參考下希望能夠有所幫助2021-10-10