• 防止接口重复提交


    https://www.jianshu.com/p/4c9a529ae4e9

    /**
     * <p>Description: [防重复提交注解]</p >
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NoRepeatSubmit {
       //还可以增加过期时间内的访问次数限制等  maxCount incr
        /**
         * 过期时长(毫秒)
         *
         * @return
         */
        long expire() default 500;@Aspect@Component
    @Slf4j
    public class NoRepeatSubmitAop {
    
        private static final String TOKEN_KEY = "Authorization";
    
        @Autowired
        private CacheService cacheService;
    
        @Autowired
        private RedissonClient redissonClient;
    
        @Pointcut("@annotation(com.fehorizon.erp.prepose.annotation.NoRepeatSubmit)")
        public void serviceNoRepeat() {
            // 这是一个标记方法
        }
    
        @Around("serviceNoRepeat()")
        public Object around(ProceedingJoinPoint pjp) throws Throwable {
            HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String token = request.getHeader(TOKEN_KEY);
            String url = request.getRequestURL().toString();
            String params = Arrays.toString(pjp.getArgs());
            String key =  CacheKeyBuild.buildSysAccountKey(MD5Util.MD(token + "-" + url + "-" + params));
            // 这里使用分布锁保证其线程安全(这里很关键),分布式锁实现可参考 [https://www.jianshu.com/p/d00999155166]
            String lockKey = "Lock-" + key;
            RLock lock = RedisLock.getLock(redissonClient, lockKey);采用redisson专门来做分布式锁,然后用redis做缓存服务,单纯的 put,get
         boolean res = RedisLock.lock(lock); if(!res) { throw new ServiceException(ResultCodeEnum.CODE_10007.code, ResultCodeEnum.CODE_10007.desc); } Optional<String> cacheValue = Optional.ofNullable(cacheService.getString(key)); log.info("======> " + Thread.currentThread() + "NoRepeatSubmitAop {} -> {}", key, cacheValue.isPresent()); if (!cacheValue.isPresent()) { try { Object o = pjp.proceed(); MethodSignature signature = (MethodSignature) pjp.getSignature(); NoRepeatSubmit noRepeatSubmit = signature.getMethod().getAnnotation(NoRepeatSubmit.class); // 默认500毫秒内同一认证用户同一个地址同一个参数,视为重复提交 cacheService.set(key, "0", noRepeatSubmit.expire(), TimeUnit.MILLISECONDS);//可以改造incr
              return o; }catch (ServiceException e){ log.error(e.getMessage(), e); throw e; }catch (Exception e){ log.error(ResultCodeEnum.CODE_10000.desc, e); throw new ServiceException(ResultCodeEnum.CODE_10000.code, e.getMessage()); } finally { RedisLock.unlock(lock); } } else {
            //可以增加最大次数限制的功能 RedisLock.unlock(lock);
    throw new ServiceException(ResultCodeEnum.CODE_10007.code, ResultCodeEnum.CODE_10007.desc); } } }
  • 相关阅读:
    ES6的新特性(18)——async 函数
    ES6的新特性(17)——Generator 函数的异步应用
    ES6的新特性(16)——Generator 函数的语法
    ES6的新特性(15)——Promise 对象
    ES6的新特性(14)——Iterator 和 for...of 循环
    ES6的新特性(13)——Symbol
    ES6的新特性(12)——Set 和 Map 数据结构
    ES6的新特性(11)——Class 的继承
    我的游戏学习日志22——游戏元素的解析(6)
    我的游戏学习日志21——游戏元素的解析(5)
  • 原文地址:https://www.cnblogs.com/brxHqs/p/13440306.html
Copyright © 2020-2023  润新知