Java 使用 Hutool + 自定义注解 + Spring AOP 实现接口限流
- 首先,我们需要引入 Hutool 和 AOP 的依赖。
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
- 定义一个注解
@RateLimit,用于标记需要限流的方法。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {
int limit() default 10; // 限流次数,默认为 10 次
long time() default 60; // 限流时间,默认为 60 秒
}
- 在 AOP 中实现对
@RateLimit注解的解析,并进行限流。
@Aspect
@Component
public class RateLimitAspect {
private static final Map<String, AccessCounter> COUNTER_MAP = new ConcurrentHashMap<>();
@Around("@annotation(rateLimit)")
public Object around(ProceedingJoinPoint point, RateLimit rateLimit) throws Throwable {
String methodName = point.getSignature().toShortString();
AccessCounter counter = COUNTER_MAP.get(methodName);
if (counter == null) {
counter = new AccessCounter(rateLimit.limit(), rateLimit.time());
COUNTER_MAP.put(methodName, counter);
}
if (counter.tryAcquire()) {
return point.proceed();
} else {
throw new RuntimeException("接口访问频率超过限制!");
}
}
private static class AccessCounter {
private final int limit;
private final long timeWindow;
private final Queue<Long> timestamps;
public AccessCounter(int limit, long timeWindow) {
this.limit = limit;
this.timeWindow = timeWindow * 1000;
this.timestamps = new LinkedList<>();
}
public boolean tryAcquire() {
long now = System.currentTimeMillis();
while (!timestamps.isEmpty() && timestamps.peek() < now - timeWindow) {
timestamps.poll();
}
if (timestamps.size() < limit) {
timestamps.offer(now);
return true;
} else {
return false;
}
}
}
}
- 在需要进行限流的接口方法上加上
@RateLimit注解即可。
@RestController
public class TestController {
@RateLimit(limit = 5, time = 60)
@GetMapping("/test")
public String test() {
return "Hello World!";
}
}
以上就是 Java 使用 Hutool + 自定义注解 + Spring AOP 实现对接口限流的方法。
原文地址: https://www.cveoy.top/t/topic/njqD 著作权归作者所有。请勿转载和采集!