1.创建AccessLimit注解,second和maxCount用于限流,loginRequired用于判断请求是否需要用户登录
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {
int second() default 0;
int maxCount() default 0;
boolean loginRequired() default true;
}
2.实现WebMvcConfigurer 加上Configuration注解 添加放行和拦截 放行自己加
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Bean
public MyInterceptor myInterceptor() {
return new MyInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
String[] addPath = {"/**"};
registry.addInterceptor(myInterceptor()).addPathPatterns(addPath);
}
}
3.没啥好说的
public class MyInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Autowired
private RedisTemplate redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
AccessLimit accessLimit = method.getAnnotation(AccessLimit.class);
ReturnPage returnPage = method.getAnnotation(ReturnPage.class);
if (accessLimit == null) { //无限制
return true;
}
ValueOperations valueOperations = redisTemplate.opsForValue();
int second = accessLimit.second();
int maxCount = accessLimit.maxCount();
boolean loginRequired = accessLimit.loginRequired();
if (!loginRequired) { //不需要登录 放行
return true;
}
String uid = JwtUtils.getUserIdByJwtToken(request);
User user = userService.getById(uid);
if (user == null) {
if (returnPage == null) {
throw new GlobalException(20002, "操作异常,请重新登录");
} else {
response.sendRedirect("/login");
return false;
}
}
if (maxCount == 0 || second == 0) { //不限流
return true;
}
String uri = request.getRequestURI();
String key = uri + "::" + uid;
Integer count = (Integer) valueOperations.get(key);
if (count == null) {
valueOperations.set(key, 1, second, TimeUnit.SECONDS);
} else if (count < maxCount) {
valueOperations.increment(key);
} else {
throw new GlobalException(20001, "操作频繁,请稍后再试");
}
return true;
}
}
此时带有@AccessLimit的函数就会被拦截了 比如下面这个
@AccessLimit
@ResponseBody
@PostMapping("purchase/{id}")
public R purchaseGoods(@PathVariable String id, Integer num, HttpServletRequest request) {
String uid = JwtUtils.getUserIdByJwtToken(request);
.
.
.
return R.ok().data("oid", order.getId());
}