注解实现防止重复提交(Aop)

news2024/9/22 7:42:07

一、前言

书接上回,上次实现了springboot整合redis,在使用过程中就避免不了重复提交的场景。springboot整合redis_crazyK.的博客-CSDN博客

重复提交的场景:

  • 用于用户误操作,多次点击表单提交按钮
  • 由于网速等原因造成页面卡顿,用户重复刷新提交页面
  • 恶用户如利用postman等工具重复恶意提交表单

为了防止以上情况的出现需要自定义一个注解来完成防止重复提交操作

二、实现

1.创建一个注解

/**
 * 自定义注解防止表单重复提交
 */
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatSubmit {
    int lockTime() default 5;
}

2.创建Http请求工具类,用于在切面时获取token使用

public class HttpContextUtils {
    public static HttpServletRequest httpServletRequest(){
        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
    }
}

3.项目中加入SpringAop依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

4.创建切面,将切点注册为自定义的注解,唯一表示采用接口url+token的形式,户每发起第一次添加请求,会经过界面,在切面获取信息后组装起来存入Redis,当用户后续发起请求时,首先判断Redis中是否缓存了这个key,如果缓存了,则证明已经提交,于是反馈给前端,如果不存在,证明没有提交,则存入Redis。

@Component
@Aspect
public class NoRepeatSubmitAspect {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Pointcut("@annotation(repeatSubmit)")
    public void pointcutNoRepeat(NoRepeatSubmit repeatSubmit){};
    @Around("pointcutNoRepeat(noRepeatSubmit)")
    public Object doNoRepeat(ProceedingJoinPoint point, NoRepeatSubmit noRepeatSubmit) throws Throwable {
        int i=noRepeatSubmit.lockTime();
        HttpServletRequest httpServletRequest = HttpContextUtils.httpServletRequest();
        String token = httpServletRequest.getHeader("token");
        String url = httpServletRequest.getRequestURL().toString();
        String sign = url+"/"+token;
        Boolean key=redisTemplate.hasKey(sign);
        if (key){
            throw new Exception("请勿重复提交");
        }
        redisTemplate.opsForValue().set(sign,sign,i, TimeUnit.SECONDS);
        return  point.proceed();
    }
}

三、测试

将我们自定义的注解加到对应方法上

 

先向redis中插入一条key为crazyk,value为csdn的数据

 

提交成功,然后在向redis中存入相同的数据后端会抛出我们在切面自定义的异常

 

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

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

相关文章

软考高级架构师笔记-8软件工程

目录 1. 前言 & 考情分析2. 软件工程概述3. 能力成熟度模型4. 软件过程模型4.1 敏捷模型4.2 统一过程模型(RUP)5. 逆向工程6. 需求工程7. 系统设计8. 测试基础知识9. 系统运行与维护10. 净室软件工程11. 结语1. 前言 & 考情分析 前文回顾: 软考高级架构师笔记-1计算机…

C++—指针与引用的区别与联系

一、为什么要有引用&#xff08;C语言没有&#xff09; ▪ 因为引⽤和值有⼀样的语义&#xff0c;而指针不是 ▪ 不存在空引⽤&#xff0c;必须初始化&#xff1b;保证值不变&#xff0c;保证编译器更加安全 ▪ 加减号、赋值操作符&#xff0c;作⽤在引用上会触发对象的操作符重…

PHP 人才信息与招聘系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP 人才信息与招聘系统 是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为PHP APACHE&#xff0c;数据 库为mysql5.0&#xff0c;使用php语言开发。…

Qt笔记-自定义QSet,QHash的Key

官方文档已经说得很详细了。 If you want to use other types as the key, make sure that you provide operator() and a qHash() implementation. Example:#ifndef EMPLOYEE_H#define EMPLOYEE_Hclass Employee{public:Employee() {}Employee(const QString &name, con…

在 Linux 中配置 IPv4 和 IPv6 地址详解

概要 IPv4和IPv6是Internet上常用的两种IP地址协议。在Linux系统中&#xff0c;您可以通过配置网络接口来设置IPv4和IPv6地址。本文将详细介绍如何在Linux中配置IPv4和IPv6地址。 步骤 1&#xff1a;确定网络接口 在开始配置IP地址之前&#xff0c;您需要确定要配置的网络接口…

CSDN竞赛第59期-参赛体验

CSDN竞赛第59期-参赛体验 前言介绍 体验收获反馈准备认可最后 前言 博主空空star主页空空star的主页 大家好&#xff0c;我是空空star&#xff0c;本篇给大家分享一下《CSDN竞赛第59期-参赛体验》。 介绍 CSDN竞赛 体验 我报名参加了CSDN举办的一场编程比赛&#xff0c;这是…

MacOS 升级golang版本后无法debug,升级delve版本

golang版本升级到1.20以后导致debug失效了&#xff0c;本文针对MacOS系统&#xff0c;win系统也可作参考。 WARNING: undefined behavior - version of Delve is too old for Go version 1.20.4 (maximum supported version 1.19) 1、升级delve版本 brew install delve 安装…

重命名Github的默认分支名

