spring boot3自定义注解+拦截器+Redis实现高并发接口限流

⛰️个人主页: 蒾酒
🔥系列专栏:《spring boot实战》
🌊山高路远,行路漫漫,终有归途
目录
写在前面
内容简介
实现思路
实现步骤
1.自定义限流注解
2.编写限流拦截器
3.注册拦截器
4.接口限流测试
写在前面
本文介绍了springboot开发后端服务中,高并发接口限流设计与实现,坚持看完相信对你有帮助。
同时欢迎订阅springboot系列专栏,持续分享spring boot的使用经验。
内容简介
本文介绍了一种使用自定义注解结合拦截器和redis实现接口限流方法。这种方法也是企业常用方法,是一种比较优雅的解决方案。
优点分析
灵活性和可定制性: 通过自定义注解和拦截器,可以根据具体的业务需求灵活定义限流规则,满足不同接口的限流需求。
性能优化: 使用Redis等高性能缓存数据库存储限流计数器,能够有效减轻应用程序的压力,提高系统的性能表现。
实时性和持久性: Redis具有较高的读写性能,可以实时更新限流计数器,并且数据持久化,保证限流规则的持久性。
分布式支持: 对于分布式系统,使用Redis等分布式缓存数据库可以方便地实现跨节点的限流策略和计数器共享,确保限流的准确性和一致性。
成熟稳定: 这种方法经过实践验证,在众多企业项目中得到广泛应用,被认为是一种成熟、稳定且可靠的解决方案。
实现思路
通过自定义一个注解标注需要进行限流的接口方法,通过拦截器对标记改注解的方法进行拦截处理
将同一ip访问同一接口的次数缓存到redis,拦截器中进行判断处理,达到访问阈值直接拒绝。
实现步骤
1.自定义限流注解
import java.lang.annotation.*;/*** @author mijiupro*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Inherited
@Documented
public @interface AccessLimit {int limit() default 10; // 限流阈值int seconds() default 60; // 时间窗口
}
2.编写限流拦截器
/*** 接口限流拦截器* @author mijiupro*/
@Slf4j
@Component
public class AccessLimitInterceptor implements HandlerInterceptor {private final StringRedisTemplate redisTemplate;public AccessLimitInterceptor(StringRedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;}@Overridepublic boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) {if (!(handler instanceof HandlerMethod handlerMethod)) {return true;}Method method = handlerMethod.getMethod();AccessLimit accessLimit = method.getAnnotation(AccessLimit.class);// 若方法上没有AccessLimit注解,直接放行if (accessLimit == null) {return true;}int limit = accessLimit.limit();int seconds = accessLimit.seconds();String key = generateKey(request); // 生成限流key// 使用基本类型long接收计数值,并确保不会因自动装箱产生NullPointerExceptionLong countResult = redisTemplate.opsForValue().increment(key, 1);long currentCount = countResult != null ? countResult : 0;if (currentCount == 1) {// 如果是第一次访问,设置过期时间redisTemplate.expire(key, seconds, TimeUnit.SECONDS);log.debug("设置访问限制计数为1:{}", key);return true;}if (currentCount > limit) {log.error("访问超过限制:{}", key);throw new RateLimitException(ResultEnum.ACCESS_LIMIT_REACHED);}log.debug("访问限制计数递增:{}", key);return true;}private String generateKey(HttpServletRequest request) {// 组合key的方式可以根据实际业务需要调整,例如考虑方法名称、用户ID等return request.getRemoteAddr() + ":" + request.getContextPath() + ":" + request.getServletPath();}}
3.注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {private final AccessLimitInterceptor accessLimitInterceptor;public WebConfig( AccessLimitInterceptor accessLimitInterceptor) {this.accessLimitInterceptor = accessLimitInterceptor;}@Overridepublic void addInterceptors(@NotNull InterceptorRegistry registry) {//添加上接口限流拦截器使之生效registry.addInterceptor(accessLimitInterceptor).order(0);}
}
4.接口限流测试
随便写个接口标记限流注解进行测试
这里使用swagger3进行测试:
Spring Boot3整合knife4j(swagger3)_springboot3 knife4j-CSDN博客文章浏览阅读2.1k次,点赞39次,收藏52次。Knife4j · 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j (xiaominfo.com)作者的使用的spring boot 3.2.2为当前最新版,所以依赖导入最新的knife4j 4.4.0。3.1 增强模式 | Knife4j (xiaominfo.com)好一个spring boot项目且版本为3X,项目可正常启动。快速开始 | Knife4j (xiaominfo.com)接下来配置以下接口文档的作者等信息。@Tag注解:标记接口类别。_springboot3 knife4jhttps://blog.csdn.net/qq_62262918/article/details/135761392?spm=1001.2014.3001.5502
@GetMapping("/get-int")@AccessLimit( limit = 5, seconds= 60)public Integer getInt() {return 1;}
前五次访问:

第六次访问:

写在最后
spring boot3自定义注解+拦截器+Redis实现高并发接口限流到这里就结束了,本文介绍了一种常见的实现方法。任何问题评论区或私信讨论,欢迎指正。
相关文章:
spring boot3自定义注解+拦截器+Redis实现高并发接口限流
⛰️个人主页: 蒾酒 🔥系列专栏:《spring boot实战》 🌊山高路远,行路漫漫,终有归途 目录 写在前面 内容简介 实现思路 实现步骤 1.自定义限流注解 2.编写限流拦截器 3.注册拦截器 4.接口限流测试 写在前…...
使用certbot为网站启用https
1. 安装certbot客户端 cd /usr/local/bin wget https://dl.eff.org/certbot-auto chmod ax ./certbot-auto 2. 创建目录和配置nginx用于验证域名 mkdir -p /data/www/letsencryptserver {listen 80;server_name ~^(?<subdomain>.).ninvfeng.com;location /.well-known…...
Unity 背包系统中拖拽物体到指定位置或互换位置效果的实现
在Unity中,背包系统是一种常见的游戏系统,可以用于管理和展示玩家所持有的物品、道具或装备。 其中的拖拽功能非常有意思,具体功能就是玩家可以通过拖拽物品图标来移动物品在背包中的位置,或者将物品拖拽到其他位置或界面中&…...
iOS客户端自动化UI自动化airtest+appium从0到1搭建macos+脚本设计demo演示+全网最全最详细保姆级有步骤有图
Android客户端自动化UI自动化airtest从0到1搭建macos脚本设计demo演示全网最全最详细保姆级有步骤有图-CSDN博客 避坑系列-必读: 不要安装iOS-Tagent ,安装appium -这2个性质其实是差不多的都是为了安装wda。注意安装appium最新版本,安装完…...
每周编辑精选|在线运行 Deepmoney 金融大模型、AI 偏好等多个优质数据集上线
目前,AI 领域对金融模型的研究成果大多是基于公共知识进行训练的,但在实际的金融实践中,这些公共知识对于当前市场的可解释性往往严重不足。一个理想的金融大模型应该能够理解新闻或数据事件,并能够即时地从主观和量化两个角度对事…...
C++多重继承与虚继承
多重继承的原理 多重继承(multiple inheritance)是指从多个直接基类中产生派生类的能力。 多重继承的派生类继承了所有父类的属性。 在面向对象的编程中,多重继承意味着一个类可以从多个父类继承属性和方法。 就像你有一杯混合果汁,它是由多种水果榨取…...
请简单介绍一下Shiro框架是什么?Shiro在Java安全领域的主要作用是什么?Shiro主要提供了哪些安全功能?
请简单介绍一下Shiro框架是什么? Shiro框架是一个强大且灵活的开源安全框架,为Java应用程序提供了全面的安全解决方案。它主要用于身份验证、授权、加密和会话管理等功能,可以轻松地集成到任何Java Web应用程序中,并提供了易于理解…...
TouchGFX之Button
TouchGFX中的按钮是一种感应触控事件的控件,能够在按钮被按下/释放时发送回调 代码 #ifndef TOUCHGFX_ABSTRACTBUTTON_HPP #define TOUCHGFX_ABSTRACTBUTTON_HPP #include <touchgfx/Callback.hpp> #include <touchgfx/events/ClickEvent.hpp> #includ…...
计算机组成原理 — 指令系统
指令系统 指令系统指令的概述指令的格式指令的字长取决于 操作数类型和操作种类操作数的类型数据在存储器中的存放方式操作类型 寻址方式指令寻址数据寻址立即寻址直接寻址隐含寻址间接寻址寄存器寻址寄存器间接寻址基址寻址变址寻址堆栈寻址 RISC 和 CISC 技术RISC 即精简指令…...
使用easyYapi生成文档
easyYapi生成文档 背景1.安装配置1.1 介绍1.2 安装1.3 配置1.3.1 Export Postman1.3.2 Export Yapi1.3.3 Export Markdown1.3.4 Export Api1.3.6 常见问题补充 2. java注释规范2.1 接口注释规范2.2 出入参注释规范 3. 特定化支持3.1 必填校验3.2 忽略导出3.3 返回不一致3.4 设置…...
蓝桥杯练习题总结(三)线性dp题(摆花、数字三角形加强版)
目录 一、摆花 思路一: 确定状态: 初始化: 思路二: 确定状态: 初始化: 循环遍历: 状态转移方程: 二、数字三角形加强版 一、摆花 题目描述 小明的花店新开张,为了吸…...
Elasticsearch(15) multi_match的使用
elasticsearch version: 7.10.1 multi_match是Elasticsearch中的一种查询类型,允许在一个或多个字段上执行全文本搜索,并合并各个字段的结果得分。这种查询有助于实现跨多个字段的统一搜索体验。 语法 {"query": {"multi_m…...
nodejs的线程模型和libuv库的基本使用
文章目录 nodejs中集成addon本地代码的回调问题单线程事件驱动模型libuvlibuv基本框架addon中使用libuv代码nodejs中集成addon本地代码的回调问题 在C++的代码中,回调函数是一个基本的代码调用方式。而在我自己的开发实践中,需要在addon这样一个nodejs的本地化模块中实现一个…...
Uni-app/Vue/Js本地模糊查询,匹配所有字段includes和some方法结合使用e
天梦星服务平台 (tmxkj.top)https://tmxkj.top/#/ 1.第一步 需要一个数组数据 {"week": "全部","hOutName": null,"weekendPrice": null,"channel": "门市价","hOutId": 98,"cTime": "…...
深度学习pytorch——激活函数损失函数(持续更新)
论生物神经元与神经网络中的神经元联系——为什么使用激活函数? 我们将生物体中的神经元与神经网络中的神经元共同分析。从下图可以看出神经网络中的神经元与生物体中的神经元有很多相似之处,由于只有刺激达到一定的程度人体才可以感受到刺激,…...
《苹果 iOS 应用开发与分发的关键问题解析》
一、背景 解决同事问的问题,来来回回被问好几次相同的问题,然后确认,我觉得不如写个文档 二、非研发人员安装iOS应用方式 TestFlightIPA 文件 对比 TestFlightIPA 文件安装方式TestFlight 是苹果提供的一个 beta 测试平台,开发者…...
爱上数据结构:顺序表和链表
一、线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的一条…...
python知识点总结(十)
python知识点总结十 1、装饰器的理解、并实现一个计时器记录执行性能,并且将执行结果写入日志文件中2、队列和栈的区别,并且用python实现3、设计实现遍历目录与子目录4、CPU处理进程最慢的情况通常发生在以下几种情况下:5、CPU处理线程最慢的…...
【Python】探索 Python 编程世界:常量、变量及数据类型解析
欢迎来CILMY23的博客 本篇主题为 探索 Python 编程世界:常量、变量及数据类型解析 个人主页:CILMY23-CSDN博客 Python系列专栏:http://t.csdnimg.cn/HqYo8 上一篇博客: http://t.csdnimg.cn/SEdbp C语言专栏: htt…...
vue页面实现左右div宽度,上下div高度分割线手动拖动高度或者宽度自动变化,两个div宽度或者高度拉伸调节,实现左右可拖动改变宽度的div内容显示区
实现左右或者上下div两部分拖动,宽度或者高度自动变化,实现流畅平滑的变化,还可以是实现拖动到一定宽度就不让拖动了,如果你不需要最小宽度,就直接去掉样式就行 这是页面。分左中右三部分,中间我是用来作为拖动的按钮…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...
用 FFmpeg 实现 RTMP 推流直播
RTMP(Real-Time Messaging Protocol) 是直播行业中常用的传输协议。 一般来说,直播服务商会给你: ✅ 一个 RTMP 推流地址(你推视频上去) ✅ 一个 HLS 或 FLV 拉流地址(观众观看用)…...
