背景: 针对某个接口, 某个时间节点或某个人做接口的请求限制
Redisutils 获取锁的逻辑同 Redisson
java
import java.lang.annotation.*;
/**
* @Author: WangShuai
* @CreateTime: 2022-10-26 15:51
* @Description: 接口防抖注解
* @Version: 1.0
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AntiShake {
/**
* 锁key
*/
String lockKey();
/**
* 请求锁定时间 单位秒
*/
int lockTime() default 2;
/**
* 是否在aop方法执行完毕后释放锁,默认释放。为false时,需要自行处理释放锁的逻辑或等待锁过期
*/
boolean releaseLock() default true;
}
AOP 逻辑实现
java
import cn.hutool.core.util.IdUtil;
import com.waitingresult.freight.annotation.AntiShake;
import com.waitingresult.freight.common.exception.base.BusinessException;
import com.waitingresult.freight.common.utils.RedisLockUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
import static com.waitingresult.base.constants.CacheConstants.ANTI_SHAKE_PRE_KEY;
/**
* @Author: WangShuai
* @CreateTime: 2022-10-26 15:54
* @Description: 防抖的切面
* @Version: 1.0
*/
@Aspect
@Slf4j
@Component
public class AntiShakeAspect {
@Pointcut("@annotation(antiShake)")
public void antiShakeAspect(AntiShake antiShake) {
}
@Around(value = "antiShakeAspect(antiShake)", argNames = "point,antiShake")
public Object aspect(ProceedingJoinPoint point, AntiShake antiShake) throws Throwable {
int lockTime = antiShake.lockTime();
boolean releaseLock = antiShake.releaseLock();
String key = ANTI_SHAKE_PRE_KEY + antiShake.lockKey();
String uuidValue = IdUtil.randomUUID();
try {
boolean lock = RedisLockUtils.getLock(key, uuidValue, lockTime, TimeUnit.SECONDS);
Object proceed;
log.info("锁key: {},获取锁结果: {}", key, lock);
if (lock) {
proceed = point.proceed();
return proceed;
} else {
throw new BusinessException(500, "当前正在排队,请稍后重试~");
}
} finally {
if (releaseLock) {
RedisLockUtils.releaseLock(key, uuidValue);
}
}
}
}