SpringBoot接口防抖(防重复提交)的一些实现方案
SpringBoot接口防抖(防重复提交)的一些实现方案
SpringBoot接口防抖(防重复提交)的一些实现方案
SpringBoot接口防抖(防重复提交)的一些实现方案
- 写回答
- 好问题 0 提建议
- 追加酬金
- 关注问题
- 邀请回答
-
2条回答 默认 最新
关注 引自免费微信小程序:皆我百晓生
在Spring Boot应用中实现接口防抖(防止重复提交)可以通过多种方式来实现。这里提供三种常见的实现方案:基于Redis、基于数据库和基于Spring Cloud Gateway。
- 基于Redis 利用Redis的有序集合(Sorted Set)特性来存储请求。当一个新的请求到达时,检查该请求是否已经在有序集合中存在,如果不存在,则添加并设置过期时间,否则忽略该请求。
首先,确保已经添加了Redis依赖,并配置Redis连接。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
然后创建一个配置类,用于配置RedisTemplate:
@Configuration public class RedisConfig { @Bean public LettuceConnectionFactory redisConnectionFactory() { return new LettuceConnectionFactory(); } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, String> template = new RedisTemplate<>(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
接下来,在控制器方法上添加注解,使用AOP进行拦截处理:
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; @Aspect @Component public class DuplicateRequestInterceptor { private static final String DUPLICATE_REQUEST_KEY_PATTERN = "duplicate_request:%s"; private final StringRedisTemplate stringRedisTemplate; @Autowired public DuplicateRequestInterceptor(StringRedisTemplate stringRedisTemplate) { this.stringRedisTemplate = stringRedisTemplate; } @Around("execution(* com.example.yourpackage.controller.YourController.yourMethod(..))") public Object preventDuplicateRequests(ProceedingJoinPoint joinPoint) throws Throwable { // 获取请求参数,作为唯一标识 String requestHash = generateRequestHash(joinPoint.getArgs()); long score = System.currentTimeMillis(); // 添加请求到有序集合,如果已存在则返回0 if (stringRedisTemplate.opsForZSet().add(DUPLICATE_REQUEST_KEY_PATTERN, requestHash, score) == 0) { throw new DuplicateRequestException("Duplicate request detected"); } // 执行业务逻辑 return joinPoint.proceed(); } private String generateRequestHash(Object[] args) { // 根据实际需求生成请求哈希,可以考虑将所有重要参数组合成字符串并进行哈希 StringBuilder hashBuilder = new StringBuilder(); for (Object arg : args) { hashBuilder.append(arg.toString()).append(","); } return hashBuilder.toString().hashCode() + ""; } }
-
基于数据库 使用数据库的唯一索引来防止重复插入。每次发送请求时,先查询数据库,如果数据已存在则忽略请求,否则执行操作并插入数据。
-
基于Spring Cloud Gateway 如果你的应用使用了Spring Cloud Gateway,可以在网关层实现防抖。可以编写一个GatewayFilterFactory,实现对请求的拦截和判断。
import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.web.server.ServerWebExchange; public class DuplicateRequestGatewayFilterFactory implements GatewayFilterFactory<DuplicateRequestGatewayFilterFactory.Config> { @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest(); // 获取请求参数,作为唯一标识 String requestHash = generateRequestHash(request); // 检查请求是否已在数据库中 boolean isDuplicate = checkDuplicateInDatabase(requestHash); if (isDuplicate) { throw new DuplicateRequestException("Duplicate request detected"); } return chain.filter(exchange); }; } private String generateRequestHash(ServerHttpRequest request) { // 实现根据请求头或请求体生成哈希的方法 } private boolean checkDuplicateInDatabase(String requestHash) { // 在数据库中检查请求是否存在 } public static class Config {} }
别忘了在Spring Cloud Gateway的配置文件中注册这个过滤器。
这些方法都可以有效地防止重复提交,具体选择哪种取决于你的项目需求和技术栈。注意,无论选择哪种方案,都需要考虑幂等性以及如何处理并发场景下的竞态条件。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报 编辑记录
悬赏问题
- ¥15 如何让企业微信机器人实现消息汇总整合
- ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
- ¥15 如何用Python爬取各高校教师公开的教育和工作经历
- ¥15 TLE9879QXA40 电机驱动
- ¥20 对于工程问题的非线性数学模型进行线性化
- ¥15 Mirare PLUS 进行密钥认证?(详解)
- ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
- ¥20 想用ollama做一个自己的AI数据库
- ¥15 关于qualoth编辑及缝合服装领子的问题解决方案探寻
- ¥15 请问怎么才能复现这样的图呀