定义接口访问频率注解
/**
* 接口访问频率注解,默认一分钟只能访问60次
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLimit {
// 限制时间 单位:秒(默认值:一分钟)
long period() default 60;
// 允许请求的次数(默认值:60次)
long count() default 60;
}
定义切点和处理逻辑,这里使用了redis进行计数
@Aspect
@Component
@Log4j2
public class RequestLimitAspect {
@Autowired
private RedisUtil redisUtil;
// 切点
@Pointcut("@annotation(requestLimit)")
public void controllerAspect(RequestLimit requestLimit) {
}
@Around("controllerAspect(requestLimit)")
public Object doAround(ProceedingJoinPoint joinPoint, RequestLimit requestLimit) throws Throwable {
// get parameter from annotation
long period = requestLimit.period();
long limitCount = requestLimit.count();
String key = "requestLimit";
Object countStr = redisUtil.get(key);
if (countStr == null) {
redisUtil.set(key, "1",period);
return joinPoint.proceed();
} else {
int count = Integer.parseInt(String.valueOf(countStr));
if (count >= limitCount) {
log.error("接口拦截:请求超过限制频率");
return HyResponse.fail("超过请求次数,请一分钟后再次请求!");
}else {
redisUtil.set(key, String.valueOf(count + 1), period);
return joinPoint.proceed();
}
}
}
}
最后直接在需要限制的请求接口上加上@RequestLimit注解
@RequestLimit(count = 60)
@GetMapping("/test")
public HyResponse test() {
return HyResponse.success();
}
RedisUtil工具类
import java.util.*;
import java.util.concurrent.TimeUnit;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
public class RedisUtil {
private RedisTemplate<String, Object> redisTemplate;
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
// =============================common============================
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key)