限流可以使用redis的过期时间自动过期限流的key,,
也可以使用一个定时器,在指定时间后清除这个key,,比如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);
}
写在拦截器里面,,拦截指定注解的controller接口
拦截器里面有个handler 转换成 HandlerMethod
handlerMethod.getMethodAnnotation() 获取这个方法上的注解
将拦截到的注解,进行判断是否需要限流,,
String.format()
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);
}
}