Skip to content

背景: 针对某个接口, 某个时间节点或某个人做接口的请求限制

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);  
            }
        }
    }
}

waitingresult.com