- 最简单的办法是在github网站直接重命名&#xff0c;但是比较危险&#xff0c;因为有很多其他人已经把这个分支拉到本地了 - 另一个办法是基于当前的主分支&#xff0c;新建一个你要重命名的目标名字的分支 - git checkout 当前主分支名 - git checkout -b 目标主分支名 - git…

CentOS 挂载ntfs格式U盘

1、查看磁盘信息 fdisk -l 如上图所示&#xff0c;可以看到插入的U盘/dev/sdc 2、查看磁盘块信息 lsblk 如上图所示&#xff0c;sdc即是插入的U盘&#xff0c;sdc1为磁盘块&#xff0c;挂载的时候使用sdc1 3、查看磁盘文件系统类型 parted -l 如上图所示&#xff0c;U盘是WD…

分布式、服务化的ERP系统架构设计

ERP之痛 曾几何时&#xff0c;我混迹于电商、珠宝行业4年多&#xff0c;为这两个行业开发过两套大型业务系统&#xff08;ERP&#xff09;。作为一个ERP系统&#xff0c;系统主要功能模块无非是订单管理、商品管理、生产采购、仓库管理、物流管理、财务管理等等。作为一个管理系…

【数据结构】单链表(超全)

目录 一、什么是链表&#xff1f;1.1 定义1.2 链表的分类 二、无头单向非循环链表2.1 结构2.2 如何遍历链表数据2.3 尾插2.4 创建新节点2.5 头插2.6 尾删2.7 头删2.8 单链表查找2.9 在pos位置之前插入2.10 删除pos位置数据2.11 在pos位置的后面插入2.12 删除pos位置后面的数据 …

Markdown学习

我展示的是一级标题 我展示的是二级标题 斜体文本 斜体文本 粗体文本 粗体文本 粗斜体文本 粗斜体文本 第一项第二项第三项 第一项第二项第三项 第一项第二项第三项 第一项&#xff1a; 第一项嵌套的第一个元素第一项嵌套的第二个元素 第二项&#xff1a; 第二项嵌套的第…

mysql 常见锁类型

表锁 & 行锁 在 MySQL 中锁的种类有很多&#xff0c;但是最基本的还是表锁和行锁&#xff1a;表锁指的是对一整张表加锁&#xff0c;一般是 DDL 处理时使用&#xff0c;也可以自己在 SQL 中指定&#xff1b;而行锁指的是锁定某一行数据或某几行&#xff0c;或行和行之间的…

ROS2 lifecycle node生命周期节点 官方例程文档翻译

0 官方例程文档 ros2 humble lifecycle demo github repo 1 引言 ROS2引入了受管理节点的概念&#xff0c;受管理的节点又被称为是生命周期节点&#xff08;LifecycleNode&#xff09;。在接下来的教程中&#xff0c;我们会解释这些节点的作用&#xff0c;是什么使得它们和普…

【Linux 驱动篇(三)】新字符设备驱动

文章目录 一、新字符设备驱动原理1. 分配和释放设备号2. 新的字符设备注册方法2.1 字符设备结构2.2 cdev_init 函数2.3 cdev_add 函数2.4 cdev_del 函数 二、自动创建设备节点1. mdev 机制2. 创建和删除类3. 创建设备4. 参考示例5. 设置文件私有数据 三、LED 灯驱动程序编写四、…

Q-Learning 原理干货讲解

强化学习 本文是强化学习和Q-Learning算法的概念及原理 项目实战案例可查看下一篇文章&#xff1a;Q-Learning 单路径吃宝箱问题–棋盘格吃宝箱问题–拓扑节点较优路径问题 一. 强化学习概述 1.1 什么是强化学习 基于环境的反馈而行动&#xff0c;通过不断与环境的交互、试错&…

AR急诊急救大平台远程专家会诊方案

随着AR技术的完善&#xff0c;在医院急救中&#xff0c;需要及时把各方面专家汇在一起会诊&#xff0c;在AR这方面有数据采集清晰&#xff0c;资料呈现方便便捷&#xff0c;针对客户需要&#xff0c;我们对业务需求分析&#xff0c;比较市面多种产品&#xff0c;把会议&#xf…

Spring Boot 中的 @Cacheable 注解

Spring Boot 中的 Cacheable 注解 在 Spring Boot 中&#xff0c;缓存是一个非常重要的话题。当我们需要频繁读取一些数据时&#xff0c;为了提高性能&#xff0c;可以将这些数据缓存起来&#xff0c;避免每次都从数据库中读取。为了实现缓存&#xff0c;Spring Boot 提供了一…

Apikit 自学日记:发起文档测试-TCP/UDP

进入某个TCP/UDP协议的API文档详情页&#xff0c;点击文档上方 测试 标签&#xff0c;即可进入 API 测试页&#xff0c;系统会根据API文档的定义的求头部、Query参数、请求体自动生成测试界面并且填充测试数据。 填写/修改请求参数 1.1设置请求参数 与发起HTTP协议测试类似&am…

Django Vue corsheaders跨域问题

跨域问题 记录一下在我自己的django-vue项目里面出现的跨域问题 我的项目之前一直是在本地跑的&#xff0c;因为需要上线测试&#xff0c;所以我就运行在同一个vlan里面 ip段&#xff1a;192.168.1.0/24 突然发现存在跨域问题&#xff0c;我django的接口访问被拦截了。 检查…