java限流

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

Timer的使用
Timer timer = new Timer()
timer.schedule(timerTast,delay,period)  
    public static void main(String[] args) {
        Timer timer = new Timer();

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("111");
            }
        }, 1000, 2000);
    }
springboot中限流

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

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

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

  • 格式化字符串
String.format()
  • HttpServletResponse返回json给前端
response.setCharacterEncoding("uft-8");
response.contentType("application/json;charset=utf-8");
response.getWriter.write()
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);
    }



}

你可能感兴趣的:(java,开发语言)