ChatGPT入门实战 时代更具竞争力的开发者

82 阅读1分钟

download:ChatGPT入门实战 时代更具竞争力的开发者

版本阐明

以下源码内容是基于RuoYi-Vue-3.8.2版本,即前后端别离版本

主要思想

标注了@RateLimiter注解的办法,在执行前调用lua脚本,把一段时间内的访问次数存入redis并返回,判别返回值能否大于设定的阈值,大于则抛出异常,由全局异常处置器处置

详细步骤

1. 注解

我们先来看一看@RateLimiter注解,在src/main/java/com/ruoyi/common/annotation包下

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface RateLimiter

{

// 限流key

public String key() default Constants.RATE_LIMIT_KEY;

// 限流时间,单位秒

public int time() default 60;

// 限流次数

public int count() default 100;

// 限流类型

public LimitType limitType() default LimitType.DEFAULT;

}

一个作用在办法上的注解,有四个属性

key:存储在redis里用到的key

time:限流时间,相当于redis里的有效期

count:限流次数

limitType: 限流类型,点开枚举发现有默许和IP两种限流方式,这两种方式的完成只是存储在redis里的key不同

2. 切面

我们来看一看@RateLimiter这个注解的切面RateLimiterAspect.java,在src/main/java/com/ruoyi/framework/aspectj包里

@Aspect

@Component

public class RateLimiterAspect

{

private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);

private RedisTemplate<Object, Object> redisTemplate;

private RedisScript limitScript;

@Autowired

public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate)

{

this.redisTemplate = redisTemplate;

}

@Autowired

public void setLimitScript(RedisScript limitScript)

{

this.limitScript = limitScript;

}

@Before("@annotation(rateLimiter)")

public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable

{

String key = rateLimiter.key();

int time = rateLimiter.time();

int count = rateLimiter.count();

String combineKey = getCombineKey(rateLimiter, point);

List keys = Collections.singletonList(combineKey);

try

{

// 调用lua脚本,传入三个参数

Long number = redisTemplate.execute(limitScript, keys, count, time);

if (StringUtils.isNull(number) || number.intValue() > count)

{

throw new ServiceException("访问过于频繁,请稍候再试");