• 自定义注解实现接口限流


    自定义注解实现接口限流

    场景:限制验证码在单位时间内的访问次数
    实现流程:自定义一个注解,注解内包含访问的次数与单位时间。通过AOP进行切面拦截,获取注解内的次数和时间,获取请求的uri与访问者ip。组成redis的key。
    使用redis将key进行原子性自增1.如果返回的是1.则设置过期时间,之后的访问直接incr即可。但是这种方式存在问题,不是原子性的,所以需要采用原子性的设置key和过期时间。
    Redis官方目前set命令已经支持了set的时候指定是nx,并且设置过期时间合并成了一条指令,保证了原子性。
    因此采用setIfAbsent()API进行设置。如果返回的true。代表首次设置key。如果已经存在,则返回false。代表key已经存在。则使用incr进行自增即可。

    代码实现

    /**
     * 处理多次请求问题,限制指定时间内只能访问的次数
     */
    @Aspect
    @Component
    public class ReqLimitSAspect {
        @Autowired
        private RedisTemplate redisTemplate;
    
        @Around("@annotation(com.tute.edu.planetcommunity.annotation.ReqLmit)")
        public Object hanlderReqLimit(ProceedingJoinPoint point) {
            MethodSignature methodSignature = (MethodSignature) point.getSignature();
            ReqLmit annotation = methodSignature.getMethod().getAnnotation(ReqLmit.class);
            long count = annotation.count();
            int time = annotation.time();
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            //获取访问者的ip
            //获取访问的uri
            String requestURI = request.getRequestURI();
            String ipAddr = IpUtils.getIpAddr(request);
            String key = "req:limit:" + ipAddr + ":" + requestURI;
            Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(key, 1, time, TimeUnit.SECONDS);
            Long countIncr=0L;
            if (!aBoolean)   {
                 countIncr = redisTemplate.opsForValue().increment(key);
            }
            if (countIncr > count) {
                throw new CustomException("调用频繁,请稍后再试!");
            }
            try {
                return point.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            return null;
        }
    }
    
  • 相关阅读:
    【已解决】ERR_BLOCKED_BY_XSS_AUDITOR:Chrome 在此网页上检测到了异常代码:解决办法
    【已解决】Microsoft visual c++ 14.0 is required问题解决办法
    爬虫处理网站的bug---小于号未转化为实体符
    pymysql 在数据库中插入空值
    python 正则括号的使用及踩坑
    pymysql 解决 sql 注入问题
    python3 操作MYSQL实例及异常信息处理--用traceback模块
    LeetCode 837. 新21点 | Python
    LeetCode 面试题64. 求1+2+…+n | Python
    LeetCode 101. 对称二叉树 | Python
  • 原文地址:https://www.cnblogs.com/chaoba/p/16004004.html
Copyright © 2020-2023  润新知