赞
踩
本文主要介绍如何定义实现注解,并配合AOP,来实现滑动时间窗口算法
注解(Annotation)是Java中的一种特殊的元数据(metadata),JDK5.0新增的,它提供了一种在代码中添加标记和元数据的方式。注解可以用于类、方法、字段和其他程序元素上。
注解以@符号开头,紧跟着注解的名称和一对括号。注解可以包含元素,这些元素可以接受值。注解的元素可以是预定义的类型,如字符串、整数等,也可以是枚举类型或其他注解类型。
注解可以用于多种目的,例如:
Java中有一些内置的注解,如@Override、@Deprecated和@SuppressWarnings。此外,你还可以自定义注解来满足特定的需求。
总之,注解是一种用于添加元数据和标记的机制,它可以在编译时和运行时提供有关代码的额外信息,我们使用注解,可以在不改变原有逻辑的情况下,补充一些逻辑。
AOP,面向切面编程,也是可以帮助我们在不修改现有代码的情况下,对程序的功能进行拓展,往往用于实现日志处理,事务控制等通用功能
常用的通知类型
通过@interface关键字来定义注解
@Retention指定注解的生命周期,RetentionPolicy.RUNTIME表示在运行时有效
@Target指定作用目标ElementType.METHOD就是要加在方法上才有效
定义了两个参数period,limitCount,来实现我们的逻辑
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface SlideWindowLimit { /** * 限制时间范围,单位ms */ long period() default 1000; /** * 限制请求次数 */ int limitCount() default 5; }
主要Lua脚本来实现,另外还可以通过list和zset来实现,感兴趣的话,后面我再写一篇文章专门来分析
这里使用的是@Around环绕注解,目前只使用了前置增强,还可以使用后置增强,记录下调用等情况,感兴趣的话,大家可以实现下
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; @Aspect @Component public class SlideWindowLimitAspect { @Autowired private SlideWindowUtils slideWindowUtils; // 配置切入点 @Pointcut("@annotation(cn.forlan.annotation.SlideWindowLimit)") public void slideWindowLimitPointcut() { } @Around("slideWindowLimitPointcut()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 获取注解属性 SlideWindowLimit slideWindowLimit = ((MethodSignature) pjp.getSignature()).getMethod().getAnnotation(SlideWindowLimit.class); if (slideWindowUtils.slideWindowAlgorithmByLua(request.getRequestURI(), slideWindowLimit.limitCount(), slideWindowLimit.period())) { return "操作过于频繁,请稍后重试"; } return pjp.proceed(); } }
注:有多个增强类对同一方法进行增强,可以通过@Order(数字)可以设置优先级,数字越小,越先执行
上面定义的作用目标是方法,所以我们直接在方法上加自定义注解,@SlideWindowLimit(period = 10000, limitCount = 5),设置10秒内只能访问5次,如下图:
我们通过Postman来快速调用5次,可以看到接口已经被限制,说明我们自定义的注解+AOP逻辑生效了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。