日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Spring AOP + Redis解决重复提交的问题

發布時間:2023/11/28 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring AOP + Redis解决重复提交的问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Spring AOP + Redis解決重復提交的問題

用戶在點擊操作的時候,可能會連續點擊多次,雖然前端可以通過設置按鈕的disable的屬性來控制按鈕不可連續點擊,但是如果別人拿到請求進行模擬,依然會出現問題,項目是用JWT進行認證的,所以用的token+url來作為key,value無所謂,因為用不到value

1.自定義注解
?

/*** 自定義不重復提交的注解*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatSubmit {/*** 設置請求鎖定時間 默認鎖定一分鐘 防止死鎖* @return*/int lockTime() default 60;}

2.自定義AOP

/*** 自定義不重復提交的切面*/
@Slf4j
@Aspect
@Component
public class RepeatSubmitAspect {@Autowiredprivate RedisUtil redisUtil;@Pointcut("@annotation(noRepeatSubmit)")public void pointCut(NoRepeatSubmit noRepeatSubmit) {}@Around("pointCut(noRepeatSubmit)")public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) {int lockSeconds = noRepeatSubmit.lockTime();ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();String key = getKey(request);try {Boolean isLock = redisUtil.tryLock(key);// 如果緩存中有這個url視為重復提交if (!isLock) {// 執行前 添加鎖redisUtil.addLock(key, 0, lockSeconds);Object o = pjp.proceed();return o;} else {log.info("重復提交");return ResponseData.oferror("請勿重復提交");}} catch (Throwable e) {e.printStackTrace();log.error("驗證重復提交時出現未知異常!");throw new RuntimeException(e);}finally {// 執行后 刪除鎖redisUtil.releaseLock(key);}}private String getKey(HttpServletRequest request) {String token = request.getHeader("Authorization");String key = token + ":" + request.getServletPath();return key;}}

3.Redis工具類

和重復提交無關的Redis操作方法我都給刪除了,因為占空間

/*** @author minalz* @Description Redis工具類* @create 2020-01-29 21:21*/
@Component
public final class RedisUtil {@Resourceprivate RedisTemplate<String, Object> redisTemplate;/*** 普通緩存獲取** @param key 鍵* @return 值*/public Object get(String key) {return key == null ? null : redisTemplate.opsForValue().get(key);}/*** 普通緩存放入并設置時間** @param key   鍵* @param value 值* @param time  時間(秒) time要大于0 如果time小于等于0 將設置無限期* @return true成功 false 失敗*/public boolean set(String key, Object value, long time) {try {if (time > 0) {redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);} else {set(key, value);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 刪除緩存** @param key 可以傳一個值 或多個*/@SuppressWarnings("unchecked")public void del(String... key) {if (key != null && key.length > 0) {if (key.length == 1) {redisTemplate.delete(key[0]);} else {redisTemplate.delete(CollectionUtils.arrayToList(key));}}}/*** 獲取分布式鎖* @return*/public Boolean tryLock(String key){Object o = this.get(key);if(o != null){return true;}return false;}/*** 添加鎖*/public void addLock(String key, Object value, int time){this.set(key, value,time);}/*** 釋放鎖*/public void releaseLock(String key){this.del(key);}
}

4.統一返回的封裝對象

/*** 接口返回封裝對象*/
public class ResponseData22 implements Serializable {private static final long serialVersionUID = 1L;public String code = "200"; // 200:成功 01:失敗public String msg = "OK";public ResponseData22() {}public ResponseData22(String type, String message) {this.code = type;this.msg = message;}public static ResponseData22 oferror(String message){return new ResponseData22("01",message);}public static ResponseData22 ofok(){return new ResponseData22("200","OK");}}

5.測試方法

在測試方法上添加@NoRepeatSubmit(lockTime = 300)

@PostMapping("/normal")
@NoRepeatSubmit(lockTime = 300)
public ResponseData normal() {ResponseData responseData = new ResponseData();responseData.msg = "我是普通用戶";return responseData;
}

?

總結

以上是生活随笔為你收集整理的Spring AOP + Redis解决重复提交的问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。