创建一个限流注解
package com.hhc.analysis.config.annotation;
import com.hhc.analysis.common.constant.CacheConstants;
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
/**
* 限流注解
*
* @author ruoyi
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter
{
/**
* 限流key
*/
public String key() default CacheConstants.RATE_LIMIT_KEY;
/**
* 限流时间
*/
public int time() default 1;
/**
* 限流次数(最大访问次数)
*/
public int count() default 5;
/**
* 时间单位,默认秒
*/
TimeUnit timeUnit() default TimeUnit.SECONDS;
}
创建一个切面类
package com.hhc.analysis.config.aspectj;
import com.hhc.analysis.common.constant.ErrorConstants;
import com.hhc.analysis.common.exception.AIDocException;
import com.hhc.analysis.config.annotation.RateLimiter;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* 限流处理
*
* @author ruoyi
*/
@Aspect
@Component
public class RateLimiterAspect
{
private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
@Autowired
private RedisTemplate redisTemplate;
/**
* 定义切点为注解
*/
@Pointcut("@annotation(com.hhc.analysis.config.annotation.RateLimiter)")
public void AccessLimitPointcut(){
}
@Before(value = "AccessLimitPointcut()")
public void handleAccessLimit(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
RateLimiter annotation = AnnotationUtils.findAnnotation(method, RateLimiter.class);
int accessMaxTimes = annotation.count();
long timeOut = annotation.time();
TimeUnit timeUnit = annotation.timeUnit();
String key = annotation.key();
// 如果redis不存在或已经过期
Long expire = redisTemplate.opsForValue().getOperations().getExpire(key);
if (!redisTemplate.hasKey(key) || Objects.requireNonNull(expire).intValue() < 0) {
redisTemplate.opsForValue().set(key, 1, timeOut, timeUnit);
} else {
long increment = redisTemplate.opsForValue().increment(key).intValue();
if (increment > accessMaxTimes) {
throw new AIDocException(ErrorConstants.INVOKE_LIMIE, "1分钟内只能请求 " + accessMaxTimes+"次,请稍后尝试!");
}
}
}
}
在调用的接口上加上@RateLimiter 就实现啦