java 自定义注解方式 + spring AOP + ExpiringMap 实现限制接口请求次数

SpringBoot限制接口访问频率 - 这些错误千万不能犯 首先是定义一个注解,方便后续对不同接口使用不同的限制频率。java复制代码/*** 接口访问频率注解,默认一分钟只能访问5次*/// 限制时间 单位:秒(默认值:一分钟)// 允许请求的次数(默认值:5次)在实现逻辑这块,我们定义一个切面函数,拦截用户的request,具体实现流程和上面介绍的限流流程一致,主要涉及到redis zset的操作。java复制代码@Aspect@Component@Log4j2@Autowired// 切点。 阅读详情

ExpiringMap简介:

它具有高性能、低开销、零依赖、线程安全、使用ConcurrentMa的实现过期entries等优点。主要特点包括:过期策略、可变有效期、最大尺寸、侦听器过期、延迟输入加载、过期自省。
可设置Map中的Entry在一段时间后自动过期,key过期 value同时会过期。
可设置Map最大容纳值,当到达Maximum size后,再次插入值会导致Map中的第一个值过期。
可添加监听事件,在监听到Entry过期时调度监听函数。
可以设置懒加载,在调用get()方法时创建对象。
可以设置过期策略:
ExpirationPolicy.CREATED:在每次更新元素时,过期时间同时清零。
ExpirationPolicy.ACCESSED:在每次访问元素时,过期时间同时清零。

添加依赖

<dependency>
    <groupId>net.jodah</groupId>
    <artifactId>expiringmap</artifactId>
    <version>0.5.10</version>
</dependency>

自定义注解

package com.**.annotation;

import java.lang.annotation.*;

/**
 * @author Jeff_Wan
 * @description 控制接口访问次数
 * @date 2023/4/14
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLimit {

    /**
     * 限制的时间间隔 毫秒
     */
    long time() default 1000;

    /**
     * 限制时间内允许请求的次数
     */
    int count() default 1;
}

自定义切面AOP

package com.**.interceptor;

import com.**.Result;
import com.**.ResultCode;
import com.**.RequestLimit;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
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.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author Jeff_Wan
 * @description 自定义切面判定访问频率
 * @date 2023/4/14
 */
@Aspect
@Component
public class RequestLimitAspect {

    /**
     * 登记 book<String, ExpiringMap>
     * key -> 请求路径URI
     * value -> ExpiringMap<String, Integer>
     *          key -> 请求地址URL
     *          value -> 请求次数
     * */
    private static ConcurrentHashMap<String, ExpiringMap> book = new ConcurrentHashMap<>();

    /**
     * 定义切点 让所有标注@LimitRequest注解的方法都执行切面方法
     *
     * @param requestLimit 过期时间和最大访问次数
     */
    @Pointcut("@annotation(requestLimit)")
    public void executeService(RequestLimit requestLimit) {

    }

    /**
     * 执行方法
     *
     * @param proceedingJoinPoint 接收参数
     * @param requestLimit 过期时间和最大访问次数
     * @return 结果
     * @throws Throwable 异常
     */
    @Around("executeService(requestLimit)")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint, RequestLimit requestLimit) throws Throwable {
        // 获得request对象
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        // 获取Map对象,如果没有则返回默认值,第一个参数是key,第二个参数是默认值
        ExpiringMap<String, Integer> expiringMap = book.getOrDefault(request.getRequestURI(), ExpiringMap.builder().variableExpiration().build());
        Integer requestCount = expiringMap.getOrDefault(request.getRemoteAddr(), 0);
        // 如果请求超过次数,不执行目标方法
        if (requestCount >= requestLimit.count()) {
            return Result.failed(ResultCode.NORMAL_ERR, "请求频率太快啦,请勿重复请求");
        } else if (requestCount == 0) {
            // 第一次请求时,设置有效时间 ExpirationPolicy(过期策略),duration(持续时间), TimeUnit(时间格式: 日、时、分、秒、毫秒)
            expiringMap.put(request.getRemoteAddr(), requestCount + 1, ExpirationPolicy.CREATED, requestLimit.time(), TimeUnit.MILLISECONDS);
        } else {
            // 未超过请求次数,记录+1
            expiringMap.put(request.getRemoteAddr(), requestCount + 1);
        }
        book.put(request.getRequestURI(), expiringMap);
        // 被拦截方法的返回值
        return proceedingJoinPoint.proceed();
    }
}

