依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
代码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FrequencyLimit {
long time() default 60000L;
int frequency() default 5;
}
@Aspect
@Component
public class FrequencyLimitAspect {
private static final Map<String, List<Long>> ACCESS_RECORD = new ConcurrentHashMap<>();
@Around("@annotation(limit)")
public Object around(ProceedingJoinPoint joinPoint, FrequencyLimit limit) throws Throwable {
String methodName = joinPoint.getSignature().toLongString();
Object[] args = joinPoint.getArgs();
long time = limit.time();
int frequency = limit.frequency();
if (!checkAccessFrequency(methodName, time, frequency)) {
throw new RuntimeException("请求太频繁,请稍后再试");
}
return joinPoint.proceed(args);
}
private boolean checkAccessFrequency(String methodName, long time, int frequency) {
long now = System.currentTimeMillis();
List<Long> accessList = ACCESS_RECORD.get(methodName);
if (accessList == null) {
accessList = new ArrayList<>();
ACCESS_RECORD.put(methodName, accessList);
}
accessList.add(now);
while (!accessList.isEmpty() && now - accessList.get(0) > time) {
accessList.remove(0);
}
return accessList.size() <= frequency;
}
}
使用
@FrequencyLimit(frequency = 5, time = 60000L)
@PostMapping("/update")
public R<?> update(@RequestBody ArticleBo articleBo) {
articleService.update(articleBo);
return R.ok(null, "修改成功");
}