SpringBoot如何實(shí)現(xiàn)一個(gè)Redis限流注解
SpringBoot實(shí)現(xiàn)一個(gè)Redis限流注解
使用步驟
1.引入庫(kù)
- 代碼如下(示例)
<!-- 引入SpringBoot Aop依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2.代碼實(shí)現(xiàn)
- 添加注解
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 "請(qǐng)求過(guò)于頻繁,請(qǐng)稍后再試"; }
- 新增限流AOP實(shí)現(xiàn)
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(); // 沒(méi)有注解,直接執(zhí)行方法 } int limit = annotation.number(); // 限制次數(shù) int expire = annotation.time(); // 過(guò)期時(shí)間 String message = annotation.message(); log.info("攔截方法: {}, 限流 key: {}, 限流次數(shù): {}, 過(guò)期時(shí)間: {} 秒", method.getName(), limit, expire); // 執(zhí)行限流邏輯 boolean isAllowed = checkRedisLimiting(method, joinPoint.getArgs(), limit, expire); if (!isAllowed) { throw new BusinessException(ErrorCode.BUSY_ERROR,message); } return joinPoint.proceed(); // 執(zhí)行原方法 } 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); // 初始值設(shè)為1,并設(shè)置過(guò)期時(shí)間 return true; } else { int count = Integer.parseInt(o.toString()); if (count >= limit) { return false; // 超過(guò)限制 } else { redisUtils.increment(redisKey, 1); // 遞增計(jì)數(shù) 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 } }
- 實(shí)現(xiàn)代碼的攔截
@GetMapping("/getAllModel") @RedisLimiting(number = 3, time = 60,message = "不要再請(qǐng)求我的獲取aiModel方法了") public BaseResponse<List<AiModelVO>> getAllModel() { return ResultUtils.success(aiModelService.getAllModel()); }
總結(jié)
以上就是今天要講的內(nèi)容,本文僅僅簡(jiǎn)單介紹了pandas的使用,而pandas提供了大量能使我們快速便捷地處理數(shù)據(jù)的函數(shù)和方法。
這些僅為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java計(jì)算程序代碼執(zhí)行時(shí)間的方法小結(jié)
這篇文章主要介紹了Java計(jì)算程序代碼執(zhí)行時(shí)間的方法,結(jié)合實(shí)例形式總結(jié)分析了java采用毫秒數(shù)及納秒數(shù)計(jì)算程序運(yùn)行時(shí)間的相關(guān)操作技巧,需要的朋友可以參考下2017-11-11解決Springboot集成Redis集群配置公網(wǎng)IP連接報(bào)私網(wǎng)IP連接失敗問(wèn)題
在Springboot 集成 Redis集群配置公網(wǎng)IP連接報(bào)私網(wǎng)IP連接失敗,一直報(bào)私有IP連接失敗,所以本文小編給大家介紹了如何解決報(bào)錯(cuò)問(wèn)題,如果有遇到相同問(wèn)題的同學(xué),可以參考閱讀本文2023-10-10springboot自定義starter啟動(dòng)器的具體使用實(shí)踐
本文主要介紹了springboot自定義starter啟動(dòng)器的具體使用實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09SpringBoot攔截器實(shí)現(xiàn)項(xiàng)目防止接口重復(fù)提交
基于SpringBoot框架來(lái)開(kāi)發(fā)業(yè)務(wù)后臺(tái)項(xiàng)目時(shí),接口重復(fù)提交是一個(gè)常見(jiàn)的問(wèn)題,本文主要介紹了SpringBoot攔截器實(shí)現(xiàn)項(xiàng)目防止接口重復(fù)提交,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09Java設(shè)置Access-Control-Allow-Origin允許多域名訪問(wèn)的實(shí)現(xiàn)方法
這篇文章主要介紹了Java設(shè)置Access-Control-Allow-Origin允許多域名訪問(wèn)的實(shí)現(xiàn)方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-10-10SpringBoot集成Spring Security的方法
Spring security,是一個(gè)強(qiáng)大的和高度可定制的身份驗(yàn)證和訪問(wèn)控制框架。這篇文章主要介紹了SpringBoot集成Spring Security的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07