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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

redis+aop防重复提交

發布時間:2024/9/30 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis+aop防重复提交 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1.防重復提交注解
  • 2.redis分布式鎖
  • 3.防止重復提交Aop

之前有記錄一篇用redis+攔截器防重復提交的內容:
redis+攔截器防重復提交

1.防重復提交注解

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface NoRepeatSubmit {/*** 設置請求鎖定時間** @return*/int lockTime() default 10;}

2.redis分布式鎖

/*** Redis 分布式鎖實現*/ @Service public class RedisLock {private static final Long RELEASE_SUCCESS = 1L;private static final String LOCK_SUCCESS = "OK";private static final String SET_IF_NOT_EXIST = "NX";// 當前設置 過期時間單位, EX = seconds; PX = millisecondsprivate static final String SET_WITH_EXPIRE_TIME = "EX";// if get(key) == value return del(key)private static final String RELEASE_LOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";@Autowiredprivate StringRedisTemplate redisTemplate;/*** 該加鎖方法僅針對單實例 Redis 可實現分布式加鎖* 對于 Redis 集群則無法使用* <p>* 支持重復,線程安全** @param lockKey 加鎖鍵* @param clientId 加鎖客戶端唯一標識(采用UUID)* @param seconds 鎖過期時間* @return*/public boolean tryLock(String lockKey, String clientId, int seconds) {return redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> {Jedis jedis = (Jedis) redisConnection.getNativeConnection();String result = jedis.set(lockKey, clientId, SetParams.setParams().nx().ex(seconds));if (LOCK_SUCCESS.equals(result)) {return true;}return false;});} //redisTemplate.execute的源碼: // public <T> T execute(RedisCallback<T> action) { // return execute(action, isExposeConnection());//}/*** 與 tryLock 相對應,用作釋放鎖** @param lockKey* @param clientId* @return*/public boolean releaseLock(String lockKey, String clientId) {return redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> {Jedis jedis = (Jedis) redisConnection.getNativeConnection();Object result = jedis.eval(RELEASE_LOCK_SCRIPT, Collections.singletonList(lockKey),Collections.singletonList(clientId));if (RELEASE_SUCCESS.equals(result)) {return true;}return false;});} }

3.防止重復提交Aop

//yixiangshangcheng @Aspect @Component @Slf4j public class RepeatSubmitAspect {@Autowiredprivate RedisLock redisLock;@Pointcut("@annotation(noRepeatSubmit)")public void pointCut(NoRepeatSubmit noRepeatSubmit) {}@Around("pointCut(noRepeatSubmit)")public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) throws Throwable {int lockSeconds = noRepeatSubmit.lockTime();HttpServletRequest request = RequestHolder.getHttpServletRequest();Assert.notNull(request, "request can not null");String bearerToken = request.getHeader("Authorization");String[] tokens = bearerToken.split(" ");String token = tokens[1];String path = request.getServletPath();String key = getKey(token, path);String clientId = getClientId();boolean isSuccess = redisLock.tryLock(key, clientId, lockSeconds);log.info("tryLock key = [{}], clientId = [{}]", key, clientId);if (isSuccess) {log.info("tryLock success, key = [{}], clientId = [{}]", key, clientId);// 獲取鎖成功Object result;try {// 執行進程result = pjp.proceed();} finally {// 解鎖redisLock.releaseLock(key, clientId);log.info("releaseLock success, key = [{}], clientId = [{}]", key, clientId);}return result;} else {// 獲取鎖失敗,認為是重復提交的請求log.info("tryLock fail, key = [{}]", key);///return ApiResult.fail("重復請求,請稍后再試");throw new BadRequestException("重復請求,請稍后再試");}}private String getKey(String token, String path) {return token + path;}private String getClientId() {return UUID.randomUUID().toString();}}

之后在Contoller方法上加 @NoRepeatSubmit即可。

總結

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

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