当前位置: 首页 > news >正文

Spring AOP+Redis实现接口访问限制

目录

  • 一、需求
  • 二、实现思路
  • 三、代码实现
    • 3.1 导入依赖
    • 3.2 配置redis
    • 3.3 自定义注解
    • 3.4 定义切面类
    • 3.5 自定义异常类
    • 3.6 全局异常处理器

一、需求

在我们程序中,有时候需要对一些接口做访问控制,使程序更稳定,最常用的一种是通过ip限制,还有一种是通过用户名限制,也可以把一个接口限制死,在一段时间内只能访问多少次,这个根据自己需求来,不固定。在需要做限制的方法上加上一个自定义注解,用aop获取到这个方法,利用redis中的increment方法,去计数访问次数,超过访问次数,return一个自定义异常。

二、实现思路

选用的是hash结构类型去存储访问次数,用访问路径作为外层key,ip作为内层key,访问次数作为value。

  1. 首先根据id从redis中取出访问次数。
  2. 如果是第一次访问就添加到redis当中,value设置为1,如果不是第一次访问就判断是否在规定访问次数内
  3. 返回结果

三、代码实现

3.1 导入依赖

		 <!--aop依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!--redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

3.2 配置redis

声明配置类

@Configuration
public class RedisConfig {@Bean@SuppressWarnings(value = { "unchecked", "rawtypes" }) //屏蔽一些无关紧张的警告public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory connectionFactory){RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();//GenericJackson2JsonRedisSerializer比Jackson2JsonRedisSerializer效率低//GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);redisTemplate.setConnectionFactory(connectionFactory);// 使用StringRedisSerializer来序列化和反序列化redis的key值redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(jsonRedisSerializer);//Hash的key也采用StringRedisSerializer的序列化方式redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(jsonRedisSerializer);redisTemplate.afterPropertiesSet();return redisTemplate;}
}

application.yml配置

spring:# redis配置redis:host: localhostport: 6379database: 0 #默认连接0号数据库

3.3 自定义注解

