news 2026/6/5 2:08:40

从 0 到 1 用 Spring Boot 3 + Redis 打造一个生产级通用幂等与防重中间件(含图解 + 代码 + 案例)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从 0 到 1 用 Spring Boot 3 + Redis 打造一个生产级通用幂等与防重中间件(含图解 + 代码 + 案例)

我们来一步步实现这个生产级通用的幂等与防重中间件。核心思路是利用Redis的原子性操作(如SETNXINCR)和唯一请求令牌(Token)机制。


1. 核心概念与设计图

(1) 幂等性 (Idempotency)
  • 定义:用户对同一操作发起多次请求,其产生的效果与一次请求相同。
  • 场景:订单支付、库存扣减、表单提交等。
  • 关键:识别重复请求。
(2) 防重放 (Anti-Replay)
  • 定义:防止恶意用户捕获并重复发送有效的请求。
  • 场景:短信验证码获取、优惠券领取等。
  • 关键:限制请求频率或次数。
(3) 设计图 (简化版)
+----------------+ 1. 生成Token +----------+ | 客户端 (前端) | ---------------------> | 应用层 | +----------------+ +----------+ | | | 2. 携带Token请求业务 | 3. 校验Token (Redis) | | v v +----------------+ +----------+ | 业务API (后端) | <---------------------- | Redis | +----------------+ 4. 业务处理 & 响应 +----------+

2. 核心实现 - 幂等性Token机制

