当前位置: 首页 > news >正文

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防重复提交(防抖)

文章目录 1. 环境准备2. 引入依赖3. 配置Redis4. 创建防重复提交注解5. 实现AOP切面6. 创建示例Controller7. 测试8. 进一步优化8.1 自定义异常处理8.2 提升Redis的健壮性 9. 总结 &#x1f389;欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨…...

使用difflib实现文件差异比较用html显示

1.默认方式&#xff0c;其中加入文本过长&#xff0c;需要换行&#xff0c;因此做 contenthtml_output.replace(</style>,table.diff td {word-wrap: break-word;white-space: pre-wrap;max-width: 100%;}</style>)&#xff0c;添加换行操作 ps&#xff1a;当前te…...

【文末附gpt升级秘笈】AI热潮降温与AGI场景普及的局限性

AI热潮降温与AGI场景普及的局限性 摘要&#xff1a; 随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;AI热一度席卷全球&#xff0c;引发了广泛的关注和讨论。然而&#xff0c;近期一些学者和行业专家对AI的发展前景提出了质疑&#xff0c;认为AI热潮将逐渐…...

Vue待学习

整个渲染过程了解 Vue实例&#xff1f;Vue模板&#xff1f;渲染函数render&#xff08;&#xff09;&#xff1f;虚拟DOM VNode?模板编译器&#xff1f;diff算法 CSS相关 CSS高级学习&#xff1f;过渡&#xff1f; 待熟悉掌握 Vue-router?VueX&#xff1f;Vue-Cli、Webpack和…...

TOP150-LC88

