1、使用@interface关键定义注解(RateLimiter.java),如下:
package com.vx.servicehi.annotation; import java.lang.annotation.*; /** * @author wangbs * @version 1.0 * @date 2019/12/16 1:25 * @className RateLimiter * @desc 限流注解 */ //注解作用域 // ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上 // ElementType.FIELD:允许作用在属性字段上 // ElementType.METHOD:允许作用在方法上 // ElementType.PARAMETER:允许作用在方法参数上 // ElementType.CONSTRUCTOR:允许作用在构造器上 // ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上 // ElementType.ANNOTATION_TYPE:允许作用在注解上 // ElementType.PACKAGE:允许作用在包上 // // 注解的生命周期 // RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件 // RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件 // RetentionPolicy.RUNTIME:永久保存,可以反射获取 // 注解的作用域 @Target(ElementType.METHOD) // 注解的生命周期 @Retention(RetentionPolicy.RUNTIME) // 允许子类继承 @Inherited // 生成javadoc的时候生成注解的信息 @Documented public @interface RateLimiter { /** * 限流key * @return */ String key() default "rate:limiter"; /** * 单位时间限制通过请求数 * @return */ long limit() default 10; /** * 过期时间,单位秒 * @return */ long expire() default 1; /** * 限流提示语 * @return */ String message() default "false"; }
2、在普通类上使用注解,使用方法
package com.vx.servicehi.controller;
import com.vx.servicehi.annotation.RateLimiter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("business")
public class BusinessController {
private static final Logger LOGGER = LoggerFactory.getLogger(BusinessController.class);
private static final String MESSAGE = "{\"code\":\"400\",\"msg\":\"FAIL\",\"desc\":\"触发限流\"}";
@Value("${server.port}")
String port;
/**
* 使用自定义注解 限流
* @param name
* @return
*/
@RequestMapping("/hi")
@RateLimiter(key = "business/hi", limit = 5, expire = 10, message = MESSAGE)
public String home(@RequestParam(value = "name", defaultValue = "forezp") String name) {
return "hi " + name + " ,i am from port:" + port;
}
}
3、解析注解,通过反射获取类,函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑
package com.vx.servicehi.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
* 解析注解
* 通过反射获取类,函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑
*
* 对于一个类或者接口来说,Class 类中提供了以下一些方法用于反射注解。
getAnnotation:返回指定的注解
isAnnotationPresent:判定当前元素是否被指定注解修饰
getAnnotations:返回所有的注解
getDeclaredAnnotation:返回本元素的指定注解
getDeclaredAnnotations:返回本元素的所有注解,不包含父类继承而来的
*
* @author wangbs
* @date 2019-12-21 22:52:42
* 主要是对自定义注解 RateLimiter 的获取 测试
*
*/
public class ParseDecription {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 1、使用类加载器加载类
try {
Class c = Class.forName("com.vx.servicehi.controller.BusinessController");
System.out.println(c);
// 2、找到类上面的注解
boolean isExist = c.isAnnotationPresent(RateLimiter.class);
if(isExist) {
// 3、拿到注解实例
RateLimiter d = (RateLimiter) c.getAnnotation(RateLimiter.class);
System.out.println("========parse class annotation=========");
System.out.println("desc = " + d.key());
System.out.println("author = " + d.message());
System.out.println("age = " + d.limit());
}
// 4、找到方法上的注解
Method[] ms = c.getMethods();
for (Method m : ms) {
boolean isMExist = m.isAnnotationPresent(RateLimiter.class);
if(isMExist) {
RateLimiter d = m.getAnnotation(RateLimiter.class);
System.out.println("========parse method annotation=========");
System.out.println("desc = " + d.key());
System.out.println("author = " + d.message());
System.out.println("age = " + d.limit());
}
}
// 另外一种解析方法
for (Method m : ms) {
Annotation[] annotations = m.getAnnotations();
for (Annotation annotation : annotations) {
if(annotation instanceof RateLimiter) {
System.out.println("========parse method annotation other way=========");
RateLimiter d = (RateLimiter) annotation;
System.out.println("desc = " + d.key());
System.out.println("author = " + d.message());
System.out.println("age = " + d.limit());
}
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}