Java 开发实例:Spring Boot+AOP+注解+Redis防重复提交(防抖)

2024-06-15 02:20

本文主要是介绍Java 开发实例:Spring Boot+AOP+注解+Redis防重复提交(防抖),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 1. 环境准备
    • 2. 引入依赖
    • 3. 配置Redis
    • 4. 创建防重复提交注解
    • 5. 实现AOP切面
    • 6. 创建示例Controller
    • 7. 测试
    • 8. 进一步优化
      • 8.1 自定义异常处理
      • 8.2 提升Redis的健壮性
    • 9. 总结

在这里插入图片描述

🎉欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量


  • ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹
  • ✨博客主页:IT·陈寒的博客
  • 🎈该系列文章专栏:Java学习路线
  • 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习
  • 🍹文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
  • 📜 欢迎大家关注! ❤️

在现代Web应用中,防止重复提交是一个常见的需求。重复提交可能会导致数据一致性问题,例如重复的订单生成、数据多次插入等。本文将介绍如何使用Spring Boot、AOP、注解和Redis来实现防重复提交(防抖)功能。

在这里插入图片描述

1. 环境准备

在开始之前,我们需要准备以下开发环境:

  • JDK 1.8+
  • Maven
  • Spring Boot
  • Redis

首先,创建一个新的Spring Boot项目,可以使用Spring Initializr(https://start.spring.io/)快速生成项目结构。选择依赖项包括:Spring Web、Spring Data Redis、Lombok等。

2. 引入依赖

pom.xml中添加必要的依赖:

<dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter Data Redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- AOP --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
</dependencies>

3. 配置Redis

application.properties文件中配置Redis连接信息:

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=yourpassword

4. 创建防重复提交注解

首先,创建一个自定义注解@NoRepeatSubmit,用于标识需要防重复提交的方法:

package com.example.demo.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatSubmit {long expire() default 5; // 防重复提交时间间隔(秒)
}

5. 实现AOP切面

接下来,创建一个AOP切面类,用于拦截标注了@NoRepeatSubmit注解的方法,并检查是否重复提交:

package com.example.demo.aspect;import com.example.demo.annotation.NoRepeatSubmit;
import lombok.extern.slf4j.Slf4j;
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;import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;@Aspect
@Component
@Slf4j
public class NoRepeatSubmitAspect {@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate HttpServletRequest request;@Around("@annotation(noRepeatSubmit)")public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) throws Throwable {String key = getKey();long expireTime = noRepeatSubmit.expire();Boolean hasKey = redisTemplate.hasKey(key);if (Boolean.TRUE.equals(hasKey)) {log.warn("重复提交请求, key: {}", key);throw new RuntimeException("请勿重复提交");}redisTemplate.opsForValue().set(key, "1", expireTime, TimeUnit.SECONDS);try {return pjp.proceed();} finally {redisTemplate.delete(key);}}private String getKey() {String sessionId = request.getSession().getId();String uri = request.getRequestURI();return "noRepeatSubmit:" + sessionId + ":" + uri;}
}

在这个切面类中,我们通过@Around注解拦截所有标注了@NoRepeatSubmit注解的方法。通过Redis,我们为每个请求生成一个唯一的key,并设置一个过期时间。如果在过期时间内再次提交相同的请求,就会被拦截。

6. 创建示例Controller

创建一个简单的Controller,用于测试防重复提交功能:

package com.example.demo.controller;import com.example.demo.annotation.NoRepeatSubmit;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/test")
public class TestController {@PostMapping("/submit")@NoRepeatSubmit(expire = 10) // 设置防重复提交时间为10秒public String submit() {return "提交成功";}
}

7. 测试

启动Spring Boot应用,使用Postman或其他工具向/test/submit端点发送POST请求。第一次请求会成功,但在10秒内重复发送相同请求将会被拦截,并返回错误信息。

8. 进一步优化

8.1 自定义异常处理

为防重复提交功能添加自定义异常处理,使其返回更加友好的错误信息:

package com.example.demo.exception;import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;@ControllerAdvice
@RestController
public class GlobalExceptionHandler {@ExceptionHandler(RuntimeException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public String handleRuntimeException(RuntimeException ex) {return ex.getMessage();}
}

8.2 提升Redis的健壮性

可以进一步优化Redis的配置,如添加连接池、超时设置等,以提升系统的健壮性和性能。

spring.redis.jedis.pool.max-active=20
spring.redis.jedis.pool.max-idle=10
spring.redis.jedis.pool.min-idle=5
spring.redis.timeout=2000

9. 总结

本文详细介绍了如何使用Spring Boot、AOP、注解和Redis实现防重复提交(防抖)功能。通过自定义注解和AOP切面,我们能够方便地为指定的接口添加防重复提交功能,避免数据重复插入等问题。

这种方法不仅实现简单,而且通过Redis的高性能存储和快速读取特性,能够有效地提升系统的性能和用户体验。在实际开发中,可以根据具体需求进行进一步的优化和扩展。希望本文能对你有所帮助!


🧸结尾 ❤️ 感谢您的支持和鼓励! 😊🙏
📜您可能感兴趣的内容:

  • 【Java面试技巧】Java面试八股文 - 掌握面试必备知识(目录篇)
  • 【Java学习路线】2023年完整版Java学习路线图
  • 【AIGC人工智能】Chat GPT是什么,初学者怎么使用Chat GPT,需要注意些什么
  • 【Java实战项目】SpringBoot+SSM实战:打造高效便捷的企业级Java外卖订购系统
  • 【数据结构学习】从零起步:学习数据结构的完整路径

在这里插入图片描述

这篇关于Java 开发实例:Spring Boot+AOP+注解+Redis防重复提交(防抖)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1062161

相关文章

Java实现按字节长度截取字符串

《Java实现按字节长度截取字符串》在Java中,由于字符串可能包含多字节字符,直接按字节长度截取可能会导致乱码或截取不准确的问题,下面我们就来看看几种按字节长度截取字符串的方法吧... 目录方法一:使用String的getBytes方法方法二:指定字符编码处理方法三:更精确的字符编码处理使用示例注意事项方

Python+PyQt5开发一个Windows电脑启动项管理神器

《Python+PyQt5开发一个Windows电脑启动项管理神器》:本文主要介绍如何使用PyQt5开发一款颜值与功能并存的Windows启动项管理工具,不仅能查看/删除现有启动项,还能智能添加新... 目录开篇:为什么我们需要启动项管理工具功能全景图核心技术解析1. Windows注册表操作2. 启动文件

Spring三级缓存解决循环依赖的解析过程

《Spring三级缓存解决循环依赖的解析过程》:本文主要介绍Spring三级缓存解决循环依赖的解析过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、循环依赖场景二、三级缓存定义三、解决流程(以ServiceA和ServiceB为例)四、关键机制详解五、设计约

spring IOC的理解之原理和实现过程

《springIOC的理解之原理和实现过程》:本文主要介绍springIOC的理解之原理和实现过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、IoC 核心概念二、核心原理1. 容器架构2. 核心组件3. 工作流程三、关键实现机制1. Bean生命周期2.

Redis实现分布式锁全解析之从原理到实践过程

《Redis实现分布式锁全解析之从原理到实践过程》:本文主要介绍Redis实现分布式锁全解析之从原理到实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、背景介绍二、解决方案(一)使用 SETNX 命令(二)设置锁的过期时间(三)解决锁的误删问题(四)Re

解决tomcat启动时报Junit相关错误java.lang.ClassNotFoundException: org.junit.Test问题

《解决tomcat启动时报Junit相关错误java.lang.ClassNotFoundException:org.junit.Test问题》:本文主要介绍解决tomcat启动时报Junit相... 目录tomcat启动时报Junit相关错误Java.lang.ClassNotFoundException

Gradle下如何搭建SpringCloud分布式环境

《Gradle下如何搭建SpringCloud分布式环境》:本文主要介绍Gradle下如何搭建SpringCloud分布式环境问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Gradle下搭建SpringCloud分布式环境1.idea配置好gradle2.创建一个空的gr

JVM垃圾回收机制之GC解读

《JVM垃圾回收机制之GC解读》:本文主要介绍JVM垃圾回收机制之GC,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、死亡对象的判断算法1.1 引用计数算法1.2 可达性分析算法二、垃圾回收算法2.1 标记-清除算法2.2 复制算法2.3 标记-整理算法2.4

一文带你搞懂Redis Stream的6种消息处理模式

《一文带你搞懂RedisStream的6种消息处理模式》Redis5.0版本引入的Stream数据类型,为Redis生态带来了强大而灵活的消息队列功能,本文将为大家详细介绍RedisStream的6... 目录1. 简单消费模式(Simple Consumption)基本概念核心命令实现示例使用场景优缺点2

springboot集成Lucene的详细指南

《springboot集成Lucene的详细指南》这篇文章主要为大家详细介绍了springboot集成Lucene的详细指南,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起... 目录添加依赖创建配置类创建实体类创建索引服务类创建搜索服务类创建控制器类使用示例以下是 Spring