自定义注解+拦截器+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…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...
结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...
渗透实战PortSwigger Labs指南:自定义标签XSS和SVG XSS利用
阻止除自定义标签之外的所有标签 先输入一些标签测试,说是全部标签都被禁了 除了自定义的 自定义<my-tag onmouseoveralert(xss)> <my-tag idx onfocusalert(document.cookie) tabindex1> onfocus 当元素获得焦点时(如通过点击或键盘导航&…...
React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?
系列回顾: 在上一篇《React核心概念:State是什么?》中,我们学习了如何使用useState让一个组件拥有自己的内部数据(State),并通过一个计数器案例,实现了组件的自我更新。这很棒&#…...
高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。
2024 年,高端封装市场规模为 80 亿美元,预计到 2030 年将超过 280 亿美元,2024-2030 年复合年增长率为 23%。 细分到各个终端市场,最大的高端性能封装市场是“电信和基础设施”,2024 年该市场创造了超过 67% 的收入。…...
