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

手机网站生成小程序德州企业网站建设要素

手机网站生成小程序,德州企业网站建设要素,有谁想做网站 优帮云,做课件需要的纯音乐网站Java 注解式限流教程(使用 Redis AOP) 在上一节中,我们已经实现了基于 Redis 的请求频率控制。现在我们将进一步升级功能,使用 Spring AOP 自定义注解 实现一个更优雅、可复用的限流方式 —— 即通过 RateLimiter 注解&#xf…

在这里插入图片描述

Java 注解式限流教程(使用 Redis + AOP)

在上一节中,我们已经实现了基于 Redis 的请求频率控制。现在我们将进一步升级功能,使用 Spring AOP + 自定义注解 实现一个更优雅、可复用的限流方式 —— 即通过 @RateLimiter 注解,对任意接口进行限流保护。


🧩 技术栈

  • Spring Boot 3.x
  • Redis
  • Jedis 连接池
  • Lua 脚本实现原子性操作
  • Spring AOP 实现注解式切面处理

📦 Maven 依赖配置(补充 AOP 支持)

确保你的 pom.xml 中包含以下依赖:

<!-- Spring Boot Redis -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>3.2.10</version>
</dependency><!-- Jedis 连接池 -->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>5.0.2</version>
</dependency><!-- Spring Boot AOP -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>3.2.10</version>
</dependency>

🛠️ Redis 配置(application.yml)

与之前保持一致:

spring:data:redis:host: 127.0.0.1port: 6379password: database: 1timeout: 5000msjedis:pool:max-active: 8   # 最大连接数max-idle: 4     # 最大空闲连接min-idle: 1     # 最小空闲连接max-wait: 2000ms # 获取连接最大等待时间

📁 项目结构概览

org.example.websocket.test
├── annotation
│   └── RateLimiter.java
├── aspect
│   └── RateLimiterAspect.java
├── utils
│   └── RedisRateLimiter.java
├── config
│   └── RateLimiterConfig.java
└── controller└── RateLimitController.java

🔖 第一步:创建自定义限流注解

RateLimiter.java

package org.example.websocket.test.annotation;import java.lang.annotation.*;/*** 自定义限流注解,支持方法或类级别标注*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter {/*** 每个窗口内允许的最大请求数,默认10次*/int limit() default 10;/*** 窗口时间(秒),默认60秒*/int windowTime() default 60;/*** 限流维度:* - ip: 按客户端IP限流* - user: 按用户ID限流(需从参数中获取)*/String key() default "ip";
}

🧠 第二步:编写 AOP 切面逻辑

RateLimiterAspect.java

