一、代码实现
1.引入依赖
<!-- springboot 整合web组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 谷歌限流jar -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.自定义注解 CurrentLimitingAnnotation
/**
* 自定义限流注解
* @author sean
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentLimitingAnnotation {
/**
* 限流名称
* @return
*/
String name() default "";
/**
* 每秒限制访问次数
* @return
*/
double token() default 5;
}
3.接口测试
/**
* @Author : sean
* @DateTime : 2021/7/28、21:30
* @Description :
**/
@RestController
public class AopController {
/**
* CurrentLimitingAnnotation token默认是5秒,这里设置1秒
* @return
*/
@GetMapping("/add")
@CurrentLimitingAnnotation(name = "add", token = 1)
public String add() {
System.out.println("add.............");
return "success";
}
}
4.AOP 拦截注解实现限流
/**
* @Author : sean
* @DateTime : 2021/7/28、21:35
* @Description : 全局拦截限流注解
**/
@Aspect
@Component
public class CurrentLimitingAop {
private ConcurrentHashMap<String, RateLimiter> rateLimiterConcurrentHashMap = new ConcurrentHashMap<>();
@Around(value = "@annotation(com.sean.satoken.annotations.CurrentLimitingAnnotation)")
public Object around(ProceedingJoinPoint joinPoint) {
try {
// 获取拦截的方法名
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
// 获取该方法的注解 CurrentLimitingAnnotation
CurrentLimitingAnnotation currentLimitingAnnotation =
methodSignature.getMethod().getDeclaredAnnotation(CurrentLimitingAnnotation.class);
//获取到注解的name,token
String name = currentLimitingAnnotation.name();
double token = currentLimitingAnnotation.token();
//判断改名称是否有创建rateLimiter 没有则创建,有则拿来用
RateLimiter rateLimiter = rateLimiterConcurrentHashMap.get(name);
if (rateLimiter == null) {
rateLimiterConcurrentHashMap.put(name, RateLimiter.create(token));
}
if (!rateLimiter.tryAcquire()) {
return "请求过于频繁,请稍后再试";
}
return joinPoint.proceed();
} catch (Throwable throwable) {
return "系统错误!";
}
}
}
5.启动类
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
6.测试
访问接口 ip:port/add,当前接口token设置了1秒,如果一秒内多次访问 return ”请求过于频繁,请稍后再试“