接口限流防刷
思路:将访问次数放入缓存,key为URI+User ID
将这个通用方法,使用拦截器改造。
1.将目标方法加上注解
@AccessLimit(seconds=5, maxCount=5, needLogin=true)
2.新建注解
@Retention(RUNTIME)
@Target(METHOD)
public @interface AccessLimit {
int seconds();
int maxCount();
boolean needLogin() default true;
}
3.新建拦截器
@Service
public class AccessLimitInterceptor extends HandlerInterceptorAdapter {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
}
}
重写preHandler(),里面的主要逻辑是
先从request里拿取token,根据这个token从redis里拿到UserInfo;
******
这里将userinfo放入到ThreadLocal<MiaoshaUser> userHolder,因为接下来的UserArgumentResolver可以直接从userHolder获取userinfo,数据共享
******
扫描所有被@AccessLimit注解的方法,没有直接返回true;
获取注解参数seconds, maxCount, needLogin;
如果needLogin==true,但是userinfo==null, 写入错误信息到response的outputstream,返回false,
根据key拿到当前的count,判断count==null,小于maxCount,否则返回false
4.注册拦截器
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
。。。
@Autowired AccessLimitInterceptor accessLimitInterceptor;
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(accessLimitInterceptor);
}
}