news 2026/4/17 18:33:42

从 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/4/18 8:56:43

计算机毕设java学校足球队信息管理系统 基于Java的校园足球队信息管理平台设计与实现 Java技术驱动的学校足球队信息管理系统开发

计算机毕设java学校足球队信息管理系统4834r9&#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。 随着互联网技术的飞速发展&#xff0c;数字化管理已成为各个领域的必然趋势。在学…

作者头像 李华
网站建设 2026/4/18 8:56:30

计算机毕业设计之jsp个人购物网站的实现

快速发展的社会中&#xff0c;人们的生活水平都在提高&#xff0c;生活节奏也在逐渐加快。为了节省时间和提高工作效率&#xff0c;越来越多的人选择利用互联网进行线上打理各种事务&#xff0c;然后线上管理系统也就相继涌现。与此同时&#xff0c;人们开始接受方便的生活方式…

作者头像 李华
网站建设 2026/4/18 5:30:58

图解AI三大核心技术:RAG、大模型、智能体

最后唠两句 为什么AI大模型成为越来越多程序员转行就业、升职加薪的首选 很简单&#xff0c;这些岗位缺人且高薪 智联招聘的最新数据给出了最直观的印证&#xff1a;2025年2月&#xff0c;AI领域求职人数同比增幅突破200% &#xff0c;远超其他行业平均水平&#xff1b;整个…

作者头像 李华
网站建设 2026/4/18 6:31:30

3D 场景灯光设计技巧详解:如何用光线营造氛围并讲好视觉故事

在 3D 场景创作中&#xff0c;灯光不仅是让物体“看得见”的工具&#xff0c;更是品牌氛围、情绪传达与叙事的核心语言。一张技术正确的渲染图&#xff0c;可能面面俱到却缺乏情感&#xff0c;而真正打动人的作品&#xff0c;多数是通过光来引导观众的感受和注意力。&#x1f3…

作者头像 李华
网站建设 2026/4/17 15:54:54

荣耀节后新品阵容曝光:笔记本、折叠屏领衔 还有平板

magic6至臻版 春节假期未至&#xff0c;荣耀2026年的首批重磅新品阵容便已浮出水面。据数码博主爆料&#xff0c;荣耀计划在春节后&#xff08;大概是3月&#xff09;推出一系列新品&#xff0c;包括两款笔记本、一款折叠屏旗舰手机及一款平板电脑&#xff0c;开启新一年的产品…

作者头像 李华