/*给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。注意&#xff1a;最终&#xff0c;合并后数组不…...

使用Python和TCN进行时间序列预测:一个完整的实战示例

使用Python和TCN进行时间序列预测&#xff1a;一个完整的实战示例 时间卷积网络&#xff08;TCN&#xff09;已被证明在处理序列数据方面表现出色&#xff0c;尤其是在需要捕获长期依赖关系的任务中。在本文中&#xff0c;我们将通过一个简单的例子&#xff0c;展示如何使用Py…...

如何用R语言ggplot2画高水平期刊散点图

文章目录 前言一、数据集二、ggplot2画图1、全部代码2、细节拆分1&#xff09;导包2&#xff09;创建图形对象3&#xff09;主题设置4&#xff09;轴设置5&#xff09;图例设置6&#xff09;散点颜色7&#xff09;保存图片 前言 一、数据集 数据下载链接见文章顶部 处理前的数据…...

Python基于 Jupyter Notebook 的图形可视化工具库之ipysigma使用详解

概要 在数据科学和网络分析中,图(Graph)结构是一种常用的数据结构,用于表示实体及其关系。为了方便图数据的可视化和交互操作,ipysigma 提供了一个基于 Jupyter Notebook 的图形可视化工具。通过 ipysigma,用户可以在 Jupyter Notebook 中创建、编辑和展示图结构,方便进…...

四叉树和KD树

1. 简介 四叉树和KD树都是用于空间数据索引和检索的树状数据结构。它们通过将空间递归地划分为更小的区域&#xff0c;并存储每个区域内的点&#xff0c;来实现快速搜索和范围查询。 2. 四叉树 2.1 定义 四叉树是一种树状数据结构&#xff0c;它将二维空间递归地划分为四个…...

C语言中结构体使用.与->访问成员变量的区别

文章目录 前言点运算符&#xff08;.&#xff09;箭头运算符&#xff08;->&#xff09;总结 前言 在C语言中&#xff0c;. 和 -> 都是用来访问结构体成员的运算符&#xff0c;但它们的使用场景和含义有所不同。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面…...

计算机二级Access选择题考点

在Access中&#xff0c;若要使用一个字段保存多个图像、图表、文档等文件&#xff0c;应该设置的数据类型是附件。在“销售表"中有字段:单价、数量、折扣和金额。其中&#xff0c;金额单价x数量x折扣&#xff0c;在建表时应将字段"金额"的数据类型定义为计算。若…...

人工智能历史与现状

1 人工智能历史与现状 1.1 人工智能的概念和起源 1.1.1 人工智能的概念 人工智能 (Artificial Intelligence ,AI)是一门研究如何使计算机 能够模拟人类智能行为的科学和技术,目标在于开发能够感知、理解、 学习、推理、决策和解决问题的智能机器。人工智能的概念主要包含 以…...

【git使用一】windows下git下载、安装和卸载

目录 &#xff08;1&#xff09;下载安装包 &#xff08;2&#xff09;安装git &#xff08;3&#xff09;安装验证 &#xff08;4&#xff09;卸载git &#xff08;1&#xff09;下载安装包 官网下载地址&#xff1a;Git 国内镜像下载地址&#xff1a;CNPM Binaries Mir…...

JVM 类加载器的工作原理

JVM 类加载器的工作原理 类加载器&#xff08;ClassLoader&#xff09;是一个用于加载类文件的子系统&#xff0c;负责将字节码文件&#xff08;.class 文件&#xff09;加载到 JVM 中。Java 类加载器允许 Java 应用程序在运行时动态地加载、链接和初始化类。 2. 类加载器的工…...

ARM Cortex-M4 CPU指令大全:作用、原理与实例

引言 在计算机系统中&#xff0c;CPU&#xff08;中央处理器&#xff09;是执行各种指令的核心部件。ARM Cortex-M4是广泛应用于嵌入式系统中的一款处理器&#xff0c;其指令集架构&#xff08;ISA&#xff09;基于ARMv7-M。本文将介绍ARM Cortex-M4处理器中的常见指令&#x…...

Mysql学习(九)——存储引擎

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 七、存储引擎7.1 MySQL体系结构7.2 存储引擎简介7.3 存储引擎特点7.4 存储引擎选择7.5 总结 七、存储引擎 7.1 MySQL体系结构 连接层&#xff1a;最上层是一些客户…...

TFT屏幕波形显示

REVIEW 关于TFT显示屏&#xff0c;之前已经做过彩条显示&#xff1a; TFT显示屏驱动_tft驱动-CSDN博客 关于ROM IP核&#xff0c;以及coe文件生成&#xff1a; FPGA寄存器 Vivado IP核_fpga寄存器资源-CSDN博客 1. TFT屏幕ROM显示正弦波 ①生成coe文件 %% sin-cos wave dat…...

服务器无法远程桌面连接不上的问题排查与解决方案

一、问题概述 当尝试使用远程桌面协议&#xff08;RDP&#xff09;连接至服务器时&#xff0c;如果连接失败&#xff0c;这通常意味着存在一些配置问题、网络问题或服务器本身的问题。此类问题对于管理员而言&#xff0c;需要系统地进行排查和解决。 二、排查步骤 1. 检查网…...

JAVA面试题整理——内存溢出与内存泄露的区别与联系

内存溢出与内存泄露的区别与联系 在前面jvm学习整理的时候其实用过一个简单的例子了解过内存溢出&#xff0c;在jvm内存模型章节下&#xff0c;大家有兴趣的可以去看看&#xff1a;JVM初学 GC_knowwait的博客-CSDN博客 内存溢出 内存溢出&#xff08;out of memory&#xff09…...

L50--- 104. 二叉树的最大深度(深搜)---Java版

1.题目描述 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 2.思路 这个二叉树的结构如下&#xff1a; 根节点 1 左子节点 2 右子节点 3 左子节点 4 计算过程 从根节点 1 开始计算&#xff1a; 计算左子树的最大深度&#xff1a; 根节点 2&#xf…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

aardio 自动识别验证码输入

技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”&#xff0c;于是尝试整合图像识别与网页自动化技术&#xff0c;完成了这套模拟登录流程。核心思路是&#xff1a;截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...