1.添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
启动类上添加注解
@EnableAspectJAutoProxy(proxyTargetClass=true)
2.AOP类
/**
* @author xionghu
* @date 2020/6/13 10:32
* @desc 配置限流切面
*/
@Aspect
@Scope
@Component
public class RateLimiterAspect {
private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
private final ConcurrentMap<String, RateLimiter> RATE_LIMITER_CACHE = new ConcurrentHashMap<>();
@Pointcut(value = "@annotation(com.ihuaben.bridge.web.ratelimiter.ApiRateLimiter)")
public void rateLimit() {
}
@Around("rateLimit()")
public Object pointcut(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
// 通过 AnnotationUtils.findAnnotation 获取 RateLimiter 注解
ApiRateLimiter rateLimiter = AnnotationUtils.findAnnotation(method, ApiRateLimiter.class);
if (rateLimiter == null) {
return point.proceed();
}
if (rateLimiter.qps() > ApiRateLimiter.NOT_LIMITED) {
double qps = rateLimiter.qps();
if (RATE_LIMITER_CACHE.get(method.getName()) == null) {
// 初始化 QPS
RATE_LIMITER_CACHE.put(method.getName(), RateLimiter.create(qps));
}
log.debug("[{}]的QPS设置为: {}", method.getName(), RATE_LIMITER_CACHE.get(method.getName()).getRate());
// 尝试获取令牌
if (RATE_LIMITER_CACHE.get(method.getName()) != null && !RATE_LIMITER_CACHE.get(method.getName()).tryAcquire(rateLimiter.timeout(), rateLimiter.timeUnit())) {
throw new BusinessException(EmBusinessError.RATELIMIT);
}
}
return point.proceed();
}
}
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
/**
* @author xionghu
* @date 2020/6/13 10:32
* @desc 创建限流限制
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiRateLimiter {
int NOT_LIMITED = 0;
/**
* qps
*/
@AliasFor("qps") double value() default NOT_LIMITED;
/**
* qps
*/
@AliasFor("value") double qps() default NOT_LIMITED;
/**
* 超时时长
* 默认间隔1s时间
*/
int timeout() default 1000;
/**
* 超时时间单位
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}
3.AOP类
@RestController
@RequestMapping({ "/admin" })
public class TestController extends BaseController {
@RequestMapping({ "/hello" })
@ApiRateLimiter(value = 5)
public ResponseEntity hello(String name) {
System.out.println("................");
return buildResponseEntity("word","hello " + name);
}
@RequestMapping({ "/Permission" })
public ResponseEntity Permission(String name) {
return buildResponseEntity("word","Permission " + name);
}
}
限制1秒钟 只能 有五个请求才能走方法
验证
image.png