/*** 接口访问频率注解,默认一分钟只能访问5次*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {long time() default 60000;  限制时间 单位:毫秒(默认值:一分钟)int value() default 5;// 允许请求的次数(默认值:5次)
}

3.4 定义切面类

@Aspect
@Component
@Slf4j
public class InterfaceLimitAspect {@Autowiredprivate RedisTemplate redisTemplate;@Pointcut("@annotation(accessLimit)")public void pt(AccessLimit accessLimit){}@Around("pt(accessLimit)")public Object Around(ProceedingJoinPoint joinPoint,AccessLimit accessLimit) throws Throwable {// 获得request对象ServletRequestAttributes sra =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = sra.getRequest();log.info(request.getRequestURI());//redis这里推荐使用hash类型,url为外层key,ip作为内层key,访问次数作为valueBoundHashOperations hashOps = redisTemplate.boundHashOps("interfaceLimit:"+request.getRequestURI());//获取ip获取接口访问次数Integer ipCount = (Integer)hashOps.get(request.getRemoteAddr());Integer count = ipCount==null?0:ipCount;//判断访问次数是否大于限制的次数if(count>=accessLimit.value()){//超过次数,不执行目标方法log.error("接口拦截:{} 请求超过限制频率【{}次/{}ms】,IP为{}",request.getRequestURI(),accessLimit.value(),accessLimit.time(),request.getRemoteAddr());throw new AccessLimitException(ResultCodeEnum.ACCESS_LIMIT);}else{//请求时,设置有效时间, 记录加一hashOps.increment(request.getRemoteAddr(),1);hashOps.expire(accessLimit.time()*5, TimeUnit.MILLISECONDS);}Object result = joinPoint.proceed();return result;}
}

3.5 自定义异常类

public class AccessLimitException extends RuntimeException{private Integer code;private String message;public Integer getCode(){return code;}public String getMessage(){return message;}public AccessLimitException(ResultCodeEnum resultCodeEnum){super(resultCodeEnum.getMessage());this.code = resultCodeEnum.getCode();this.message = resultCodeEnum.getMessage();}
}

3.6 全局异常处理器

@RestControllerAdvice
@Slf4j
public class HandlerException {@ExceptionHandler(Exception.class)public Result handle(Throwable e){log.info(e.getMessage());return Result.build(null, 507,"系统错误");}@ExceptionHandler(AccessLimitException.class)public Result AccessHandle(AccessLimitException e){log.error(e.getMessage());return Result.build(null,e.getCode(),e.getMessage());}
}

相关文章:

Spring AOP+Redis实现接口访问限制

目录 一、需求二、实现思路三、代码实现3.1 导入依赖3.2 配置redis3.3 自定义注解3.4 定义切面类3.5 自定义异常类3.6 全局异常处理器 一、需求 在我们程序中&#xff0c;有时候需要对一些接口做访问控制&#xff0c;使程序更稳定&#xff0c;最常用的一种是通过ip限制&#x…...

互联网后端技术大全!

互联网后端技术大全&#xff01; 一. 系统开发 高内聚/低耦合 高内聚 高内聚指一个软件模块是由相关性很强的代码组成&#xff0c;只负责一项任务&#xff0c;也就是常说的单一责任原则。模块的内聚反映模块内部联系的紧密程度。 低耦合 模块之间联系越紧密&#xff0c;其…...

Android SDK 上手指南||第九章 Manifest文件

第九章 Manifest文件 到目前为止&#xff0c;我们已经熟悉了Android项目中的各个组成部分&#xff0c;包括其资源。在今天的文章中&#xff0c;我们将以项目Manifest文件作为核心内容。 对于一个项目来说&#xff0c;Manifest既可以很简单、也可以很复杂&#xff0c;其具体情…...

CVE-2023-3450:锐捷 RG-BCR860 命令执行漏洞复现

锐捷 RG-BCR860 命令执行漏洞(CVE-2023-3450)复现 0x01 前言 本次测试仅供学习使用&#xff0c;如若非法他用&#xff0c;与本文作者无关&#xff0c;需自行负责&#xff01;&#xff01;&#xff01; 0x02 漏洞描述 Ruijie Networks RG-BCR860是中国锐捷网络&#xff08;R…...

【ES】elasticsearch8.3.3

这里仅实践操作并根据实际问题进行记录笔记。 运行 ES8 我们需要在自己的电脑上安装好 Docker Desktop。接着我们运行如下的命令&#xff1a;出现两个异常&#xff0c;一个是需要使用winpty因为我使用win的docker desktop&#xff0c;另外一个问题是docker启动elasticsearchE…...

2023年下半年广州/深圳软考(中/高级)认证报名,当然弘博创新

软考是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资格考试。 系统集成…...

2017. 网格游戏;2397. 被列覆盖的最多行数;2202. K 次操作后最大化顶端元素

2017. 网格游戏 核心思想&#xff1a;前缀和枚举。读完题后可以发现&#xff0c;第一个机器人走的路线就像一条分割线&#xff0c;第二个机器人只能获得上面白色部分或者下面白色部分的最大值。这个最大值怎么求&#xff0c;我们可以通过前缀和来求&#xff0c;然后通过枚举转…...

专访远航汽车远勤山:踏踏实实做好产品 直面挑战乘风远航

8月25日&#xff0c;第二十六届成都国际汽车展览会在中国西部国际博览城隆重开幕。车展举办期间&#xff0c;远航汽车董事长远勤山先生、产品研发总监王震先生向媒体分享了远航汽车品牌发展、产品研发、技术创新以及市场布局等内容。 “通过我们的付出和努力&#xff0c;让我们…...

Redis基本了解

Redis 基于内存进⾏存储&#xff0c;⽀持 key-value 的存储形式&#xff0c;底层是⽤ C 语⾔编写的。 基于 key-value 形式的数据字典&#xff0c;结构⾮常简单&#xff0c;没有数据表的概念&#xff0c;直接⽤键值对的形式完成数据的管理&#xff0c;Redis ⽀持 5 种数据类型…...

Seata处理分布式事务之1.7.0

https://blog.csdn.net/zhang33565417/article/details/122768300 1.5.0之后版本发生了很大改变 1.seata安装 1.1官网地址 http://seata.io/zh-cn/ 1.2下载地址 https://github.com/seata/seata/releases 下载的是seata-server-1.7.0.zip 1.3seata相关配置的修改 seata-…...

在k8s中用label控制Pod部署到指定的node上

案例-标注k8s-node1是配置了SSD的节点 kubectl label node k8s-node1 disktypessd 查看标记 测试 将pod部署到disktypessd的节点上&#xff08;这里设置了k8s-node1为ssd&#xff09; 部署后查看结果-副本全都运行在了k8s-node1上—符合预期 删除标记 kubectl label node k8…...

vue3 搭配ElementPlus做基础表单校验 自定义表单校验

<script setup> import { ref, reactive } from vue// 表单元素 const dom ref(null) // 校验规则 const rules {name: [{ required: true, message: 请输入活动名称, trigger: blur }],//校验手机号格式phone: [{ required: true, message: "请输入电话", t…...

Vue项目中处理key=value格式的数据-案例

返回值 {qrCode: expiredAt1693821779265&token449d599830b8486a9c7b15e0bc3f036c, listenUri: wss://ws.abcdtest.link/?token0f63c64883ed7ea338e100a28946aba654165ad0f} expiredAt1693821779265&token449d599830b8486a9c7b15e0bc3f036c 需要处理上面的字符串 co…...

如何截取视频中的一段视频?分享几种视频分割方法

当处理长视频时&#xff0c;视频分割可以使您更加高效。如果您只需要处理其中的一部分&#xff0c;而不是整个视频&#xff0c;那么分割视频可以使您更容易找到需要处理的部分。而且&#xff0c;分割视频还可以使您更容易在不同的项目之间重复使用视频片段。教大家几种简单的视…...

《Go 语言第一课》课程学习笔记(十四)

接口 认识接口类型 接口类型是由 type 和 interface 关键字定义的一组方法集合&#xff0c;其中&#xff0c;方法集合唯一确定了这个接口类型所表示的接口。type MyInterface interface {M1(int) errorM2(io.Writer, ...string) }我们在接口类型的方法集合中声明的方法&#…...

windows下配置pcl-python

1.前提概要 python版本的pcl基本上只有3.6的能用&#xff0c;本人3.7/3.8均进行了尝试。 因为很多博主提到的Gtk已经下载不了了&#xff0c;实在是维护人员太懒了。如果你看到这里&#xff0c;可以试试下面这个链接&#xff0c;说不定又能用了呢。 Gtk下载&#xff1a;http:…...

CNN详细讲解

CNN(Convolutional Neural Network) 本文主要来讲解卷积神经网络。所讲解的思路借鉴的是李宏毅老师的课程。 CNN&#xff0c;它是专门被用在影像上的。 Image Classification 我们从影像分类开始说起。 我们举例来说&#xff0c;它固定的输入大小是100*100的解析度&#x…...

pdf怎么编辑文字?了解一下这几种编辑方法

pdf怎么编辑文字&#xff1f;PDF文件的普及使得它成为了一个重要的文件格式。然而&#xff0c;由于PDF文件的特性&#xff0c;它们不可直接编辑&#xff0c;这就使得PDF文件的修改变得比较麻烦。但是&#xff0c;不用担心&#xff0c;接下来这篇文章就给大家介绍几种编辑pdf文字…...

MASM32编程状态栏显示字符动画,按钮跑马灯

一、需求分析 由于sysInfo扫描的内容比较多&#xff0c;打算为它增加一点动画效果&#xff0c;提醒用户程序正在运行&#xff0c;耐心等待。 二、构建测试窗口 测试窗口上放置有一个按钮&#xff0c;按钮上的初始文字是“开始扫描”&#xff1b;并使用状态栏&#xff0c;状态…...

Pytorch-以数字识别更好地入门深度学习

目录 一、数据介绍 二、下载数据 三、可视化数据 四、模型构建 五、模型训练 六、模型预测 一、数据介绍 MNIST数据集是深度学习入门的经典案例&#xff0c;因为它具有以下优点&#xff1a; 1. 数据量小&#xff0c;计算速度快。MNIST数据集包含60000个训练样本和1000…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...