1.redis接口限流注解
定义一个注解标明需要使用限流的接口
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AccessLimit {/*** @return 单位时间(秒)*/int seconds();/*** @return 单位时间最大请求次数*/int maxCount();
}
2.配置拦截器
在springboot的拦截器中,如果你没有配置拦截器,需要自定义类继承HandlerInterceptor,
@Log4j2
public class WebSecurityHandler implements HandlerInterceptor {@Autowiredprivate RedisService redisService;@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {//如果请求输入方法if (handler instanceof HandlerMethod) {HandlerMethod hm = (HandlerMethod) handler;//获取方法中的注解,看是否有该注解AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);if (accessLimit != null) {long seconds = accessLimit.seconds();int maxCount = accessLimit.maxCount();//关于key的生成规则可以自己定义 本项目需求是对每个方法都加上限流功能,如果你只是针对ip地址限流,那么key只需要只用ip就好String key = IpUtils.getIpAddress(httpServletRequest) + hm.getMethod().getName();//从redis中获取用户访问的次数try {//此操作代表获取该key对应的值自增1后的结果long q = redisService.incrExpire(key, seconds);if (q > maxCount) {render(httpServletResponse, Result.ok(null, "请求过于频繁,请稍候再试"));log.warn(key + "请求次数超过每" + seconds + "秒" + maxCount + "次");return false;}return true;} catch (RedisConnectionFailureException e) {log.warn("redis错误: " + e.getMessage());return true;}}}return false;}private void render(HttpServletResponse response, Result<?> result) throws Exception {response.setContentType("application/json;charset=UTF-8");OutputStream out = response.getOutputStream();String str = JSON.toJSONString(result);out.write(str.getBytes("UTF-8"));out.flush();out.close();}
}
3.测试注解
@AccessLimit(seconds = 10, maxCount = 2)
访问受限测试
redis信息
后台打印信息