ConcurrentHashMap是多线程安全的Map,它的key是接口url,value是一个多线程安全且键值对是有有效期的Map(ExpiringMap)。

ExpiringMap的key是请求的ip地址,value是已经请求的次数

示例(注解加在方法上即可)

	@RequestLimit(time = 60000)
    @PostMapping("/add")
    public Result<?> saveBusiness(@RequestBody BusinessSaveOrUpParam params) {
        boolean result = businessService.saveBusiness(params);
        return Result.judge(result);
    }

结果

在这里插入图片描述

expiringmap:一个使条目过期的高性能线程安全映射 过期地图 一种高性能、低开销、零依赖、线程安全的实现,它可以使条目过期。 功能包括: 支持 Java 6+,尽管文档为简单起见使用了 lambdas。 用法 ExpiringMap 允许您创建一个在特定时间段后或在超过最大地图大小时使条目过期的地图: Map< String> map = ExpiringMap . builder() .maxSize( 123 ) .expiration( 30 , TimeUnit . SECONDS ) .build(); // Expires after 30 seconds or as soon as a 124th element is added and this is the next one to expire based on the expiration policy map . put( 立即下载

相关推荐

汇川PLC程序框架设计:模块化分层与标准化实践指南

在工业自动化领域,可编程逻辑控制器(PLC)是设备控制的核心大脑。其编程质量直接决定了系统的稳定性、可维护性与开发效率。遵循高内聚、低耦合的软件工程原则,通过模块化分层设计,能够将复杂的控制逻辑分解为硬件驱动、设备控制、流程管理等清晰层级,并利用功能块(FB)封装可复用的设备控制逻辑。这种结构化方法的技术价值在于大幅提升代码的可读性、可测试性与团队协作效率,有效降低后期维护与功能迭代的难度。其应用场景广泛覆盖从单机设备到复杂产线的自动化项目。本文聚焦于汇川PLC平台,深入探讨如何构建一套融合了**状态机编程

weixin_29188997的博客 401

ExpiringMap:轻量级的Java缓存方式

一、ExpiringMap 具有高性能、低开销、零依赖、线程安全、使用 ConcurrentMap 的实现过期 entries 等优点。其主要特点包括:过期策略、可变有效期、最大尺寸、侦听器过期、延迟输入加载、过期自省等。

原名:@程序员大禹 3896

基于深度学习的Person Re-ID(综述)

一. 问题的提出        Person Re-ID 全称是 Person Re-Identification,又称为 行人重检测 or 行人再识别,直观上可以通过两种思路进行比对,一种是 通过 静态图像(still-image)进行特征比对,另一种是通过视频的时序特征(temporal)进行 Video Re-Id。        不管是采用 图像特征比对的方法 还是 结合时序特征比

跟随技术的脚步-linolzhang的专栏 2万+

ExpiringMap使用详解

ExpiringMap使用详解

Charge8的博客 2573

Kindle电子书DRM破解全攻略:从下载到转换的完整流程(含最新DeDRM插件配置)

本文详细介绍了如何合法移除个人购买的Kindle电子书的DRM保护,实现跨设备阅读与备份。核心内容包括使用最新DeDRM插件(如noDRM分支)配合Calibre进行配置,并针对亚马逊最新的KFX加密格式提供了密钥提取与实战操作指南。文章强调该方法仅适用于个人合理使用,旨在帮助读者真正掌控自己的数字资产。

