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

防重复提交:自定义注解 + 拦截器(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)

防重复提交&#xff1a;自定义注解 拦截器&#xff08;HandlerInterceptor&#xff09; 一、思路&#xff1a; 1、首先自定义注解&#xff1b; 2、创建拦截器实现类&#xff08;自定义类名称&#xff09;&#xff0c;拦截器&#xff08;HandlerInterceptor&#xff09;; 3…...

Excel中将文本格式的数值转换为数字

在使用excel时&#xff0c;有时需要对数字列进行各种计算&#xff0c;比如求平均值&#xff0c;我们都知道应该使用AVERAGE()函数&#xff0c;但是很多时候结果却“不尽如人意”。 1 问题&#xff1a; 使用AVERAGE函数&#xff1a; 结果&#xff1a; 可以看到单元格左上角有个…...

uni-app开发小程序中遇到的map地图的点聚合以及polygon划分区域问题

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

【笔记】软件测试的艺术

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

配置本地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贴片制造:专业、现代、智能的未来之选

在现代科技的快速发展下&#xff0c;SMT贴片制造作为电子元器件的核心工艺之一&#xff0c;正以其专业、现代和智能的特点成为未来的首选。 随着电子产品越来越小型化&#xff0c;传统的手工焊接已经无法满足高速、高精度、高稳定性的要求。而SMT贴片制造作为一种先进的表面贴…...

python sqlalchemy db.session 的commit()和colse()对session中的对象的影响

实验一&#xff1a;commit&#xff08;&#xff09;之后查看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中的一个内建对象&#xff0c;它提供了一组方法&#xff0c;用于对对象和函数进行操作和检查。这些方法与内建对象的方法非常相似&#xff0c;但具有更高的灵活性。 以下是Reflect对象的一些常用方法&#xff1a; 1、Reflect.apply(target, thisArgument,…...

Ajax + Promise复习简单小结simple

axios使用 先看看老朋友 axios axios是基于Ajaxpromise封装的 看一下他的简单使用 安装&#xff1a;npm install axios --save 引入&#xff1a;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的选择&#xff0c;在S-GW的候选序列和P-GW的候选序列中比较&#xff0c;寻找是否有合一的S-GW/P-GW&#xff0c;并且根据S-GW的优先级和权重信息进行排序&#xff0c;得到S-GW/P-GW的候选组。 2、SGW>PGW连接 PD…...

SQL sever中用户管理

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

linux————pxe网络批量装机

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

处理时延降低24倍,联通云粒数据引擎优化实践

*作者&#xff1a;郑扬勇&#xff0c;云粒星河数据中台产品负责人 云粒智慧科技有限公司成立于 2018 年 6 月&#xff0c;是中国联通集团混改以来成立的首家合资公司&#xff0c;是中国智慧城市数智化建设者。一直以来&#xff0c;云粒智慧以数字化、智能化、集约化产品为核心&…...

学习MATLAB

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

React 18 对 state 进行保留和重置

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

MySQL之事务与引擎

目录 一、事物 1、事务的概念 2、事务的ACID特点 3、事务之间的相互影响 4、Mysql及事务隔离级别(四种) 1、查询会话事务隔离级别 2、查询会话事务隔离级别 3、设置全局事务隔离级别 4、设置会话事务隔离级别 5、事务控制语句 6、演示 1、测试提交事务 2、测试事务回滚 4…...

Flink集群常见的监控指标

为确保能够全面、实时地监控Flink集群的运行状态和性能指标。以下是监控方案的主要组成部分&#xff1a; Flink集群概览&#xff1a;通过访问Flink的JobManager页面&#xff0c;您可以获取集群的总体信息&#xff0c;包括TaskManager的数量、任务槽位数量、运行中的作业以及已…...

Taotoken控制台提供的API Key管理与访问控制功能详解

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Taotoken控制台提供的API Key管理与访问控制功能详解 对于团队管理者或项目负责人而言&#xff0c;如何安全、高效地分发和管理大模…...

后悔没早装!iPhone装上这8个APP,生产力瞬间拉满

有了iPhone之后&#xff0c;很多人都会遇到同一个问题——软件商店里应用浩如烟海&#xff0c;到底哪些才是真正值得装的&#xff1f;有的软件看起来花里胡哨&#xff0c;装上后却很少打开&#xff1b;有的工具看似简单&#xff0c;用惯了才发现离不开了。作为一个从“有了它只…...

振弦采集模块设计:从传感器选型到数字信号处理的完整指南

1. 振弦采集读数模块&#xff1a;从物理振动到数字信号的完整旅程在工程测量、结构健康监测以及乐器数字化等领域&#xff0c;我们常常需要精确地捕捉一根弦或类似结构的振动信息。比如&#xff0c;监测桥梁拉索的张力变化、分析古筝琴弦的声学特性&#xff0c;或者检测工业设备…...

从CAN报文到转速值:手把手拆解SAE J1939-71的F004参数组(附Python解析代码)

从CAN报文到转速值&#xff1a;SAE J1939-71的F004参数组实战解析与Python实现 在汽车电子和商用车诊断领域&#xff0c;SAE J1939协议栈堪称工程师的"第二语言"。而其中J1939-71文档定义的参数组(PGN)解析&#xff0c;则是将原始CAN报文转化为工程价值的核心技能。本…...

ARM与FPGA通信接口设计:从并行总线到AXI的软硬件协同实践

1. 项目概述&#xff1a;从一次调试“事故”说起去年&#xff0c;我在一个边缘计算网关的项目上&#xff0c;遇到了一个让人头大的问题。项目核心是一块定制板&#xff0c;处理器是四核的ARM Cortex-A53&#xff0c;旁边紧挨着一片中等规模的FPGA。我们的设计是让ARM负责复杂的…...

Sunshine游戏串流:打造你自己的云端游戏主机

Sunshine游戏串流&#xff1a;打造你自己的云端游戏主机 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 想要在客厅大屏、卧室平板甚至手机上玩书房电脑里的3A大作吗&#xff1f;S…...

CLup使用:一键创建Doris存算一体集群

通过 CLup 数据库管理平台的可视化界面&#xff0c;一键自动化部署 Apache Doris 存算一体集群&#xff0c;自动完成环境检查、配置初始化、节点部署与集群注册&#xff0c;无需手动执行复杂的 FE/BE 配置与启动命令&#xff0c;大幅降低部署门槛。CLup安装部署请看&#xff1a…...

OpenClaw 架构详解:AI Agent 的编排与执行骨架

核心定位&#xff1a;OpenClaw 自动化运行时&#xff08;Automation Runtime&#xff09;&#xff0c;一个给 AI 套上安全、可控、可审计缰绳的框架。 它不追求 AI 的"惊喜"&#xff0c;而是追求可预测性、可审计性和零故障。 文章目录一、设计哲学&#xff1a;网关…...

别再从头训练了!用SAM-Adapter‘轻量化’微调,让你的分割模型快速适配新任务

SAM-Adapter&#xff1a;轻量化微调技术让图像分割模型快速适配新任务 在计算机视觉领域&#xff0c;Segment Anything Model&#xff08;SAM&#xff09;的出现无疑掀起了一场分割技术的革命。这个由Meta推出的基础模型&#xff0c;以其惊人的零样本泛化能力震撼了整个行业。然…...

观察不同模型在Taotoken平台上的实际响应速度与效果差异

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 观察不同模型在Taotoken平台上的实际响应速度与效果差异 在开发与创作过程中&#xff0c;我们常常需要调用大模型API来完成文本生成…...