package org.example.websocket.test.aspect;import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.example.websocket.test.annotation.RateLimiter;
import org.example.websocket.test.utils.RedisRateLimiter;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import java.util.Random;@Aspect
@Component
public class RateLimiterAspect {private final RedisRateLimiter redisRateLimiter;public RateLimiterAspect(RedisRateLimiter redisRateLimiter) {this.redisRateLimiter = redisRateLimiter;}@Around("@annotation(rateLimiter)")public Object around(ProceedingJoinPoint joinPoint, RateLimiter rateLimiter) throws Throwable {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();String keyPrefix = rateLimiter.key();String dynamicKey = "";if ("ip".equals(keyPrefix)) {dynamicKey = getClientIP(request);} else if ("user".equals(keyPrefix)) {dynamicKey = request.getParameter("account");}if (dynamicKey == null || dynamicKey.isEmpty()) {return "无法识别限流标识,请检查请求参数或IP信息";}String redisKey = "rate_limit:" + keyPrefix + ":" + dynamicKey;// 执行限流判断if (!redisRateLimiter.check(redisKey, rateLimiter.limit(), rateLimiter.windowTime())) {return "请求过于频繁,请稍后再试";}// 防枚举攻击延迟try {Thread.sleep(new Random().nextInt(200));} catch (InterruptedException ignored) {}// 继续执行原方法return joinPoint.proceed();}private String getClientIP(HttpServletRequest request) {String ip = request.getHeader("X-Forwarded-For");if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}if (ip != null && ip.contains(",")) {ip = ip.split(",")[0].trim();}return ip;}
}

🧮 第三步:优化 Redis 限流工具类

RedisRateLimiter.java

package org.example.websocket.test.utils;import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;import java.util.Collections;public class RedisRateLimiter {private final StringRedisTemplate redisTemplate;public RedisRateLimiter(StringRedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;}public boolean check(String key, int limit, int expireTime) {String luaScript = buildLuaScript();DefaultRedisScript<Boolean> script = new DefaultRedisScript<>(luaScript, Boolean.class);Boolean isAllowed = redisTemplate.execute(script,Collections.singletonList(key),String.valueOf(limit), String.valueOf(expireTime));return Boolean.TRUE.equals(isAllowed);}private String buildLuaScript() {return "local key = KEYS[1]\n" +"local limit = tonumber(ARGV[1])\n" +"local expire_time = tonumber(ARGV[2])\n" +"local current = redis.call('incr', key)\n" +"if current == 1 then\n" +"    redis.call('expire', key, expire_time)\n" +"elseif current > limit then\n" +"    return false\n" +"end\n" +"return true";}
}

⚙️ 第四步:注册 RedisRateLimiter Bean

RateLimiterConfig.java

package org.example.websocket.test.config;import org.example.websocket.test.utils.RedisRateLimiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;@Configuration
public class RateLimiterConfig {@Beanpublic RedisRateLimiter redisRateLimiter(StringRedisTemplate redisTemplate) {return new RedisRateLimiter(redisTemplate);}
}

🧪 第五步:在控制器中使用注解限流

RateLimitController.java

package org.example.websocket.test.controller;import jakarta.servlet.http.HttpServletRequest;
import org.example.websocket.test.annotation.RateLimiter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class RateLimitController {// 使用注解按 IP 限流@GetMapping("/testAnnoRateLimit")@RateLimiter(limit = 10, windowTime = 60, key = "ip")public String testAnnoRateLimit(@RequestParam String account, HttpServletRequest request) {return "恭喜,请求成功放行!";}// 使用注解按用户限流@GetMapping("/testUserRateLimit")@RateLimiter(limit = 5, windowTime = 30, key = "user")public String testUserRateLimit(@RequestParam String account, HttpServletRequest request) {return "用户[" + account + "] 请求成功放行!";}
}

✅ 效果演示

当你多次快速访问 /testAnnoRateLimit 接口时,在超过设定频率后会返回:

请求过于频繁,请稍后再试

📌 总结

你现在拥有了一个 基于注解的限流系统,可以轻松地对任意接口进行限流保护。该方案具备如下优点:

特性描述
✅ 注解驱动使用 @RateLimiter 轻松启用限流
✅ 多种限流维度支持 IP、用户等多维限流
✅ Lua 原子操作Redis + Lua 保证线程安全
✅ 易于扩展后续可增加令牌桶算法、滑动窗口优化等


文章转载自:

http://DKLX3vT8.ncqzb.cn
http://q6lpkJwM.ncqzb.cn
http://UGrZWRAK.ncqzb.cn
http://n6QSTlt4.ncqzb.cn
http://YjiwfQ5Y.ncqzb.cn
http://A438i6zs.ncqzb.cn
http://3PD6NIuX.ncqzb.cn
http://Ss6p3Exc.ncqzb.cn
http://0CtSQuO2.ncqzb.cn
http://b7EYG4gz.ncqzb.cn
http://kfBGWCxh.ncqzb.cn
http://QIRRe2v6.ncqzb.cn
http://XeGD4c4Y.ncqzb.cn
http://rXHkv18s.ncqzb.cn
http://4YAlA03x.ncqzb.cn
http://Lh6LsjWf.ncqzb.cn
http://hPI9IHT1.ncqzb.cn
http://gNRnLx5U.ncqzb.cn
http://pEatliOD.ncqzb.cn
http://nUToLj0u.ncqzb.cn
http://YlMqkAX7.ncqzb.cn
http://uk9MuRkG.ncqzb.cn
http://uRAlRD5n.ncqzb.cn
http://qa3bqIqH.ncqzb.cn
http://L0VxgfQq.ncqzb.cn
http://AlHKqk1l.ncqzb.cn
http://9OwTZ1QK.ncqzb.cn
http://J93AcMtk.ncqzb.cn
http://U3YY0mDJ.ncqzb.cn
http://YNBlHB3x.ncqzb.cn
http://www.dtcms.com/wzjs/646682.html

相关文章:

  • 做网站多少钱西宁君博正规邢台规划局网站建设
  • 怎么用frontpage做网站装修设计公司取名
  • 网站模板搭建网络推广服务外包公司
  • 网站建设概念股辽宁建设工程信息网络
  • 建设银行反钓鱼网站wordpress付款后可见
  • 雅安做网站深圳企业网站建设公司
  • 网站源码完整怎样做吧网站排名做上去
  • 济南网站建设公司哪个好网站的推广方案有哪些
  • 网站标题的作用海外网站免费建设
  • 做网站的登陆功能太原建站建设
  • 网站外链作用2018年静安区品牌网站建设
  • 汕头网站建设报价物联网技术应用是学什么的
  • 梁山网站建设哪家好北京网站制作net2006
  • 太仓网站建设有限公司网站兼容代码
  • 电子商务网站功能特点如何做网站霸屏
  • 做网站用什么系统网站建设明细费用
  • 安装php和mysql网站网站建设员招聘
  • 网站建设与管理读书心得东莞本地生活网
  • 洋洋点建站简单网页制作源代码
  • 烟台网站建设团队企业网站模板免费版
  • wordpress网站缓存安装浏览器网页游戏
  • 横岗网站建设多少钱重庆最新情况 最新消息
  • 周口市住房和城乡建设局网站最好的互联网公司
  • 最好建站网站公共资源交易中心主任级别
  • 没网站怎么做二维码扫描连接做公司网站需要什么资料
  • 网站服务器安全配置保健品网站源码
  • 外贸公司手机网站中国乐清网
  • 网站后台账号密码忘记了怎么办门窗网站制作宣传语
  • 触摸屏网站建设网站地域分站怎么做
  • 旅游网官方网站建设网站对企业的重要性