使用注解形式,进行接口的动态限流配置
添加依赖项
<!-- springboot 整合web组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
编写注解ApiLimit
package com.test.config.limit;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiLimit {
/**
* 名称
* @return
*/
String name();
/**
* 限速每秒生成token数量
* @return
*/
double token() default 1.0;
}
编写ApiLimitAspect
package com.test.config.limit;
import com.google.common.util.concurrent.RateLimiter;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@Aspect
@Component
public class ApiLimitAspect {
protected Logger logger = LoggerFactory.getLogger(getClass());
private ConcurrentHashMap<String, RateLimiter> rateLimiters = new ConcurrentHashMap();
@Pointcut("@annotation(com.test.config.limit.ApiLimit)"
+ "|| @within(com.test.config.limit.ApiLimit)")
public void dsPointCut() {
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
ApiLimit apiLimit = getApiLimit(point);
if (Objects.nonNull(apiLimit)){
// 获取注解上的name
String name = apiLimit.name();
// 获取注解上的token
double token = apiLimit.token();
RateLimiter rateLimiter = rateLimiters.get(name);
if (rateLimiter == null) {
rateLimiter = RateLimiter.create(token);
rateLimiters.put(name, rateLimiter);
}
// 开始限流
boolean result = rateLimiter.tryAcquire();
if (!result) {
return "当前访问人数过多,请稍后重试!";
}
}
return point.proceed();
}
/**
* 获取限速注解
*/
public ApiLimit getApiLimit(ProceedingJoinPoint point) {
MethodSignature signature = (MethodSignature) point.getSignature();
ApiLimit apiLimit = AnnotationUtils.findAnnotation(signature.getMethod(), ApiLimit.class);
if (Objects.nonNull(apiLimit)) {
return apiLimit;
}
return AnnotationUtils.findAnnotation(signature.getDeclaringType(), ApiLimit.class);
}
}
在使用的方法或类型添加限速注解
@GetMapping("/add")
@ApiLimit(name = "add", token = 5)
public String add() {
return "my is add";
}
评论区