创建自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimiter {
int value() default 1000;
}
实现自定义注解
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Aspect
public class RateLimiterAspect {
private final ConcurrentHashMap<String, Long> rateLimiterMap = new ConcurrentHashMap<>();
//切点
@Pointcut("@annotation(com.jsxy.activiti.utils.RateLimiter)")
public void rateLimiterPointCut() {
}
//环绕通知,用于在方法执行前进行限流判断。
@Around("rateLimiterPointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
//signature 方法签名
//method 方法对象
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
//获取自定义注解
RateLimiter rateLimiter = method.getAnnotation(RateLimiter.class);
int millis = rateLimiter.value();
String key = method.getDeclaringClass().getName() + "#" + method.getName();
//获取当前时间戳
long currentTimeMillis = System.currentTimeMillis();
Long lastTimeMillis = rateLimiterMap.putIfAbsent(key, currentTimeMillis);
//并且当前时间与上一次访问时间的差小于限流时间间隔,则抛出异常,否则更新`ratelimitermap`中的时间戳。
if (lastTimeMillis != null && (currentTimeMillis - lastTimeMillis) < millis) {
throw new RuntimeException("请求过于频繁,请稍后再试");
}
rateLimiterMap.put(key, currentTimeMillis);
return joinPoint.proceed();
}
}
在需要的方法上,添加注解,即可防止重复提交