springboot AOP + ConcurrentHashMap 接口调用频率限制实现
时间: 2023-10-14 08:20:24 浏览: 125
实现接口调用频率限制可以使用AOP和ConcurrentHashMap结合的方式。
首先,在Spring Boot中,我们可以使用AOP来拦截接口的调用。我们可以定义一个切面,使用@Aspect注解标注,然后在切入点方法中定义需要拦截的注解。
例如,我们可以定义一个@FrequencyLimit注解,用于标注需要限制调用频率的方法:
```java
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface FrequencyLimit {
// 限制时间段,单位为秒
int interval() default 60;
// 时间段内最大请求次数
int maxCount() default 10;
}
```
然后,在切面中,我们可以拦截该注解标注的方法,并且进行限制调用频率的操作。可以使用ConcurrentHashMap来存储每个接口的调用次数和最后一次调用时间。
```java
@Component
@Aspect
public class FrequencyLimitAspect {
private ConcurrentHashMap<String, Long> lastRequestTimeMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Integer> requestCountMap = new ConcurrentHashMap<>();
@Around("@annotation(frequencyLimit)")
public Object frequencyLimit(ProceedingJoinPoint joinPoint, FrequencyLimit frequencyLimit) throws Throwable {
Object result = null;
String methodName = joinPoint.getSignature().toLongString();
long currentTime = System.currentTimeMillis();
int interval = frequencyLimit.interval();
int maxCount = frequencyLimit.maxCount();
synchronized (this) {
// 获取最后一次请求时间和请求次数
Long lastRequestTime = lastRequestTimeMap.get(methodName);
Integer requestCount = requestCountMap.get(methodName);
if (lastRequestTime == null || currentTime - lastRequestTime >= interval * 1000) {
// 如果该接口在限制时间段内没有被调用过,则重置请求次数和最后一次请求时间
lastRequestTimeMap.put(methodName, currentTime);
requestCountMap.put(methodName, 1);
} else {
// 如果该接口在限制时间段内已经被调用过,则增加请求次数
requestCount++;
if (requestCount > maxCount) {
// 如果请求次数超过了限制,则抛出异常
throw new RuntimeException("Exceeded maximum request limit");
}
lastRequestTimeMap.put(methodName, currentTime);
requestCountMap.put(methodName, requestCount);
}
}
// 调用原始方法
result = joinPoint.proceed();
return result;
}
}
```
在切面中,我们使用synchronized关键字来保证线程安全,因为ConcurrentHashMap并不能完全保证线程安全。同时,我们使用了@Around注解来拦截被@FrequencyLimit注解标注的方法,然后在方法中实现限制调用频率的逻辑。
这样,我们就可以实现接口调用频率限制了。在需要限制调用频率的方法中,我们只需要加上@FrequencyLimit注解即可。例如:
```java
@GetMapping("/test")
@FrequencyLimit(interval = 60, maxCount = 10)
public String test() {
return "test";
}
```
这样,每个IP地址每分钟内最多只能调用该方法10次,超过次数会抛出异常。
阅读全文