delta的博客 576

【PCL】SolidWorks 三维建模 STL, OBJ 采样生成 PCD 点云数据(附源码)

[PCL自学篇] 一.SolidWorks三维建模STL,OBJ采样生成PCD点云数据新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 这阵子做线结构光视觉检测(轨道)项目的过程中,发现之前的许多知识点在逐渐遗忘,常言好记性

idiot5lie的博客 1万+

推荐一款高效的 Java 过期 Map 实现库: ExpiringMap

如果你在开发中需要一个可以自动过期的 Map 数据结构, 那么你可以尝试一下 ExpiringMap。 ## 项目简介 ExpiringMap 是一个轻量级、高性能的 Java 过期 Map 实现库。它提供了一种简单易用的方式来创建具有过期功能的 Map, 支持以毫秒、秒、分钟、小时或天为单位设置过期时间。 ## 主要特性 1. **自动过期** - 支持自动移除已过期的键值对。 2. *...

gitblog_00006的博客 1162

Cass三角网法土方计算优化技巧:如何根据地形特点调整边界采样间距

本文深入探讨了Cass软件中三角网法(DTM法)土方计算的优化技巧,核心在于如何根据地形的复杂程度动态调整边界采样间距。针对平坦、复杂及人工构造物等不同地形特征,提供了具体的间距调整策略与精度验证方法,旨在帮助工程师在计算精度与效率间找到最佳平衡,实现精细化土方计算。

weixin_29294975的博客 524

java实现限制接口访问次数

springboot项目下限制莫个接口在规定时间内的访问次数

f234344435的博客 9930

汽车电子电气架构演进:从分布式ECU到域集中与中央计算

汽车电子电气架构(EEA)是整车电子系统的顶层设计框架,定义了计算、通信、供电等核心要素的组织方式。其演进遵循从分布式到集中式的技术路径,旨在解决传统架构下ECU数量膨胀带来的成本、复杂度和协同难题。通过域控制器(DCU)整合功能域,以及向中央计算+区域控制架构发展,实现了硬件资源池化、软硬件解耦与高速通信。这一变革的核心技术价值在于提升算力利用率、简化线束布局、支持软件定义汽车(SDV)与持续OTA升级。在智能电动汽车时代,新架构为智能座舱、自动驾驶等复杂应用提供了可扩展的平台基础,推动了汽车产业从硬件导

weixin_30326741的博客 386

制作INCA和CANape通用的A2L

CANape和INCA通用的A2L配置与修改

赞的博客 5963

SpringBoot在一定时间内限制接口请求次数-接口防刷拦截

SpringBoot在一定时间内限制接口请求次数-接口防刷拦截

EPW云沐 2785

为 ABAP BSP 与 ICF 量身打造的错误页实践:从 CX_ROOT 到 SICF 的端到端落地指南

摘要 本文系统讲解SAP ABAP平台中BSP与ICF层的错误页定制方法。在BSP层,通过标记错误页属性和绑定ERROR_OBJECT异常对象,实现友好的错误展示与日志记录。ICF层通过SICF事务码统一配置错误页、登录与登出逻辑,支持服务树继承。文章包含可直接落地的代码示例,并针对现代Fiori架构给出演进建议,帮助开发者提升用户体验与系统安全性。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 227

java 自定义注解方式 + spring AOP 实现限制接口请求次数

