限流可以使用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() {@Overridepublic 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<>();@Overridepublic 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();// 多少时间后清除maplong delay = rateLimiter.time();timer.schedule(new TimerTask() {@Overridepublic 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;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}}