(1) Token生成服务 (IdempotentService)
@Service public class IdempotentService { @Autowired private StringRedisTemplate redisTemplate; /** * 生成幂等性Token (存储到Redis,有效期默认30分钟) * @return 唯一Token字符串 */ public String generateToken() { String token = UUID.randomUUID().toString().replace("-", ""); redisTemplate.opsForValue().set(token, "0", 30, TimeUnit.MINUTES); // 初始状态 return token; } /** * 校验Token有效性 (原子操作) * @param token 客户端传递的Token * @return true-有效且首次使用; false-无效或已使用 */ public boolean validateToken(String token) { // Lua脚本保证原子性: 检查是否存在 && 标记为已使用 String script = "if redis.call('get', KEYS[1]) == '0' then " + "redis.call('set', KEYS[1], '1') " + "return true " + "else return false end"; DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(script, Boolean.class); return Boolean.TRUE.equals(redisTemplate.execute(redisScript, Collections.singletonList(token))); } }

3. 防重放机制 - 基于时间窗口

(1) 防重服务 (AntiReplayService)
@Service public class AntiReplayService { @Autowired private StringRedisTemplate redisTemplate; /** * 检查是否允许请求 (例如:1分钟内同一用户最多3次) * @param key 防重Key (如: user:123:send_sms) * @param timeWindow 时间窗口 (秒) * @param maxCount 最大允许次数 * @return true-允许; false-超过限制 */ public boolean allowRequest(String key, long timeWindow, int maxCount) { Long count = redisTemplate.opsForValue().increment(key, 1); if (count == 1) { redisTemplate.expire(key, timeWindow, TimeUnit.SECONDS); // 设置过期 } return count != null && count <= maxCount; } }

4. 集成Spring Boot - 自定义注解与AOP

(1) 幂等注解 (@Idempotent)
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Idempotent { String tokenParam() default "token"; // 客户端传递Token的参数名 }
(2) 防重注解 (@AntiReplay)
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AntiReplay { String key() default ""; // 防重Key (支持SpEL表达式) long window() default 60; // 时间窗口 (秒) int maxCount() default 1; // 最大请求次数 }
(3) AOP切面处理 (IdempotentAspect&AntiReplayAspect)
@Aspect @Component public class IdempotentAspect { @Autowired private IdempotentService idempotentService; @Around("@annotation(idempotent)") public Object around(ProceedingJoinPoint joinPoint, Idempotent idempotent) throws Throwable { // 1. 获取请求中的Token HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); String token = request.getParameter(idempotent.tokenParam()); // 2. 校验Token if (!idempotentService.validateToken(token)) { throw new IdempotentException("重复请求或Token无效"); } // 3. 执行原方法 return joinPoint.proceed(); } }

5. 使用案例

(1) 订单创建 (幂等)
@RestController @RequestMapping("/order") public class OrderController { @Idempotent // 启用幂等校验 @PostMapping("/create") public ResponseEntity<String> createOrder(@RequestParam String token, @RequestBody OrderDTO order) { // 业务逻辑... return ResponseEntity.ok("订单创建成功"); } }
(2) 短信发送 (防重)
@RestController @RequestMapping("/sms") public class SmsController { @AntiReplay(key = "'sms:' + #phone", window = 60, maxCount = 1) @GetMapping("/send") public ResponseEntity<String> sendSms(@RequestParam String phone) { // 发送短信逻辑... return ResponseEntity.ok("验证码已发送"); } }

6. 生产级优化

  • Redis集群:使用Redisson实现分布式锁增强一致性。
  • Token存储:结合JWT携带用户信息。
  • 监控告警:记录异常日志,对接监控系统。
  • 压测:使用JMeter模拟高并发场景。

总结

通过Redis的原子操作 + 唯一Token + AOP注解,我们实现了一个轻量级、高可用的幂等与防重中间件。代码已适配Spring Boot 3,可直接集成到生产环境!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 18:50:13

机器学习 - 堆叠集成(Stacking)

摘要&#xff1a;堆叠集成&#xff08;Stacking&#xff09;是一种机器学习集成技术&#xff0c;通过分层组合多个基础模型和元模型提升预测性能。其核心流程包括&#xff1a;先用不同算法训练基础模型&#xff0c;再将它们的预测结果作为输入训练元模型&#xff0c;最终由元模…

作者头像 李华
网站建设 2026/5/20 14:34:15

横评后发现AI论文工具,千笔AI VS 文途AI,本科生写作更高效!

随着人工智能技术的迅猛发展&#xff0c;AI辅助写作工具正逐步渗透到高校学术写作场景中&#xff0c;成为本科生、研究生完成毕业论文不可或缺的得力助手。越来越多的学生开始借助这些工具来提升写作效率、降低论文压力。然而&#xff0c;面对市场上种类繁多的AI写作工具&#…

作者头像 李华
网站建设 2026/5/30 17:25:24

RAG调优全攻略:解决大模型知识库检索难题,从入门到精通的实战指南

很多开发者在搭建完基础RAG后会发现&#xff1a;虽然demo跑通了&#xff0c;但在面对复杂业务、海量知识库或口语化提问时&#xff0c;准确率往往不尽如人意。RAG应用的落地也绝非“向量数据库 大模型”那么简单。本文结合最新的行业实践与技术调优指南&#xff0c;为你深度拆…

作者头像 李华
网站建设 2026/5/22 8:48:56

别再说没出路!2026中专大数据专业毕业生的真实就业方向与起薪揭秘

中专大数据专业就业方向与薪资分析2026年中专大数据专业毕业生在就业市场上有多种选择&#xff0c;涵盖技术、运营、销售等多个领域。以下为具体方向及薪资数据&#xff0c;结合行业趋势与证书&#xff08;如CDA数据分析师&#xff09;的加持作用。技术类岗位岗位名称职责技能要…

作者头像 李华
网站建设 2026/6/1 23:35:47

手机长焦镜头技术发展史与现状

长焦是唯一真正重要的手机摄像头 手机制造商正竭尽全力在长焦镜头上投入一切&#xff0c;以期脱颖而出。 开端 某公司的Galaxy S20 Ultra并非首款配备潜望式长焦镜头的手机——某机构和另一家机构都早于这家公司——但它是在美国首款对此大肆宣传的手机。某公司对S20 Ultra的几…

作者头像 李华
网站建设 2026/6/2 14:54:53

Java:统计字符串出现次数的终极解法!

文章目录 Java&#xff1a;统计字符串出现次数的终极解法&#xff01;问题分析解决方案方案一&#xff1a;使用数组统计实现步骤&#xff1a;示例代码&#xff1a; 方案二&#xff1a;使用 HashMap 统计实现步骤&#xff1a;示例代码&#xff1a; 方案三&#xff1a;使用 Java …

作者头像 李华