自定义注解 + Redis 实现业务的幂等性

1.实现幂等性思路

实现幂等性有两种方式:

⭐ 1. 在数据库层面进行幂等性处理(数据库添加唯一约束).

例如:新增用户幂等性处理,username 字段可以添加唯一约束.

⭐ 2. 在应用程序层面进行幂等性处理.

而在应用程序方面进行幂等性处理,又有两种方式:

  • 通过 Spring AOP 方式实现幂等性判断(需要额外添加依赖).
  • 通过 Spring Boot 提供的拦截器实现幂等性判断.

例如:发表评论,同一个用户可以发表相同的评论,添加唯一约束不合适,放在程序层面处理.

2. 自定义注解 + Redis 实现业务幂等性

【实现思路】

  1. 创建自定义幂等性注解.

  2. 实现自定义幂等性注解的拦截器

    1. 创建拦截器,添加幂等性判断逻辑

    2. 定义幂等性判断的 ID(两种方式)

      1. 请求方携带唯一业务 ID

      2. 后端程序自行组织唯一业务 ID:当前用户 ID + 请求的数据(此处使用第二种)

  3. 配置拦截规则

  4. 使用自定义幂等性注解来保证业务的幂等性

2.1 自定义幂等性注解

/*** 自定义幂等性判断注解** @author helong*/
@Target(ElementType.METHOD) // 方法注解
@Retention(RetentionPolicy.RUNTIME)  // 程序运行期间有效
public @interface Idempotent {/*** 幂等性判断的时效** @return*/int time() default 60;
}

2.2 实现自定义幂等性注解的拦截器

