• java限流


    限流可以使用redis的过期时间自动过期限流的key,,
    也可以使用一个定时器,在指定时间后清除这个key,,比如Timer

    Timer的使用
    Timer timer = new Timer()
    timer.schedule(timerTast,delay,period)  
    
    • 1
    • 2
        public static void main(String[] args) {
            Timer timer = new Timer();
    
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    System.out.println("111");
                }
            }, 1000, 2000);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    springboot中限流

    写在拦截器里面,,拦截指定注解的controller接口

    • 怎么在拦截器中获取controller层的方法
    拦截器里面有个handler  转换成 HandlerMethod 
    handlerMethod.getMethodAnnotation()   获取这个方法上的注解
    
    • 1
    • 2

    将拦截到的注解,进行判断是否需要限流,,

    • 格式化字符串
    String.format()
    
    • 1
    • HttpServletResponse返回json给前端
    response.setCharacterEncoding("uft-8");
    response.contentType("application/json;charset=utf-8");
    response.getWriter.write()
    
    • 1
    • 2
    • 3
    public class RateLimiterInterceptor implements HandlerInterceptor {
    
        private final Map<String,Integer> map = new HashMap<>();
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            if (handler instanceof HandlerMethod){
                HandlerMethod handlerMethod = (HandlerMethod) handler;
    
    
                RateLimiter rateLimiter = handlerMethod.getMethodAnnotation(RateLimiter.class);
                if (rateLimiter == null){
                    return true;
                }
    
    
    
                String methodName = handlerMethod.getMethod().getName();
    
                boolean limit = this.isLimit(request, rateLimiter, methodName);
                if (limit){
                    this.responseOut(response,rateLimiter,methodName);
                    return  false;
                }
                System.out.println("methodName = " + methodName);
            }
            return HandlerInterceptor.super.preHandle(request, response, handler);
    //        return true;
        }
    
        /**
         * 限流后的输出
         */
        private  void responseOut(HttpServletResponse response,RateLimiter rateLimiter,String methodName){
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/json;charset=utf-8");
    
            String format = String.format("%s %d毫秒内访问次数为%d,已经超过最大访问次数,请稍后访问", methodName, rateLimiter.time(), rateLimiter.count());
    
    
            UnifyResponse unifyResponse = new UnifyResponse(500, format, null);
            try {
                String r = new ObjectMapper().writeValueAsString(unifyResponse);
                response.getWriter().write(r);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 是否限流
         */
        private boolean isLimit(HttpServletRequest request,RateLimiter rateLimiter,String methodName){
            String ipAddr = request.getRemoteAddr();
            String key = ipAddr+"-"+methodName;
    //        System.out.println("key = " + key);
            System.out.println("map = " + map);
            Integer number = map.get(key);
            if (number == null){
                // 第一次访问
                Timer timer = new Timer();
                // 多少时间后清除map
                long delay = rateLimiter.time();
    
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        System.out.println("删除任务执行");
                        map.remove(key);
                    }
                },delay);
                // 初始化计数器
                map.put(key,1);
            }else{
                number++;
    
                if (number > rateLimiter.count()){
                    // 超过最大限流
                    return true;
                }
                map.put(key,number);
            }
    
            return false;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        }
    
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
  • 相关阅读:
    使用JSZip实现在浏览器中操作文件与文件夹
    Spring Cloud之API网关(Gateway)
    LeetCode刷题---简单组(四)
    Redis的发布订阅功能教程,实现实时消息和key过期事件通知功能
    java-BigDecimal 用法注意事项
    ctf之流量分析学习
    Chrome插件精选 — 暗色主题插件
    jdbc 数据源(DruidDataSourceFactory)连接池 —— druid
    HNU计网实验:实验四 应用层和传输层协议分析(PacketTracer)
    Swift 高阶函数详解(forEach、filter、map、flatMap、compactMap、reduce、sorted)
  • 原文地址:https://blog.csdn.net/qq_36022463/article/details/133547944