//自定义注解
@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyRateLimiter {
//向令牌桶放入令牌的速率
double rate();
//从令牌桶获取令牌的超时时间
long timeout() default 0;
}
//实现桶的限流和aop切面
@Aspect
@Component
public class MyRateLimiterAspect {
private RateLimiter rateLimiter = RateLimiter.create(2);
@Pointcut(“execution(public * com.test.limiter.controller..(…))”)
public void pointcut(){
}
/**
- 核心切面方法 */
@Around(“pointcut()”)
public Object process(ProceedingJoinPoint proceedingJoinPoint) throws
Throwable{
MethodSignature signature = (MethodSignature)
proceedingJoinPoint.getSignature();
//使用反射获取方法上是否存在@MyRateLimiter注解
MyRateLimiter myRateLimiter =
signature.getMethod().getDeclaredAnnotation(MyRateLimiter.class);
if(myRateLimiter == null){ //程序正常执行,执行目标方法
return proceedingJoinPoint.proceed();
}
//获取注解上的参数
//获取配置的速率
double rate = myRateLimiter.rate(); //获取客户端等待令牌的时间
long timeout = myRateLimiter.timeout();
//设置限流速率 rateLimiter.setRate(rate);
//判断客户端获取令牌是否超时
boolean tryAcquire = rateLimiter.tryAcquire(timeout,
TimeUnit.MILLISECONDS);
if(!tryAcquire){ //服务降级
fullback();
return null;
}
//获取到令牌,直接执行
return proceedingJoinPoint.proceed();
}
/**
- 降级处理 */
private void fullback() {
response.setHeader(“Content-type”, “text/html;charset=UTF-8”);
PrintWriter writer = null;
try {
writer = response.getWriter(); writer.println(“出错了,请重新刷新?”); writer.flush();;
} catch (IOException e) {
e.printStackTrace();
}finally {
if(writer != null){
} }
}
该方法只能在单机服务器中使用,如果使用分布式按照我上一篇文章进行操作