@Component
public class IdempotentInterceptor implements HandlerInterceptor {@Resourceprivate ObjectMapper objectMapper;@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 只处理控制器方法,而不处理其他类型的请求(如静态资源)if (handler instanceof HandlerMethod) {Method method = ((HandlerMethod) handler).getMethod();// 尝试获取方法上的 Idempotent 注解Idempotent idempotent = method.getAnnotation(Idempotent.class);if (ObjectUtil.isNotNull(idempotent)) {// 生成唯一业务 IDString id = createId(request);ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();// 如果 Redis 中已存在相同的业务 ID,阻止重复提交if (ObjectUtil.isNotNull(ops.get(id))) {response.setContentType("application/json;charset=UTF-8");response.setCharacterEncoding("UTF-8");String json = "{\"code\": 500, \"msg\": \"数据正在处理,请勿重复提交!\", \"data\": null}";response.getWriter().write(json);return false;} else {// 如果 Redis 中不存在相同的业务 ID,存储这个 ID 并设置过期时间ops.set(id, Boolean.TRUE.toString(), idempotent.time(), TimeUnit.SECONDS);return true;}}}// 如果不是 HandlerMethod 实例或没有 Idempotent 注解,继续处理请求return HandlerInterceptor.super.preHandle(request, response, handler);}/*** 生成幂等性 Id -> md5(用户ID + 请求参数)** @param request*/private String createId(HttpServletRequest request) throws JsonProcessingException {Long uid = NumberUtils.LONG_ZERO;// 获取当前用户的详细信息SecurityUserDetails userDetails = SecurityUtil.getCurrentUser();if (ObjectUtil.isNotNull(userDetails)) {uid = userDetails.getUid();}// 将请求参数转换为 JSON 字符串String requestParam = objectMapper.writeValueAsString(request.getParameterMap());return SecureUtil.md5(uid + requestParam);}
}

2.3 配置拦截规则

@Configuration
public class WebConfig implements WebMvcConfigurer {/*** 注入自定义拦截器*/@Resourceprivate IdempotentInterceptor idempotentInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(idempotentInterceptor)// 拦截所有的请求.addPathPatterns("/**")// 放行静态资源.excludePathPatterns("/index.html").excludePathPatterns("/login.html").excludePathPatterns("/image/**").excludePathPatterns("/js/**").excludePathPatterns("/layui/**");}
}

此处也可以不需要放行静态资源,因为上一步的自定义幂等性注解拦截器的逻辑里,第一个 if 就相当于放行了静态资源。

2.4 使用自定义幂等性注解

@PostMapping("/add")
@Idempotent
public ResponseEntity addComment(@Validated Comment comment) {comment.setUid(SecurityUtil.getCurrentUser().getUid());boolean result = commentService.save(comment);return result ? ResponseEntity.success(Boolean.TRUE) : ResponseEntity.fail("评论失败");
}

就拿发表评论来看,添加完自定义幂等性注解后,来到前端页面尝试在 1 分钟内,使用相同的用户,发表相同的评论:

PS:Security 用户对象,获取当前登录用户的代码,请参照这篇文章:SpringSecurity + JWT 实现登录认证-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1483480.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

一款由AI编写,简洁而实用的开源IP信息查看器

大家好&#xff0c;今天给大家分享一款用于查询和显示用户当前 IP 地址的轻量级项目MyIP。 MyIP提供了多种功能&#xff0c;包括IP地址查询、网络连通性检查、WebRTC连接检测、DNS泄露检查、网速测试、MTR测试等等。 使用MyIP&#xff0c;我们可以轻松地查看自己的公网IP地址&…

Linux网络——套接字与UdpServer

目录 一、socket 编程接口 1.1 sockaddr 结构 1.2 socket 常见API 二、封装 InetAddr 三、网络字节序 四、封装通用 UdpServer 服务端 4.1 整体框架 4.2 类的初始化 4.2.1 socket 4.2.2 bind 4.2.3 创建流式套接字 4.2.4 填充结构体 4.3 服务器的运行 4.3.1 rec…

迁移学习在乳腺浸润性导管癌病理图像分类中的应用

1. 引言 乳腺癌主要有两种类型:原位癌:原位癌是非常早期的癌症&#xff0c;开始在乳管中扩散&#xff0c;但没有扩散到乳房组织的其他部分。这也称为导管原位癌(DCIS)。浸润性乳腺癌:浸润性乳腺癌已经扩散(侵入)到周围的乳腺组织。侵袭性癌症比原位癌更难治愈。将乳汁输送到乳…

2024717-VSCode-1.19.1-部署gcc13-C++23-win10-22h2

2024717-VSCode-1.19.1-部署gcc13-C++23-win10-22h2 一、软件环境 标签:C++ VSCode mingw gcc13分栏:C++操作系统:Windows10 x64 22h2二、操作步骤 1. 下载安装VScode 1.1官网 打开官网【https://code.visualstudio.com/Download】,选择【System Installer】【x64】,按…

Java面试八股之什么是Redis的缓存更新

什么是Redis的缓存更新 Redis的缓存更新是指当缓存中的数据发生变化时&#xff0c;需要将这些变化同步到缓存中以保持数据的一致性。缓存更新的目的是确保缓存中的数据始终是最新的&#xff0c;以便用户可以获取到最新的数据。 常见的缓存更新策略包括&#xff1a; 直接覆盖…

AWS基础知识

VPC (Virtual Private Cloud): 参考&#xff1a;https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html With Amazon Virtual Private Cloud (Amazon VPC), you can launch AWS resources in a logically isolated virtual network that you’ve defined…

昇思25天学习打卡营第30天 | MindNLP ChatGLM-6B StreamChat

今天是第30天&#xff0c;学习了MindNLP ChatGLM-6B StreamChat。 今天是参加打卡活动的最后一天&#xff0c;经过这些日子的测试&#xff0c;昇思MindSpore效果还是不错的。 ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型&#xff0c;具有62亿参数&#xff0c;基于 …

PyTorch 深度学习实践-卷积神经网络高级篇

视频指路 参考博客笔记 参考笔记二 文章目录 上课笔记10.1GoogleNet&#xff08;Inception 层&#xff09;代码实现10.2 Residual Net代码实现 上课笔记 可以设置padding‘same’ 使输入输出大小一致 10.1GoogleNet&#xff08;Inception 层&#xff09; 说明&#xff1a;In…

【Node.js】初识 Node.js

Node.js 概念 Node.js 是一个开源与跨平台的 JavaScript运行时环境 &#xff0c;在浏览器外运行 V8 JavaScript 引擎(Google Chrome的内核)&#xff0c;利用事件驱动、非阻塞和异步输入输出 等技术提高性能。 可以理解为 Node.js就是一个服务器端的、非阻塞式 l/O 的、事件驱…

Mac 安装MySQL 配置环境变量 修改密码

文章目录 1 下载与安装2 配置环境变量3 数据库常用命令3.1 Mac使用设置管理mysql服务启停 4 数据库修改root密码4.1 知道当前密码4.2 忘记当前密码4.3 问题 参考 1 下载与安装 官网&#xff1a;https://www.mysql.com/ 找到开源下载方式 下载社区版 2 配置环境变量 对于Mac…

NVIDIA Container Toolkit 安装与配置帮助文档(Ubuntu,Docker)

NVIDIA Container Toolkit 安装与配置帮助文档(Ubuntu,Docker) 本文档详细介绍了在 Ubuntu Server 22.04 上使用 Docker 安装和配置 NVIDIA Container Toolkit 的过程。 概述 NVIDIA 容器工具包使用户能够构建和运行 GPU 加速容器。即可以在容器中使用NVIDIA显卡。 架构图如…

观测云对接 Fluentd 采集业务日志最佳实践

概述 Fluentd 是一个开源数据收集器&#xff0c;专为简化日志管理和使日志数据更加易于访问、使用而设计。作为一个高度可扩展的工具&#xff0c;它能够统一数据收集和消费过程&#xff0c;使得构建实时分析的日志系统变得更加高效。 观测云目前已集成 Fluentd &#xff0c;可…

milvus的collection操作

milvus的collection操作 创建collection import uuidfrom pymilvus import (connections,FieldSchema, CollectionSchema, DataType,Collection, )collection_name "hello_milvus" host "192.168.230.71" port 19530 username "" password…

VSCode中通过launch.json文件打断点DeBug调试代码(详细图文教程)

先吐槽 IDE编译工具调试代码是非常重要的&#xff0c;之前使用Pycharm很方便&#xff0c;直接在Configuration中配置参数就行&#xff0c;见下。使用VSCode进行有命令代码调试时相对麻烦一些&#xff0c;看其它教程没撤清楚&#xff0c;这里做个总结&#xff0c;学者耐心学习。…

01 MySQL

学习资料&#xff1a;B站视频-黑马程序员JavaWeb基础教程 文章目录 JavaWeb整体介绍 MySQL1、数据库相关概念2、MySQL3、SQL概述4、DDL:数据库操作5、DDL:表操作6、DML7、DQL8、约束9、数据库设计10、多表查询11、事务 JavaWeb整体介绍 JavaWeb Web&#xff1a;全球广域网&…

网络准入控制设备是什么?有哪些?网络准入设备臻品优选

小李&#xff1a;“小张&#xff0c;最近公司网络频繁遭遇外部攻击&#xff0c;我们得加强一下网络安全了。” 小张&#xff1a;“是啊&#xff0c;我听说实施网络准入控制是个不错的选择。但具体什么是网络准入控制设备&#xff1f;我们有哪些选择呢&#xff1f;” 小李微笑…

基于 MelosBoom ,捕获 DePIN 赛道发展红利

Melos是一个Web3音乐领域的先驱性生态&#xff0c;其允许任何人通过其工具创作音乐&#xff0c;生成的内容可以保存为NFT并进入流通&#xff0c;同时支持该音乐资产支持开放再创作。最为最具影响力以及发展潜力的Web3音乐生态&#xff0c;其不仅获得了来自于头部VC Binance Lab…

分布式缓存-Redis持久化

使用缓存的时候&#xff0c;我们经常需要对内存中的数据进行持久化&#xff08;将内存中的数据写入到硬盘中&#xff09;。 原因&#xff1a;重用数据&#xff08;比如重启机器、机器故障之后恢复数据&#xff09;&#xff0c;做数据同步&#xff08;比如 Redis 集群的主从节点…

零基础STM32单片机编程入门(十五) DHT11温湿度传感器模块实战含源码

文章目录 一.概要二.DHT11主要性能参数三.DHT11温度传感器内部框图四.DTH11模块原理图五.DHT11模块跟单片机板子接线和通讯时序1.单片机跟DHT11模块连接示意图2.单片机跟DHT11模块通讯流程与时序 六.STM32单片机DHT11温度传感器实验七.CubeMX工程源代码下载八.小结 一.概要 DH…

超声波清洗机买哪款?口碑炸裂的眼镜清洗机推荐

各位时尚潮人们、眼镜党们注意啦&#xff01;现在超声波清洗机火得一塌糊涂&#xff0c;各种品牌各种款式功能五花八门&#xff0c;但你知道吗&#xff1f;不是每一款都能名副其实&#xff0c;特别是那些便宜货&#xff0c;宣传得天花乱坠&#xff0c;拆开却发现内部只有一个破…