springboot实现一个redis限流注解
使用步骤
1.引入库
- 代码如下(示例)
<!-- 引入springboot aop依赖 -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-aop</artifactid>
</dependency>2.代码实现
- 添加注解
package com.hhh.springai_test.annotation;
import java.lang.annotation.elementtype;
import java.lang.annotation.retention;
import java.lang.annotation.retentionpolicy;
import java.lang.annotation.target;
@target(elementtype.method)
@retention(retentionpolicy.runtime)
public @interface redislimiting {
int number() default 3;
int time() default 60;
string message() default "请求过于频繁,请稍后再试";
}- 新增限流aop实现
package com.hhh.springai_test.aop;
import cn.hutool.crypto.digest.md5;
import com.hhh.springai_test.annotation.redislimiting;
import com.hhh.springai_test.common.errorcode;
import com.hhh.springai_test.exception.businessexception;
import com.hhh.springai_test.utils.redisutils;
import lombok.extern.slf4j.slf4j;
import org.aspectj.lang.proceedingjoinpoint;
import org.aspectj.lang.annotation.around;
import org.aspectj.lang.annotation.aspect;
import org.aspectj.lang.reflect.methodsignature;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.component;
import java.lang.reflect.method;
import java.lang.reflect.parameter;
@aspect
@component("redislimitingaspect")
@slf4j
public class redislimitingaspect {
@autowired
private redisutils redisutils;
@around("@annotation(com.hhh.springai_test.annotation.redislimiting)") // 只拦截带 @redislimiting 的方法
public object redislimiting(proceedingjoinpoint joinpoint) throws throwable {
methodsignature signature = (methodsignature) joinpoint.getsignature();
method method = signature.getmethod(); // 直接获取被代理的方法
// 获取 @redislimiting 注解
redislimiting annotation = method.getannotation(redislimiting.class);
if (annotation == null) {
return joinpoint.proceed(); // 没有注解,直接执行方法
}
int limit = annotation.number(); // 限制次数
int expire = annotation.time(); // 过期时间
string message = annotation.message();
log.info("拦截方法: {}, 限流 key: {}, 限流次数: {}, 过期时间: {} 秒",
method.getname(), limit, expire);
// 执行限流逻辑
boolean isallowed = checkredislimiting(method, joinpoint.getargs(), limit, expire);
if (!isallowed) {
throw new businessexception(errorcode.busy_error,message);
}
return joinpoint.proceed(); // 执行原方法
}
private boolean checkredislimiting(method method, object[] args, int limit, int expire) {
// 生成 redis key
string rediskey = generaterediskey(method, args);
// 查询 redis 是否存在
object o = redisutils.get(rediskey);
if (o == null) {
redisutils.setex(rediskey, 1, expire); // 初始值设为1,并设置过期时间
return true;
} else {
int count = integer.parseint(o.tostring());
if (count >= limit) {
return false; // 超过限制
} else {
redisutils.increment(rediskey, 1); // 递增计数
return true;
}
}
}
private string generaterediskey(method method, object[] args) {
stringbuilder builder = new stringbuilder();
builder.append(method.getdeclaringclass().getname()).append(":").append(method.getname()).append(":");
parameter[] parameters = method.getparameters();
for (int i = 0; i < parameters.length; i++) {
builder.append(parameters[i].getname()).append("=").append(args[i]).append("&");
}
return md5.create().digesthex16(builder.tostring()); // 生成唯一 redis key
}
}- 实现代码的拦截
@getmapping("/getallmodel")
@redislimiting(number = 3, time = 60,message = "不要再请求我的获取aimodel方法了")
public baseresponse<list<aimodelvo>> getallmodel() {
return resultutils.success(aimodelservice.getallmodel());
}总结
以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。
这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论