反射和自定义注解实战案例

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


前言

写该文章的目的主要复习一些注解和反射的内容同时也让大家理解一下框架中这两样技术是如何运用的。


提示以下是本篇文章正文内容下面案例可供参考

一、反射API

  • Class类代表类的实体在运行的Java应用程序中表示类和接口
  • Field类代表类的成员变量成员变量也称为类的属性
  • Method类代表类的方法
  • Constructor类代表类的构造方法
  1. getField、getMethod和getCostructor方法可以获得指定名字的域、方法和构造器。
  2. getFields、getMethods和getCostructors方法可以获得类提供的public域、方法和构造器数组其中包括超类的共有成员。
  3. getDeclatedFields、getDeclatedMethods和getDeclaredConstructors方法可以获得类中声明的全部域、方法和构造器其中包括私有和受保护的成员但不包括超类的成员。

二、接口限流实战案例

该实战案例是通过使用谷歌的guavay与自定义注解相结合来实现接口限流。

1导入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
    </dependencies>

2.自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CzxLimit {
    /**
     * name 限流的名称
     *
     * @return
     */
    String name() default "";

    /**
     * 每s 能够允许访问的次数 10 底层
     * 令牌桶
     *
     * @return
     */
    double token() default 10;
}

说明

  1. token参数可以理解为该接口每秒最多可以访问几次。

3.定义控制层

@RestController
public class TestController {

    @GetMapping("/get")
    @CzxLimit(name = "get", token = 1)
    public String get() {
        return "get接口限制一秒钟登录一次";
    }

    @GetMapping("/add")
    @CzxLimit(name = "add")
    public String add() {
        return "add接口限制一秒钟登录10次不填默认10次";
    }

    @GetMapping("/push")
    public String push() {
        return "push接口无限制";
    }
}

说明

  1. 控制层我们定义了三个方法,并在get()和add()方法上加入了自定义注解说明get()该接口每秒最对访问一次add()上的自定义注解未填token属性的值说明默认每秒访问10次。

4.使用AOP环绕通知拦截方法

注解和接口都已经定义好我们来看看是怎么实现限流的。

@Aspect
@Component
public class CzxLimitAop {
    private ConcurrentHashMap<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>();

    @Around(value = "@annotation(com.example.reflect.ano.CzxLimit)")
    public Object around(ProceedingJoinPoint joinPoint){
        try {
            //获取拦截的方法名
            Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            //获取到该注解
            CzxLimit annotation = methodSignature.getMethod().getAnnotation(CzxLimit.class);
            String name = annotation.name();
            double token = annotation.token();
            // 判断该名称是否有创建RateLimiter
            RateLimiter rateLimiter = rateLimiters.get(name);
            if (rateLimiter == null) {
                rateLimiter = RateLimiter.create(token);
                rateLimiters.put(name, rateLimiter);
            }
            rateLimiter.tryAcquire();
            //如果被限流的话
            boolean result = rateLimiter.tryAcquire();
            if (!result) {
                return "当前访问人数过多请稍后重试!";
            }
            Object proceedResult = joinPoint.proceed();// 目标方法   public String get() {}
            return proceedResult;
        }catch (Throwable throwable){
           return "系统错误";
        }
    }
}

说明

  1. @annotation(com.example.reflect.ano.CzxLimit)注解的作用是该环绕通知会拦截所有加上了该注解的接口。
  2. 通过joinPoint获取拦截的方法进而获取该注解再根据注解参数进行限流控制。
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6