一般的注解aop切面解决限流问题。

//自定义注解
@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){
    } }
    }

该方法只能在单机服务器中使用,如果使用分布式按照我上一篇文章进行操作

你可能感兴趣的:(java)