1.对请求的接口做了一个限流的控制,
2.利用到:AOP,redis,定时器;
3.在请求的congtroller层上加相应的注解就可以;
具体的Demo工程如下
package com.weigu.xiaochuang.project; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.util.Map; import java.util.Timer; import java.util.TimerTask; //https://blog.csdn.net/befroe_You/article/details/83748927 @Aspect @Component @Slf4j public class RequestLimitContract { private Map<String, Integer> redisTemplate = Maps.newHashMap(); @Before("within(@org.springframework.stereotype.Controller *)&& @annotation(limit)") public void requestLimit(final JoinPoint joinPoint, RequestLimit limit) throws RequestLimitException { try { Object[] args = joinPoint.getArgs(); HttpServletRequest request = null; for (int i = 0; i < args.length; i++) { if (args[i] instanceof HttpServletRequest) { request = (HttpServletRequest) args[i]; break; } } /** * 将请求参数转变为request */ if (request == null) { throw new RequestLimitException("方法中缺失HttpServletRequest参数"); } String ip = request.getLocalAddr(); String url = request.getRequestURI().toString(); String key = "req_limit".concat(ip).concat(url); if (redisTemplate.get(key) == null || redisTemplate.get(key) == 0) { redisTemplate.put(key, 1); } else { redisTemplate.put(key, redisTemplate.get(key) + 1); } Integer count = redisTemplate.get(key); if (count > 0) { //创建一个定时器 Timer timer = new Timer(); TimerTask timerTask = new TimerTask() { @Override public void run() { redisTemplate.remove(key); } }; //这个定时器设定在time规定的时间之后会执行上面的remove方法,也就是说在这个时间后它可以重新访问 timer.schedule(timerTask, limit.time()); } if (count > limit.count()) { log.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]"); throw new RequestLimitException(); } }catch (RequestLimitException e){ throw e; }catch (Exception e){ } } }
package com.weigu.xiaochuang.project; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented @Order(Ordered.HIGHEST_PRECEDENCE) public @interface RequestLimit { /** * 允许访问最大次数 */ int count() default Integer.MAX_VALUE; /** * 时间段 */ long time() default 6000; }
package com.weigu.xiaochuang.project; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; @Controller public class testController { @RequestMapping("/hello") @RequestLimit(count = 4, time = 60000) public String test(HttpServletRequest request) { return "hello1111"; } }