自定义注解+拦截器+redis限流
逻辑:写一个注解,自定义在多少秒内限制访问多少次。
自定义拦截器,对于加了注解的请求,在执行方法前。先检查有没有注解,如果有注解就将请求的ip+url拼接作为key。
查询redis中有没有该key,没有就存入(key,1,注解中设置的时间限制,单位)
如果redis有该key,就将原来的value取出+1,
1.自定义注解
import java.lang.annotation.*;
@Inherited
@Documented
@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {int limit() default 5;int sec() default 5;
}
2.拦截器
在springboot中自定义拦截器,实现HandlerInterceptor
接口。实现三个方法:preHandle()//请求到达controller前
postHandle()//请求到达controller后
afterCompletion()//渲染视图后调用
import com.qcby.xmdemo.annocation.AccessLimit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Component
public class AccessLimitInterceptor implements HandlerInterceptor {@Autowiredprivate RedisTemplate redisTemplate;@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();if (!method.isAnnotationPresent(AccessLimit.class)) {return true;}AccessLimit accessLimit = method.getAnnotation(AccessLimit.class);if (accessLimit == null) {return true;}int limit = accessLimit.limit();int sec = accessLimit.sec();String key = getIpAddr(request) + request.getRequestURI();Integer maxLimit = (Integer) redisTemplate.opsForValue().get(key);if (maxLimit == null) {redisTemplate.opsForValue().set(key, 1, sec, TimeUnit.SECONDS);//set时一定要加过期时间} else if (maxLimit < limit) {redisTemplate.opsForValue().set(key, maxLimit + 1, sec, TimeUnit.SECONDS);} else {output(response, "请求太频繁!");return false;}}return true;}public void output(HttpServletResponse response, String msg) throws IOException {response.setContentType("application/json;charset=UTF-8");ServletOutputStream outputStream = null;try {outputStream = response.getOutputStream();outputStream.write(msg.getBytes("UTF-8"));} catch (IOException e) {e.printStackTrace();} finally {outputStream.flush();outputStream.close();}}@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}//获取请求ip的方法private static String getIpAddr(HttpServletRequest request) {List<String> ipHeadList = Stream.of("X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "X-Real-IP").collect(Collectors.toList());for (String ipHead : ipHeadList) {if (checkIP(request.getHeader(ipHead))) {return request.getHeader(ipHead).split(",")[0];}}return "0:0:0:0:0:0:0:1".equals(request.getRemoteAddr()) ? "127.0.0.1" : request.getRemoteAddr();}private static boolean checkIP(String ip) {return !(null == ip || 0 == ip.length() || "unknown".equalsIgnoreCase(ip));}}
3.注册拦截器
注册到Spring MVC的拦截器链中。实现WebMvcConfigurer
接口并重写addInterceptors()
方法来实现。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@AutowiredAccessLimitInterceptor accessLimitInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(accessLimitInterceptor).addPathPatterns("/**")//拦截所有的路径.excludePathPatterns("/LoginCntroller/login");}
}
4.测试
@Controller
@RequestMapping("/hello")
public class AopController {@ResponseBody@RequestMapping("/index")@AccessLimit(limit = 4,sec = 10)//加上自定义注解即可public String test (HttpServletRequest request, @RequestParam(value = "username",required = false) String userName) {return "hello!";}}
相关文章:
自定义注解+拦截器+redis限流
逻辑:写一个注解,自定义在多少秒内限制访问多少次。 自定义拦截器,对于加了注解的请求,在执行方法前。先检查有没有注解,如果有注解就将请求的ipurl拼接作为key。 查询redis中有没有该key,没有就存入&…...

Springcloud物流配送后台-计算机毕业设计源码69809
目 录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2 物流配送后台系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1数据增加流程 2.2.2 数据修改流程 2.2.3 数据…...
【Java面试篇】数据埋点监控页面pv的SDK接口实现
面试题如下: 题目要求你实现一个 Monitor.counter(String code, String dim) 接口,用于监控数据统计。 具体要求: 数据聚合: 你需要按照 code 和 dim 的组合进行数据聚合, code 代表监控项的唯一标识, dim 为自定义维度。上报频率: 每分钟上报一次聚合后的数据。数据保证…...

vue3直播视频流easy-player
vue3直播视频流easy-player <script src"/easyPlayer/EasyPlayer-element.min.js"></script> easyPlayer文件下载地址 https://download.csdn.net/download/weixin_42120669/89605739 <template><div class"container"><div …...
Python笔试面试题AI答之面向对象(3)
文章目录 12.Python中OOPS是什么?1. 类(Class)2. 对象(Object)3. 面向对象编程的主要特性4. 面向对象编程的优点 13.解释一下Python中的继承?继承的基本语法继承的特性继承的类型 14. 什么是封装࿱…...

vulnhub靶场serial-php渗透(蜥蜴细!)
目录 一、信息收集 1.探测主机存活(目标主机IP地址) 2.访问web服务 3.后台目录和端口扫描 4.解析bak.zip源码 二、漏洞利用 1.构造payload 2.通过bp的repeater模块 3.get shell 4.获取反弹shell 三、提升权限 1. 查看系统版本,内核…...

Qt Designer,仿作一个ui界面的练习(一):界面的基本布局
初学不要太复杂,先做一个结构简单的,大致规划一下功能分区,绘制草图: 最终的效果: 界面主要由顶边栏、侧边栏、内容区构成。顶边栏左边是logo,右边是时钟显示。侧边栏最上边是切换按钮,用以动画…...
《深入了解 Postman 接口测试工具》
在现代 Web 开发中,接口测试是确保系统稳定性和可靠性的关键环节。Postman 作为一款强大的接口测试工具,为开发者和测试人员提供了便捷、高效的测试体验。本文将深入详解 Postman 的各项功能和使用方法。 一、Postman 简介 Postman 是一款功能丰富的 A…...
java使用org.apache.commons:commons-compress解压 .7z压缩包
前言 java使用org.apache.commons:commons-compress解压 .7z压缩包 一、使用步骤 1.引入库 代码如下(示例):cpmpress需要用到xz依赖,不一起引入会报错。 <!-- https://mvnrepository.com/artifact/org.tukaani/xz --> …...
通过知识库系统实现卓越医疗保健
提供更好的患者治疗效果;提高医疗保健组织的效率和有效性。 利用 Baklib 的力量 Baklib 使患者、代理人和专业人员能够轻松采用知识库系统。 1.对于患者 通过自助在线知识库提供有关药品、测试、服务、康复等的信息,改善患者体验和健康结果。 2.对于…...

基于C语言从0开始手撸MQTT协议代码连接标准的MQTT服务器,完成数据上传和命令下发响应(华为云IOT服务器)
文章目录 一、前言二、搭建开发环境三、网络编程基础概念科普3.1 什么是网络编程3.2 TCP 和 UDP协议介绍3.3 TCP通信的实现过程 四、Windows下的网络编程相关API介绍4.1 常用的函数介绍4.2 函数参数介绍4.3 编写代码体验网络编程 五、访问华为云IOT服务器创建一个产品和设备5.2…...
程序员面试中的“八股文”:敲门砖还是绊脚石?
在现代技术行业中,“八股文”成为了程序员面试中的常见问题。“八股文”究竟能否在实际工作中发挥应有的作用,成了一个备受争议的话题。许多IT从业者都提出疑问:程序员面试到底考察的是什么?是工作能力、工作经验,还是…...

液位传感器- 从零开始认识各种传感器【二十四期】
液位传感器|从零开始认识各种传感器 1、什么是液位传感器 ? 液位传感器是一种用于检测和测量液体位置和高度的装置,广泛应用于工业、农业、环保和家庭等领域。液位传感器可以实时监测液体的水平,以实现自动化控制和安全防护。 2、液位传感器…...
【c++】爬虫到底违不违法?
很多小伙伴都想知道爬虫到底违法吗,今天博主就给大家科普一下 爬虫本身并不违法,但使用爬虫采集数据可能涉及违法风险,具体取决于采集行为是否侵犯了他人的合法权益,尤其是隐私权和个人信息权。以下是对爬虫是否违法的详细分析&am…...
Python基础知识笔记——特殊符号
1. #:注释符号。在它后面的内容直到行尾都会被 Python 解释器忽略,通常用于添加注释说明代码。 2. :赋值运算符。用于将右侧的值赋给左侧的变量。 3. :等于运算符。用于比较两个值是否相等。 4. !:不等于运算符。用…...

Thinkphp仿华为商城源码/红色风格电脑手机数码商城系统网站源码
Thinkphp仿华为商城,主要实现了商品首页展示、用户意见、商品分类列表、商品搜索、商品详细展示、购物车、订单生成、在线付款、以及个人中心完善个人资料、用户修改收货地址、余额查询、消费查询、订单管理、商品评价、热销商品和最近商品浏览; 后台是…...

超有用的数据恢复方法!你一定不要错过!
无论我们当下所使用的是何种设备,例如电脑、U 盘、硬盘、相机、行车记录仪,都难以避免出现误删文件的情况。那么,这些被误删的数据究竟应当通过何种方式找回? 今日,为大家分享若干极为实用的数据恢复方法,望…...
CDH清理磁盘空间完全攻略和完整实现自动化脚本(大数据清除日志)
在CDH集群中,自动清除日志的意义非常重大。尤其是在内网环境下,运维人员无法随时登录服务器进行操作,或者是因为放长假等原因不能每天进行运维工作。这时,如果日志不自动清理,就会面临日志空间满了的问题,这可能造成CDH各组件无法正常工作,离线数仓计算完全停止。 考虑…...

vulhub:Apache解析漏洞apache_parsing
在Apache1.x/2.x中Apache 解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断。如 1.php.xxxxx 漏洞原理 Apache HTTPD 支持一个文件拥有多个后缀,并为不同后缀执行不同的指令。比如如下配置文件 AddType te…...

Raspberry Pi Docker 运行 IRIS
在 Raspberry Pi 上成功安装 Docker 后可以安装 IRIS 数据库。 安装的命令为: docker run --name my-iris -d --publish 1972:1972 --publish 52773:52773 intersystems/irishealth-community:latest-em-linux-arm64v8 注意,我们这里暴露了 2 个端口&a…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...