SpringBoot自定义注解+AOP+redis实现防接口幂等性重复提交,从概念到实战
本文为千锋教育技术团独家创作,更多技术类知识干货,点个关注持续追更~
接口幂等性是Web开发中非常重要的一个概念,它可以保证多次调用同一个接口不会对结果产生影响。如果你想了解更多关于接口幂等性的知识,那么本文就是一个不错的起点。
在Web开发中,我们经常需要防止用户重复提交某个操作,尤其是一些需要保证数据一致性的操作,如支付等。而接口幂等性就是解决这个问题的一种方案。
接口幂等性指的是:无论调用多少次同一个接口,最终的结果都是一致的。如果接口不具备幂等性,那么多次调用可能会导致数据的不一致性,甚至产生莫名其妙的错误。**
那么,如何实现接口幂等性呢?
本文小岳将给大家介绍一种实现方案,即:使用SpringBoot自定义注解+AOP+redis来实现防接口幂等性重复提交。
1. 概念解析
1.1 接口幂等性
接口幂等性是指:同一个接口的多次调用,最终的结果都是一致的。这意味着,无论调用多少次接口,最终的结果都应该是相同的。这是因为接口的幂等性保证了多次调用接口不会对结果产生影响。
在Web开发中,保证接口幂等性非常重要。
例如, 假设我们有一个接口用来修改用户信息,那么该接口应该具备幂等性。如果用户多次调用该接口,那么最终的结果都应该是一致的,即用户信息被修改成功。如果接口不具备幂等性,那么多次调用可能会导致数据的不一致性,甚至产生莫名其妙的错误。
为了实现接口的幂等性,我们可以使用一些技术手段,例如使用Token或者在服务端存储请求的处理状态。这些技术手段可以确保同一个请求只会被处理一次,从而保证接口的幂等性。
总之,接口幂等性是Web开发中非常重要的一个概念,它可以保证多次调用同一个接口不会对结果产生影响。因此,我们在开发过程中需要注意保证接口的幂等性,以确保系统的稳定性和数据的一致性。
1.2 防重复提交
防重复提交是指系统要能够识别出用户重复提交某个操作,并且不会再次执行该操作。这是为了避免数据的不一致性和重复操作产生的问题。
在本文中,我们使用自定义注解@Idempotent、AOP和Redis来实现防接口幂等性重复提交。
当一个请求被处理过后,我们会将请求的处理状态存储到Redis中,并设置一个过期时间,以保证不会一直占用Redis的内存空间。来看示例代码:
@RestController
public class DemoController {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/demo")
@Idempotent(expire = 60)
public String demo(@RequestParam("id") Long id) {
if (redisTemplate.hasKey("demo:" + id)) {
return "请勿重复提交";
}
// 处理请求
redisTemplate.opsForValue().set("demo:" + id, "1", 60, TimeUnit.SECONDS);
return "success";
}
}
在上面的代码中,我们在demo方法上使用了自定义注解@Idempotent,并设置了过期时间为60秒。当一个请求被处理过后,我们会将请求的处理状态存储到Redis中,以保证在60秒内不会再次执行该操作。如果用户重复提交该操作,那么系统会返回请勿重复提交的提示。这样就可以有效地避免接口重复提交产生的问题。
需要注意的是,为了防止多次请求同时到达服务器,导致多次同时处理,我们需要在Redis中加锁,可以使用Redis的setnx命令或者分布式锁来实现。另外,为了保证幂等性,我们需要保证请求是幂等的,即多次请求的结果都是一致的。如果请求不是幂等的,那么我们需要对请求进行去重处理,以保证只有一个请求被处理。
2. 实现方案
2.1 自定义注解
为了实现接口的幂等性,我们需要先定义一个自定义注解。注解的作用是标记一个方法是否支持幂等性。如果支持幂等性,那么就需要对该方法进行特殊处理,使得多次调用该方法不会对结果产生影响。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {
}
2.2 AOP切面
我们可以使用AOP来判断一个方法是否被标记了@Idempotent注解。如果被标记了注解,那么就需要对该方法进行特殊处理,以实现幂等性。
@Aspect
@Component
public class IdempotentAspect {
private final RedisTemplate redisTemplate;
@Autowired
public IdempotentAspect(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Around("@annotation(com.example.demo.annotation.Idempotent)")
public Object idempotent(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取请求参数
Object[] args = joinPoint.getArgs();
// 获取请求方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 获取注解信息
Idempotent idempotent = method.getAnnotation(Idempotent.class);
String key = getKey(joinPoint);
// 判断是否已经请求过
if (redisTemplate.hasKey(key)) {
throw new RuntimeException("请勿重复提交");
}
// 标记请求已经处理过
redisTemplate.opsForValue().set(key, "1", idempotent.expire(), TimeUnit.SECONDS);
// 处理请求
return joinPoint.proceed(args);
}
/**
* 获取redis key
*/
private String getKey(ProceedingJoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
String methodName = method.getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
Object[] args = joinPoint.getArgs();
StringBuilder sb = new StringBuilder();
sb.append(className).append(":").append(methodName);
for (Object arg : args) {
sb.append(":").append(arg.toString());
}
return sb.toString();
}
}
2.3 Redis存储
我们使用Redis来存储请求的处理状态。当一个请求被处理过后,我们会将请求的处理状态存储到Redis中,并设置一个过期时间,以保证不会一直占用Redis的内存空间。
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
}
2.4 示例代码
下面是一个示例代码,该代码演示了如何使用@Idempotent注解来实现接口的幂等性。
@RestController
public class DemoController {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/demo")
@Idempotent(expire = 60)
public String demo(@RequestParam("id") Long id) {
// 处理请求
return "success";
}
}
3. 总结
本文介绍了如何使用SpringBoot自定义注解+AOP+redis来实现防接口幂等性重复提交。
我们首先定义了一个自定义注解@Idempotent,然后使用AOP来判断一个方法是否被标记了该注解。如果被标记了该注解,那么就需要对该方法进行特殊处理,以实现幂等性。最后,我们使用Redis来存储请求的处理状态,并设置一个过期时间,以保证不会一直占用Redis的内存空间。
以上就是本文的全部内容,更多技术类干货,点我主页持续追更~ 大家如果有技术类问题,欢迎和我们一起交流讨论
祝天天开心!
SpringBoot自定义注解+AOP+redis实现防接口幂等性重复提交,从概念到实战的更多相关文章
- SpringBoot使用自定义注解+AOP+Redis实现接口限流
为什么要限流 系统在设计的时候,我们会有一个系统的预估容量,长时间超过系统能承受的TPS/QPS阈值,系统有可能会被压垮,最终导致整个服务不可用.为了避免这种情况,我们就需要对接口请求进行限流. 所以 ...
- AOP+Redis锁防止表单重复提交
确保分布式锁同时满足以下四个条件 1.互斥性.在任意时刻,只有一个客户端能持有锁 2.不会发生死锁.即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁 3.具有容错性.只要 ...
- Springboot + redis + 注解 + 拦截器来实现接口幂等性校验
Springboot + redis + 注解 + 拦截器来实现接口幂等性校验 1. SpringBoot 整合篇 2. 手写一套迷你版HTTP服务器 3. 记住:永远不要在MySQL中使用UTF ...
- SpringCloud微服务实战——搭建企业级开发框架(三十九):使用Redis分布式锁(Redisson)+自定义注解+AOP实现微服务重复请求控制
通常我们可以在前端通过防抖和节流来解决短时间内请求重复提交的问题,如果因网络问题.Nginx重试机制.微服务Feign重试机制或者用户故意绕过前端防抖和节流设置,直接频繁发起请求,都会导致系统防重 ...
- ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存
基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...
- java/springboot自定义注解实现AOP
java注解 即是注释了,百度解释:也叫元数据.一种代码级别的说明. 个人理解:就是内容可以被代码理解的注释,一般是一个类. 元数据 也叫元注解,是放在被定义的一个注解类的前面 ,是对注解一种限制. ...
- 使用AOP+自定义注解完成spring boot的接口权限校验
记使用AOP+自定义注解完成接口的权限校验,代码如下: pom文件添加所需依赖: 1 <dependency> 2 <groupId>org.aspectj</group ...
- SpringBoot 自定义注解 实现多数据源
SpringBoot自定义注解实现多数据源 前置学习 需要了解 注解.Aop.SpringBoot整合Mybatis的使用. 数据准备 基础项目代码:https://gitee.com/J_look/ ...
- [技术博客] SPRINGBOOT自定义注解
SPRINGBOOT自定义注解 在springboot中,有各种各样的注解,这些注解能够简化我们的配置,提高开发效率.一般来说,springboot提供的注解已经佷丰富了,但如果我们想针对某个特定情景 ...
- JavaWeb -- Struts1 使用示例: 表单校验 防表单重复提交 表单数据封装到实体
1. struts 工作流程图 超链接 2. 入门案例 struts入门案例: 1.写一个注册页面,把请求交给 struts处理 <form action="${pageContext ...
随机推荐
- cider 二面
cider 二面 1.祖传自我介绍 2.当前BLF外卖业务缺点是什么? 产品单一 : 跟竞品比较起来,产品单一导致用户流量很少 3.QLExpress二次开发的原因 流程对接 提升性能 后台对接 4. ...
- Promise和await、同步和异步
1.同步和异步是什么: ①同步:同步是指如果一个进程在执行某个请求的时候,如果该请求需要等待一段时间,那么该进程会一直等待下去,直到收到返回信息才继续执行下去 ②异步: 指一个请求在执行某个请 ...
- SHELL-反弹shell
什么是shell? 在我们深入了解发送和接收 shell 的复杂性之前,了解 shell 实际上是什么很重要.用最简单的术语来说,shell 就是我们在与命令行环境 (CLI) 交互时使用的工具.换句 ...
- SpringBoot笔记--事件监听+启动流程+监控+项目部署
事件监听 ApplicationContextInitializer SpringApplicationRunListener ApplicationRunner CommandLineRunner ...
- Tars-Java网络编程源码分析
作者:vivo 互联网服务器团队- Jin Kai 本文从Java NIO网络编程的基础知识讲到了Tars框架使用NIO进行网络编程的源码分析. 一.Tars框架基本介绍 Tars是腾讯开源的支持多语 ...
- Docker 基础及安装
目录 一.简介 二.Docker的基本组成 三.Docker的安装 四.配置国内阿里云镜像加速 五.Hello World 上手实践 六.Docker底层原理 更多内容,前往 IT-BLOG 一.简介 ...
- 我为什么推荐Nuxt3
我为什么推荐Nuxt3? 大家好,我今天想和你们分享一个非常棒的前端框架--Nuxt3.自从我接触了Nuxt3,我发现它在前端开发领域具有很多优点.我想逐一向你们介绍Nuxt3的优势,并向大家推荐一些 ...
- Nginx主要功能
Nginx主要功能: 1.反向代理2.负载均衡3.HTTP服务器(包含动静分离)4.正向代理 一.反向代理 反向代理应该是 Nginx 做的最多的一件事了,什么是反向代理呢,以下是百度百科的说法:反向 ...
- 用 Go 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分. 示例: 输入:nums = [1,2,3,4]输出:[1,3,2,4] 注:[3,1, ...
- [大数据]sqoop安装与运用
1 文由 项目使用场景:OLTP Oracle 数据导入到 OLAP HIVE 2 Sqoop简述 Apache Sqoop(TM) 是一款开源的ETL工具,设计用于在 Apache Hadoop和结 ...