
使用技术:Spring AOP、自定义注解、Redis
我们可以先定义注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {
// 限流标识
String key() default "";
// 限制次数
int limit();
// 时间窗口(秒)
int window();
}然后定义对应的切面:
@Aspect
@Component
public class RateLimitAspect {
@Resource
private StringRedisTemplate redisTemplate;
@Around("@annotation(rateLimit)")
public Object limit(ProceedingJoinPoint joinPoint, RateLimit rateLimit) {
String key = buildKey(joinPoint, rateLimit);
int limit = rateLimit.limit();
int window = rateLimit.window();
Long count = redisTemplate.opsForValue().increment(key);
if (count == 1) {
// 第一次访问,设置过期时间
redisTemplate.expire(key, Duration.ofSeconds(window));
}
if (count != null && count > limit) {
// 限流后如何处理则根据实际情况来 比如这里可以抛出异常终止请求
}
return joinPoint.proceed();
}
private String buildKey(ProceedingJoinPoint joinPoint, RateLimit rateLimit) {
// 可根据实际情况 如用户ID 用户IP等拼接
String prefix = "rate_limit:";
return prefix + rateLimit.key();
}
}最后就可以在controller里使用了:
@GetMapping("/test")
@RateLimit(key = "test", limit = 5, window = 60)
public String test() {
return "OK";
}原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。