欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

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

来源: javaer 分享于  点击 47525 次 点评:202

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


目录
  • SpringBoot实现一个Redis限流注解
    • 使用步骤
      • 1.引入库
      • 2.代码实现
  • 总结

    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提供了大量能使我们快速便捷地处理数据的函数和方法。

    这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持3672js教程。

    您可能感兴趣的文章:
    • Springboot中使用Redisson+AOP+自定义注解实现访问限流与黑名单拦截
    • SpringBoot使用自定义注解+AOP+Redis实现接口限流的实例代码
    • SpringBoot如何使用自定义注解实现接口限流
    相关栏目:

    用户点评