【接口限流】java中springboot实现接口限流防抖处理(JUC注解版)

ops/2024/10/22 21:17:39/

文章目录

    • 1、添加pom项目依赖
    • 2、注解类RateLimit
    • 3、限流切面RateLimitAspect
    • 4、controller层使用注解
    • 小结

1、添加pom项目依赖

		<!--AspectJ来实现切面,在方法执行前进行限流检查--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version></dependency>

2、注解类RateLimit

java">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 RateLimit {int limit() default 0;long timeUnit() default 0;boolean byIp() default false;boolean byRequestParam() default false;String paramName() default "";
}

3、限流切面RateLimitAspect

java">
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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 org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;/*** @author ZY.Jia* @date 2024/10/12 16:32* 限流切面类RateLimitAspect,使其支持根据 IP 和请求参数进行限流。**/
@Aspect
@Component
public class RateLimitAspect {@Autowiredprivate RateLimitConfig rateLimitConfig;private ConcurrentHashMap<String, AtomicInteger> requestCounts = new ConcurrentHashMap<>();private ConcurrentHashMap<String, AtomicLong> lastAccessTimes = new ConcurrentHashMap<>();@Around("@annotation(com.cmst.financialmiddleplatform.platformmaincenter.annotation.RateLimit)")public Object rateLimit(ProceedingJoinPoint joinPoint) throws Throwable {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();String requestIp = String.valueOf(request.getRemoteAddr()).trim();String requestURI = request.getRequestURI();// 获取被调用方法的方法名String methodKey = request.getMethod();Class<?>[] parameterTypes = new Class<?>[joinPoint.getArgs().length];for (int i = 0; i < joinPoint.getArgs().length; i++) {parameterTypes[i] = joinPoint.getArgs()[i].getClass();}Method method = joinPoint.getTarget().getClass().getMethod(joinPoint.getSignature().getName(), parameterTypes);RateLimit rateLimitAnnotation = method.getAnnotation(RateLimit.class);//注解方式获取参数int limit = rateLimitAnnotation.limit();long timeUnit = rateLimitAnnotation.timeUnit();boolean byIp = rateLimitAnnotation.byIp();boolean byRequestParam = rateLimitAnnotation.byRequestParam();String paramName = rateLimitAnnotation.paramName();//配置文件获取参数/*int limit = rateLimitConfig.getLimit();long timeUnit = rateLimitConfig.getTimeUnit();boolean byIp = rateLimitConfig.isByIp();boolean byRequestParam = rateLimitConfig.isByRequestParam();String paramName = rateLimitConfig.getParamName();*/Object requestParam = new Object();Object[] args = joinPoint.getArgs();if (args != null || args.length > 0) {for (Object arg : args) {requestParam = arg;}}Map<String, String> stringStringHashMap = new HashMap<String, String>();stringStringHashMap = JSONObject.parseObject(requestParam.toString(), Map.class);String key = methodKey + "_" + requestURI;if (byIp) {key += "_" + requestIp;}if (byRequestParam && stringStringHashMap.containsKey(paramName)) {key += "_" + paramName + "_" + stringStringHashMap.get(paramName);}// 如果该方法的计数不存在于 map 中,则初始化一个新的 AtomicInteger 并放入 map,否则返回已有的计数AtomicInteger count = requestCounts.computeIfAbsent(key, k -> new AtomicInteger(0));AtomicLong lastAccessTime = lastAccessTimes.computeIfAbsent(key, k -> new AtomicLong(System.currentTimeMillis()));long currentTime = System.currentTimeMillis();if (currentTime - lastAccessTime.get() > timeUnit) {// 时间超过指定时间单位,重置计数和时间count.set(0);lastAccessTime.set(currentTime);}if (count.get() < limit) {count.incrementAndGet();return joinPoint.proceed();} else {throw new RuntimeException("超过限制次数,请联系服务商!。");}}
}

4、controller层使用注解

注解解释:不对ip限流,只对参数中参数名为systemCode的参数值进行监控限流,一周的访问上限为350次

java">	@PostMapping("/123")@Syslog(description = "123")@RateLimit(limit = 350, timeUnit = 7*24*60*60*1000, byIp = false, byRequestParam = true, paramName = "systemCode")public MessageResult method123(@RequestBody String json) throws Exception {//。。。。。return new MessageResult("测试限流注解");}

小结

注解方式适用于各接口访问上限固定的情况。当客户需求明确规定了某段时间内的访问上限时,这种方式较为适用。

  • 优点:操作简便。由于各个接口的需求不尽相同,采用注解方式可以方便地进行设置。
  • 缺点:无法满足客户对访问上限不确定的接口需求。-----可以通过配置方式解决

后续更新Redis实现的限流防抖处理


http://www.ppmy.cn/ops/127659.html

相关文章

学习第三十六行

QValidator::State里面state为0&#xff0c;完全不匹配&#xff0c;1&#xff0c;部分匹配&#xff0c;2&#xff0c;完全匹配,对于label或者textedit里面的字符均为QString类型&#xff0c;特别是遇到数字&#xff0c;需要QString::number转化&#xff0c;对于正则表达式&…

【Docker项目实战】使用Docker部署HumHub社交网络平台

【Docker项目实战】使用Docker部署HumHub社交网络平台 一、HumHub介绍1.1 HumHub简介1.2 HumHub特点1.3 主要使用场景二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、下载HumHub镜…

Swin-Transformer

网络整体架构&#xff1a; Swin-transformer与vision transformer对比&#xff1a; Swin-Transformer构建的feature map具有层次性&#xff0c;类似于卷积神经网络&#xff0c;随着特征层的不断加深&#xff0c;feature map的高和宽是不断减小的&#xff1b;层次性使Swin-Tran…

什么是优秀的单元测试?

阅读本文之前&#xff0c;请投票支持这款 全新设计的脚手架 &#xff0c;让 Java 再次伟大&#xff01; 单元测试的质量意义 合理编写单元测试&#xff0c;可使团队工程师告别牛仔式编程&#xff0c;产出易维护的高质量代码。随着单元测试覆盖率的上升&#xff0c;项目会更加…

学习笔记——交换——STP(生成树)桥协议数据单元(BPDU)

四、桥协议数据单元(BPDU) 1、BPDU基本概念 桥协议数据单元(Bridege Protocol Data Unit,BPDU)BPDU是STP的协议报文&#xff0c;直接封装在二层协议&#xff0c;是传输载体。是STP能够正常工作的根本。 BPDU主要由 4 部分组成&#xff1a; (1)根桥ID (2)发送者到根桥的开…

Django中如何实现用户认证和会话管理

在Django中实现用户认证和会话管理&#xff0c;我们可以利用Django内置的认证系统&#xff0c;它包括用户账号、组、权限和基于cookie的用户会话管理。以下是一些基本步骤和概念&#xff1a; 用户认证&#xff08;Authentication&#xff09;&#xff1a; Django的认证系统可以…

PyTorch 2.5 发布带来一些新特性和改进

官网&#xff1a;https://github.com/pytorch/pytorchGitHub&#xff1a;https://github.com/pytorch/pytorch原文&#xff1a;https://github.com/pytorch/pytorch/releases/tag/v2.5.0 主要亮点 (Highlights)] SDPA CuDNN 后端&#xff1a;为 torch.nn.functional.scaled_d…

⌈ 传知代码 ⌋ 农作物病害分类(Web端实现)

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…