首页 > 其他 > 详细

使用guava实现接口限流

时间:2021-07-23 11:07:00      阅读:39      评论:0      收藏:0      [点我收藏+]

使用guava实现接口限流

依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.3.5.RELEASE</version>
       <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <modelVersion>4.0.0</modelVersion>
?
   <artifactId>apiLimit</artifactId>
?
   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <dependency>
           <groupId>com.google.guava</groupId>
           <artifactId>guava</artifactId>
           <version>30.1.1-jre</version>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-aop</artifactId>
       </dependency>
       <dependency>
           <groupId>org.aspectj</groupId>
           <artifactId>aspectjweaver</artifactId>
           <version>1.9.1</version>
       </dependency>
   </dependencies>
</project>

限流注解

package com.cyz.annocation;
?
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
?
/**
* @Author lian-chen
* @Date 2021/7/23 8:19
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLianChenLimit {
   /**
    * 限流的名称
    *
    * @return
    */
   String name() default "";
?
   /**
    * 限制次数 每秒
    */
   double token() default 20;
}

AOP通知

package com.cyz.aop;
?
import com.cyz.annocation.MyLianChenLimit;
import com.google.common.util.concurrent.RateLimiter;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
?
import java.util.concurrent.ConcurrentHashMap;
?
/**
* @Author lian-chen
* @Date 2021/7/23 8:25
*/
@Aspect
@Component
public class CurrentLimitAop {
?
   /**
    * 存放每一个方法对应的 RateLimiter
    */
   private ConcurrentHashMap<String, RateLimiter> rateLimiterMap = new ConcurrentHashMap<>();
?
   @Before(value = "@annotation(com.cyz.annocation.MyLianChenLimit)")
   public void before() {
       System.out.println("前置通知......");
  }
?
   /**
    * 只要方法上有加上自定义的限流注解,就会被aop环绕通知
    *
    * @param joinPoint 切入点
    * @return
    */
   @Around(value = "@annotation(com.cyz.annocation.MyLianChenLimit)")
   public Object around(ProceedingJoinPoint joinPoint) {
       /**
        * 拦截目标方法
        */
       try {
           /**
            * 获取拦截的方法名
            */
           Signature signature = joinPoint.getSignature();
           MethodSignature methodSignature = (MethodSignature) signature;
?
           /**
            * 获取方法注解的参数
            */
           MyLianChenLimit myLianChenLimit = methodSignature.getMethod().getDeclaredAnnotation(MyLianChenLimit.class);
           String name = myLianChenLimit.name();
           double token = myLianChenLimit.token();
?
           /**
            * 获取或创建对应的 RateLimiter
            */
           RateLimiter rateLimiter = rateLimiterMap.get(name);
           if (rateLimiter == null) {
               /**
                * 没秒生成对应个数的token
                */
               rateLimiter = RateLimiter.create(token);
               rateLimiterMap.put(name, rateLimiter);
          }
?
           System.out.println("环绕通知开始执行。。。。。");
           /**
            * 限流控制
            */
           boolean b = rateLimiter.tryAcquire();
           if (!b) {
               System.out.println("限制访问.....");
               return "访问人数过多,请稍后访问.....";
          }
           /**
            * 执行目标方法 返回目标方法结果
            */
           Object result = joinPoint.proceed();
           System.out.println("环绕通知结束执行。。。。。");
?
           return result;
      } catch (Throwable throwable) {
           return "系统异常";
      }
  }
?
   @After(value = "@annotation(com.cyz.annocation.MyLianChenLimit)")
   public void after() {
       System.out.println("后置通知......");
  }
}

接口

package com.cyz.controller;
?
import com.cyz.annocation.MyLianChenLimit;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
?
/**
* @Author lian-chen
* @Date 2021/7/22 8:44
*/
@RestController
public class TestController {
?
   @MyLianChenLimit(name = "get",token = 2)
   @GetMapping("/get")
   public String get(){
       System.out.println("get目标方法执行。。。");
       return "hello get";
  }
?
   @MyLianChenLimit(name = "add",token = 10)
   @GetMapping("/add")
   public String add(){
       System.out.println("add目标方法执行。。。");
       return "hello add";
  }
}

启动类

package com.cyz;
?
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
?
/**
* @Author lian-chen
* @Date 2021/7/22 8:45
*/
?
@SpringBootApplication
public class App {
   public static void main(String[] args) {
       SpringApplication.run(App.class,args);
  }
}
?

 

使用guava实现接口限流

原文:https://www.cnblogs.com/liang-chen-fly/p/15047358.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!