SpringBoot如何实现一个Redis限流注解

2025-05-14 10:12:13 121
魁首哥

springboot实现一个redis限流注解

使用步骤

1.引入库

  • 代码如下(示例)
        
        
            org.springframework.boot
            spring-boot-starter-aop
        

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> getallmodel() {
        return resultutils.success(aimodelservice.getallmodel());
    }

总结

以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

分享
海报
121
上一篇:java -jar命令详解之运行JAR文件、传递参数与性能调优 下一篇:SpringBoot+shardingsphere实现按月分表功能教程

忘记密码?

图形验证码