防重复提交:自定义注解 + 拦截器(HandlerInterceptor)
防重复提交:自定义注解 + 拦截器(HandlerInterceptor)
一、思路:
1、首先自定义注解;
2、创建拦截器实现类(自定义类名称),拦截器(HandlerInterceptor);
3、创建类:配置拦截器路径(拦截URL规则);
二、代码示例:
1、首先自定义注解;
import java.lang.annotation.*;/*** @ClassName Resubmit* @Descripition 自定义注解-防重复提交* @Author * @Date 2023/8/31 10:38*/ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface Resubmit {/*** 默认过期时间* 单位:秒** @return*/int value() default 100;/*** 频繁请求提示语** @return*/String messge() default "请求过于频繁,请稍后再试!";}
2、创建拦截器实现类(自定义类名称),拦截器(HandlerInterceptor);
import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map;/*** @ClassName ResubmitInterceptorUtil* @Descripition 防重复提拦截器工具类* @Author * @Date 2023/8/31 10:52*/ @Slf4j @Component public class ResubmitInterceptorUtil implements HandlerInterceptor {// key: 固定前缀private static final String FIXED_SESSION = "repeatData";@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {try {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;// 请求方法Method method = handlerMethod.getMethod();// 获取自定义注解-防重复注解(@Resubmit)Resubmit annotation = method.getAnnotation(Resubmit.class);// 判断方法是否添加自定义注解(@Resubmit)if (annotation != null) {//如果重复相同数据if (repeatDataValidator(request)) {// 自定义返回结果类Result result = new Result();result.setCode(500);result.setMessage(annotation.messge());// 设置字符集编码response.setCharacterEncoding("UTF-8");// response.getWriter().write(JSON.toJSONString("请勿频繁提交请求,稍后再试."));response.getWriter().write(JSON.toJSONString(result));return false;} else {return true;}}return true;} else {return true;}} catch (IOException e) {log.error("防重复提拦截器工具类异常", e);return false;}}/*** 验证同一个url数据是否相同提交,相同返回true** @param request* @return*/private boolean repeatDataValidator(HttpServletRequest request) {// 获取POST请求体-body-入参String params = getRequestBodyParam(request);// 获取请求路径String url = request.getRequestURI();Map<String, String> map = new HashMap<>();// 组装Map key: url、 value:url+请求方法体+时间map.put(url, params);String nowUrlParams = JSON.toJSONString(map);Object preUrlParams = request.getSession().getAttribute(FIXED_SESSION);//如果上一个数据为null,表示还没有访问页面if (preUrlParams == null) {//如果上一个数据为null,表示还没有访问页面request.getSession().setAttribute(FIXED_SESSION, nowUrlParams);return false;} else {//如果上次url+数据和本次url+数据相同,则表示重复添加数据if (preUrlParams.equals(nowUrlParams)) {log.info("[请求频繁提交 repeatDataValidator URL :{}; param :{}]", url, params);return true;} else {//如果上次 url+数据 和本次url加数据不同,则不是重复提交request.getSession().setAttribute(FIXED_SESSION, nowUrlParams);return false;}}}/*** 获取请求体-body-入参** @param request* @return*/private String getRequestBodyParam(HttpServletRequest request) {BufferedReader bufferedReader = null;StringBuffer stringBuffer = new StringBuffer();try {bufferedReader = request.getReader();String str = null;while ((str = bufferedReader.readLine()) != null) {stringBuffer.append(str);}bufferedReader.close();} catch (IOException e) {log.error("解析入参异常!!!", e);} finally {if (bufferedReader != null) {try {bufferedReader.close();} catch (IOException e) {log.error("解析入参异常!!!", e);}}}return stringBuffer.toString();} }
3、创建类:配置拦截器路径(拦截URL规则);
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** @ClassName WebMvcConfig* @Descripition 配置拦截路径* @Author * @Date 2023/9/1 10:08*/ @Configuration public class WebMvcConfig implements WebMvcConfigurer {@Autowiredprivate ResubmitInterceptorUtil resubmitInterceptorUtil;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 配置拦截类registry.addInterceptor(resubmitInterceptorUtil)// 设置拦截路径URL.addPathPatterns("/**");}}
相关文章:
防重复提交:自定义注解 + 拦截器(HandlerInterceptor)
防重复提交:自定义注解 拦截器(HandlerInterceptor) 一、思路: 1、首先自定义注解; 2、创建拦截器实现类(自定义类名称),拦截器(HandlerInterceptor); 3…...

Excel中将文本格式的数值转换为数字
在使用excel时,有时需要对数字列进行各种计算,比如求平均值,我们都知道应该使用AVERAGE()函数,但是很多时候结果却“不尽如人意”。 1 问题: 使用AVERAGE函数: 结果: 可以看到单元格左上角有个…...

uni-app开发小程序中遇到的map地图的点聚合以及polygon划分区域问题
写一篇文章来记录以下我在开发小程序地图过程中遇到的两个小坑吧,一个是点聚合,用的是joinCluster这个指令,另一个是polygon在地图上划分多边形的问题: 1.首先说一下点聚合问题,由于之前没有做过小程序地图问题&#…...

【笔记】软件测试的艺术
软件测试的心理学和经济学 测试是为发现错误而执行程序的过程,所以它是一个破坏性的过程,测试是一个“施虐”的过程。 软件测试的10大原则 1、测试用例需要对预期输出的结果有明确的定义 做这件事的前提是能够提前知晓需求和效果图,如果不…...

配置本地maven
安装maven安装包 修改环境变量 vim ~/.bash_profile export JMETER_HOME/Users/yyyyjinying/apache-jmeter-5.4.1 export GOROOT/usr/local/go export GOPATH/Users/yyyyjinying/demo-file/git/backend/go export GROOVY_HOME/Users/yyyyjinying/sortware/groovy-4.0.14 exp…...
C# 按钮的AcceptButton和CancelButton属性
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System...
SMT贴片制造:专业、现代、智能的未来之选
在现代科技的快速发展下,SMT贴片制造作为电子元器件的核心工艺之一,正以其专业、现代和智能的特点成为未来的首选。 随着电子产品越来越小型化,传统的手工焊接已经无法满足高速、高精度、高稳定性的要求。而SMT贴片制造作为一种先进的表面贴…...
python sqlalchemy db.session 的commit()和colse()对session中的对象的影响
实验一:commit()之后查看stu的属性id,查看db.session是否改变 db_test.route("/db_test",methods["GET"]) def db_test():stuStuTest()stu.stu_age22stu.stu_name"nnannns"stu.stu_class11print("sessio…...

python读取图像小工具
一、和图像交互获得图像的坐标和像素值 import cv2 import numpy as np import signal import threading import timeif __name__ __main__:img cv2.imread(XXX,0)#读取图片font_face,font_scale,thicknesscv2.FONT_HERSHEY_SIMPLEX,0.5,1#鼠标交互def mouseHandler(event,x…...
【ES6】JavaScript中Reflect
Reflect是JavaScript中的一个内建对象,它提供了一组方法,用于对对象和函数进行操作和检查。这些方法与内建对象的方法非常相似,但具有更高的灵活性。 以下是Reflect对象的一些常用方法: 1、Reflect.apply(target, thisArgument,…...

Ajax + Promise复习简单小结simple
axios使用 先看看老朋友 axios axios是基于Ajaxpromise封装的 看一下他的简单使用 安装:npm install axios --save 引入:import axios from axios GitHub地址 基本使用 axios({url: http://hmajax.itheima.net/api/province}).then(function (result…...

WebDAV之π-Disk派盘 + 小书匠
小书匠是一款功能丰富,强大的知识管理工具。全平台覆盖,离线数据存储,自定义数据服务器,所见即所得的 markdown 编辑体验。 小书匠提供了多种实用的编辑模式,例如:栏编辑、双栏编辑、三栏编辑、全屏写作、全屏阅读等。并且该软件还提供了许多有用的扩展语法,比如Latex公…...

LTE ATTACH流程、PDN流程、PGW地址分配介绍
1、S-GW\P-GW选择 MME根据S-GW和P-GW的拓扑信息进行S-GW/P-GW的选择,在S-GW的候选序列和P-GW的候选序列中比较,寻找是否有合一的S-GW/P-GW,并且根据S-GW的优先级和权重信息进行排序,得到S-GW/P-GW的候选组。 2、SGW>PGW连接 PD…...

SQL sever中用户管理
目录 一、用户管理常见方法 二、用户管理方法示例 2.1. 创建登录账户: 2.1.1 检查是否创建账户成功: 2.2. 创建数据库用户: 2.2.1检查用户是否创建成功: 2.3. 授予权限: 2.3.1授予 SELECT、INSERT 和 U…...

linux————pxe网络批量装机
目录 一、概述 什么是pxe pxe组件 二、搭建交互式pxe装机 一、配置基础环境 二、配置vsftpd 三、配置tftp 四、准备pxelinx.0文件、引导文件、内核文件 一、准备pxelinux.0 二、准备引导文件、内核文件 五、配置dhcp 一、安装dhcp 二、配置dhcp 六、创建default文…...

处理时延降低24倍,联通云粒数据引擎优化实践
*作者:郑扬勇,云粒星河数据中台产品负责人 云粒智慧科技有限公司成立于 2018 年 6 月,是中国联通集团混改以来成立的首家合资公司,是中国智慧城市数智化建设者。一直以来,云粒智慧以数字化、智能化、集约化产品为核心&…...

学习MATLAB
今日,在大学慕课上找了一门关于MATLAB学习的网课,MATLAB对于我们这种自动化的学生应该是很重要的,之前也是在大三的寒假做自控的课程设计时候用到过,画一些奈奎斯特图,根轨迹图以及伯德图,但那之后也就没怎…...

React 18 对 state 进行保留和重置
参考文章 对 state 进行保留和重置 各个组件的 state 是各自独立的。根据组件在 UI 树中的位置,React 可以跟踪哪些 state 属于哪个组件。可以控制在重新渲染过程中何时对 state 进行保留和重置。 UI 树 浏览器使用许多树形结构来为 UI 建立模型。DOM 用于表示 …...

MySQL之事务与引擎
目录 一、事物 1、事务的概念 2、事务的ACID特点 3、事务之间的相互影响 4、Mysql及事务隔离级别(四种) 1、查询会话事务隔离级别 2、查询会话事务隔离级别 3、设置全局事务隔离级别 4、设置会话事务隔离级别 5、事务控制语句 6、演示 1、测试提交事务 2、测试事务回滚 4…...
Flink集群常见的监控指标
为确保能够全面、实时地监控Flink集群的运行状态和性能指标。以下是监控方案的主要组成部分: Flink集群概览:通过访问Flink的JobManager页面,您可以获取集群的总体信息,包括TaskManager的数量、任务槽位数量、运行中的作业以及已…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...