java 自定义注解方式 实现限制接口请求次数 注解类RequestLimit package com.cujia.user.common.annotation; import java.lang.annotation.*; @Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RequestLimit { /** 限制的时间间隔 毫秒 */ long

weixin_45279005的博客 1091

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

spring boot限制接口访问次数

spring boot限制接口访问次数

weixin_41463944的博客 1800

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Spring控制重复请求

通过AOP拦截所有请求,控制在规定时间内请求次数。

掐指一算乀缺钱 477

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

springboot下一些小工具记录

java的一些小工具记录访问接口--指定时间限制次数网页显示资源--图片或json文件json图片提供文件下载 访问接口–指定时间限制次数 1.maven引入2个依赖 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </depen

pakchoily的博客 319

Java使用自定义注解限制接口调用频率

用来获取唯一的HashMap,其中的Value是从1970-01-01T00:00:00Z(协调世界时,UTC)到当前时间点之间的毫秒数。记录一次在公司遇到的错误:当时对接了高德的周边搜索接口开放给前端调用,但是只是过了3个小时前端就过来找我说接口报错了,我看日志发现问题是高德接口调用次数在当日已经超过了5000次所以高德做限制了,于是决定做接口我调用频率限制的代码。限制接口调用频率的方法一般都是通过时间来判断,所以最好的办法就是使用redis来记录接口调用的时间。

weixin_63020134的博客 2616

java 懒加载map_ExpiringMap用法详解

ExpiringMap用法详解ExpiringMap用法详解功能简介使用说明详细介绍1 设置过期时间与过期协议2为Map中单个元素设置过期时间3设置Map的Maximum size4过期监听事件5懒加载1.功能简介1.可设置Map中的Entry在一段时间后自动过期。2.可设置Map最大容纳值,当到达Maximum size后,再次插入值会导致Map中的第一个值过期。3.可添加监听事件,在监听到En...

weixin_42321496的博客 704

java程序内部缓存cache,ExpiringMap

@Bean(name="cache2") public Cache cache2() { return new GuavaCache("cache", CacheBuilder.newBuilder().maximumSize(30000).expireAfterWrite(2, TimeUnit.DAYS).build()); } @Autowired private Cache cache; // cache.invalidateAll();...

可爱猪猪 792

java expiringMap 替代redis 简易缓存工具

WoAiXiaoMingMing的博客 530

Java如何设置Map过期时间的的几种方法

ExpiringMap具有高性能、低开销、零依赖、线程安全、使用 ConcurrentMap 的实现过期 entries 等优点。设置 Map 中的 Entry 在一段时间后自动过期。设置 Map 最大容纳值,当到达 Max size 后,再次插入值会导致 Map 中的第一个值过期。设置 添加监听事件,在监听到 Entry 过期时调度监听函数。设置懒加载,在调用 get() 方法时创建对象。允许您了解条目预计何时过期。

不曾留得桃花影 3922

采用ExpiringMap实现锁功能

前段时间突然看到了ExpiringMap这个东西,然后上github上看了看,也查看了一些博客,觉得这东西还挺有趣的,ExpiringMap 和 map 一样,但是和map不同的是ExpiringMap可以设置key-value的过期时间,这个特性和Redis很像,Redis可以做锁,这个当然也可以做锁。然后尝试着做了做。 1 导入ExpiringMap <dependency> <groupId>net.jodah</groupId>

weixin_43885494的博客 810

expiringmap 设置key 过期时间

<dependency> <groupId>net.jodah</groupId> <artifactId>expiringmap</artifactId> <version>0.5.8</version> </dependency> ExpiringMap<...

qq_33348135的博客 1684

Java如何设置过期时间的map的几种方法

这篇文章主要介绍了Java缓存Map设置过期时间实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下前言最近项目需求需要一个类似于redis可以设置过期时间的K,V存储方式。项目前期暂时不引进redis,暂时用java内存代替。解决方案1. ExpiringMap功能简介 :1.可设置Map中的Entry在一段时间后自动过期。2.可设置Map最大容纳值,当到达Maximum size后,再次插入值会导致Map中的第一个值过期。3.可添加监听事件,在监听到

杜海的博客 7891

Java 同一IP接口QPS限制(单例)

【代码】Java 同一IP接口QPS限制(单例)

之一的博客 987
上一篇: Nacos 共享配置(shared-configs)和扩展配(extension-config)
下一篇: rabbitmq.channel方法介绍
Java_ESS
博客等级 码龄7年 97粉丝 25原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值