zoukankan      html  css  js  c++  java
  • 防止接口重复提交

    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); } } }
  • 相关阅读:
    ASP.NET Repeater-重复器
    ADO.NET数据库访问技术
    类库和委托、 is 和as
    小知识
    多态
    封装和继承
    资源管理器
    简易计算器
    小知识点
    jquery cookie页面传值和jquery监听页面刷新
  • 原文地址:https://www.cnblogs.com/brxHqs/p/13440306.html
Copyright © 2011-2022 走看看