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

news2024/12/28 4:48:08

文章目录

    • 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 {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private 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外卖订购系统
  • 【数据结构学习】从零起步:学习数据结构的完整路径

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1835814.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI从云端到边缘:人员入侵检测算法的技术原理和视频监控方案应用

在当今数字化、智能化的时代&#xff0c;安全已成为社会发展的重要基石。特别是在一些关键领域&#xff0c;如公共安全、智能化监管以及智慧园区/社区管理等&#xff0c;确保安全无虞至关重要。而人员入侵检测AI算法作为一种先进的安全技术&#xff0c;正逐渐在这些领域发挥着不…

怎样打印微信文档文件?

在日常生活和工作中&#xff0c;我们经常需要打印微信中的文档文件&#xff0c;无论是工作资料、学习笔记还是其他重要信息。随着科技的发展&#xff0c;我们不再需要前往打印店进行繁琐的操作&#xff0c;而是可以通过一些便捷的在线打印平台轻松实现。今天&#xff0c;我们就…

git 快速将当前目录添加仓储

一、进入目录 git init git add . git commit -m "init" git remote add origin http://192.168.31.104/root/AutoBuildDemo.git 二、登录gitlab&#xff0c;创建项目AutoBuildDemo 最后执行&#xff1a; git push -u origin master

【C语言】--- 常见调试信息预处理器宏

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【C语言】--- 常见调试信息预处理器宏 开…

如何用Java SE数组实现高速的数字转换功能

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

技术分析:开源大模型的兴起与热门项目推荐

技术分析&#xff1a;开源大模型的兴起与热门项目推荐 引言 随着人工智能&#xff08;AI&#xff09;技术的不断发展&#xff0c;开源大模型成为了许多程序员和研究人员关注的焦点。开源项目不仅促进了技术的快速迭代和普及&#xff0c;还为更多的人提供了学习和实践的机会。…

推荐常用的三款源代码防泄密软件

三款源代码防泄密软件——安秉源代码加密、Virbox Protector 和 MapoLicensor——确实各自在源代码保护的不同方面有其专长。这些软件可以满足企业对于源代码保护的三大需求&#xff1a;防止泄露、防止反编译和防止破解。 安秉源代码加密&#xff1a; 专注于源代码文件的加密&…

惊艳视觉!7个让你大开眼界的数据可视化案例

数据可视化是指通过视觉呈现信息的一种方式&#xff0c;它仍处于不断演变的过程中。许多企业、政府和其他组织都使用数据可视化分析来寻求保持竞争优势。在界面设计中&#xff0c;数据可视化也呈现出越来越流行的趋势&#xff0c;学习数据可视化也是设计师保持竞争优势的一种方…

进程间通信以及线程的同步互斥机制

1.进程间通信机制 常用的六种通信机制&#xff1a; 管道、消息队列、共享内存、信号灯集、信号、Socket 管道&#xff08;Pipe&#xff09;和无名管道&#xff08;匿名管道&#xff09;&#xff1a; 管道是一种半双工的通信方式&#xff0c;数据只能单向流动&#xff0c;通常…

AI在医学中神奇应用

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT-3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年11月7日&#xff0c;OpenAI首届开发者大会被称为“科技界的春晚”&#xff0c;吸引了全球广大…

前端菜鸡学习日记 -- 关于pnpm

哈咯哇大家&#xff0c;我又来了&#xff0c;最近稍微悠闲一些&#xff0c;所以就趁着这个机会学习一些新的知识&#xff0c;今天就是碰巧遇到了pnm&#xff0c;这个可以看作是npm的升级版本&#xff0c;比npm要快&#xff0c;用起来也更得劲更迅速 官网地址&#xff1a;https…

jupyter使用的一个奇怪bug——SyntaxError: invalid non-printable character U+00A0

bug来由&#xff1a;从其他部分例如kaggle里复制来的代码直接粘贴在jupyter notebook里&#xff0c;每一行代码都会出现&#xff1a; Cell In[5], line 1 warnings.filterwarnings(ignore) ^ SyntaxError: invalid non-printable character U00A0 单元格 In[5]&#xff0c;第 …

Rocky Linux 更换CN镜像地址

官方镜像列表&#xff0c;下拉查找 官方镜像列表&#xff1a;https://mirrors.rockylinux.org/mirrormanager/mirrorsCN 开头的站点。 一键更改镜像地址脚本 以下是更改从默认更改到阿里云地址 cat <<EOF>>/RackyLinux_Update_repo.sh #!/bin/bash # -*- codin…

react native中基于webview的腾讯图形验证码

react native中基于webview的腾讯图形验证码 效果实例图第三方库 腾讯验证码 效果实例图 第三方库 npm i react-native-webviewreact-native-webview import React, { useEffect, useState } from react; import { StyleSheet, Text, View } from react-native; import { We…

8.12 矢量图层面要素单一符号使用二(仅渲染中心点)

文章目录 前言仅渲染中心点&#xff08;Centroid fill&#xff09;QGis设置面符号为仅渲染中心点&#xff08;Centroid fill&#xff09;二次开发代码实现仅渲染中心点&#xff08;Centroid fill&#xff09; 总结 前言 本章介绍矢量图层线要素单一符号中仅渲染中心点&#xf…

【三】【QT开发应用】VSQT和QTCreator项目互相转化的方法,QTCreator项目转化VSQT,VSQT转化为QTCreator

VSQT和QTCreator项目互相转化的方法 QTCreator项目转化VSQT 环境变量配置 将qmake.exe所在的目录添加到系统path里面. 转化命令 qmake -tp vc xxx.pro 生成.vcxproj文件 环境变量配置 将qmake.exe所在的目录路径添加到系统path中. 接着用cmd命令行转换,可能出现的问题 …

C++ 70 之 类模版中的成员函数,在类外实现

#include <iostream> #include <string> using namespace std;template<class T1, class T2> class Students10{ public:T1 m_name;T2 m_age;Students10(T1 name, T2 age); // 类内声明 类外实现// {// this->m_name name;// this->m_age …

淘宝文件系统-哈希查找分析

一.框架理解 在淘宝文件系统中&#xff0c;通常会将文件索引存储在一块内存中&#xff0c;这块内存包含了若干个主块&#xff08;Index Block&#xff09;。每个主块中存储着多个文件的索引信息。每个文件的索引按照哈希表的形式进行存储&#xff0c;通过哈希值来定位到具体的文…

QPST的使用

QPST&#xff08;Qualcomm Product Support Tool&#xff09;是一个针对高通芯片开发的传输软件。 下载软件 进行安装 安装后使用&#xff0c;QPSTConfig 可以自动抓取dump的log 使用QFile 刷机

DDPM公式推导(六)

为了整篇文章的完整性&#xff0c;给出文章剩余部分的翻译。这篇博客没有公式推导部分。 4 Experiments 我们在所有实验中设置 T 1000 T1000 T1000&#xff0c;以使采样过程中神经网络评估的次数与之前的工作 [53, 55] 相匹配。我们将前向过程的方差设置为从 β 1 1 0 − …