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 ...
随机推荐
- Python第九章实验报告
一.实验对象:<零基础学Python>第九章异常处理及程序调试的实例 二.实验环境:IDLE Shell 3.9.7 三.实验目的:了解和掌握常用的异常处理语句 四.实验过程: 实例01 ...
- 后台运行&和nohup使用
这里首先先介绍一下 ctrl+z bg fg jobs 命令 下面为了观察效果,test1.sh脚本不停的输出hello ctrl + z ,会使一个正在运行的进程挂起(暂停)到后台,而且执行jobs ...
- 二叉树、B树、B*树、AVL树... 这么多树你真的搞清楚了吗?
经常在面试或者平时工作中,我们都会听到类似的树,类似于二叉树.B树.B*树.AVL树等等,很多情况下可能对他们都是只有一知半解.今天我总结了所有常见的树的原理,深入浅出的分析了其中的优缺点和注意事项, ...
- Springboot 结合 Netty 实战聊天系统
音视频技术为什么需要微服务 微服务,英文名:microservice,百度百科上将其定义为:SOA 架构的一种变体.微服务(或微服务架构)是一种将应用程序构造为一组低耦合的服务. 微服务有着一些鲜明的 ...
- 带你深入Java Log框架,彻底搞懂Log4J、Log4J2、LogBack,SLF4J
最近系统被扫出来还在使用老旧的log4j,需要升级到最新的log4j.但是在升级的发现,Java相关的日志处理库有log4j, log4j2,slf4j和logback,初一看确实有点头大,那么区别是 ...
- c#动态执行字符串脚本(优化版)
像javascript中有eval()来执行动态代码,c#中是没有的,于是自己动手丰衣足食, 先来代码 1 using System; 2 using System.Data; 3 using Sys ...
- Win11右键菜单改回传统样式
Win11右键菜单,比较不人性化,隐藏了一些常用选项,需要点"更多选项"才能显示,多次一举. 解决方法,一句话: reg.exe add "HKCU\Software\C ...
- wireshark抓包教程详解
https://blog.csdn.net/lixinkuan328/article/details/122985439 Wireshark 的抓包和分析,看这篇就够了!:https://blog.c ...
- STM32 HAL库学习(F407ZGT6) (1)-晶振/时钟树
时钟树(以F407为例) 对于 STM32F4 系列的芯片,正常工作的主频可以达到 168Mhz,但并不是所有外设都需要系统时钟这么高的频率,比如看门狗以及RTC只需要几十Khz的时钟即可.同一个 ...
- kubernetes核心实战(四)--- Deployments
6.Deployments(重点) 一个 Deployment 控制器为 Pods和 ReplicaSets提供描述性的更新方式. 描述 Deployment 中的 desired state,并且 ...