发送ajax请求时由于click事件重复绑定导致的请求重复发送问题

确认删除市场活动

问题场景

项目背景:CRM练习项目,通过复选框选择列表中的数据,用户点击删除按钮,弹出确认弹窗,用户点击确认后,前端分装数据到数组,发送ajax请求,将数据传递至Controller进行处理。
JDK:jdk21.0.2
IDE:intelliJ IDEA
数据库:MariaDB10
服务器:Tomcat10
构建工具:apache-maven-3.9.6
项目地址:https://gitcode.com/weixin_44803446/crm-project/overview


问题描述

  1. ajax发送数组数据,后台接收不到的问题
    前端将选中的复选框的value值封装到数组中,在ajax中,使用data:JSON.stringify(Arry)处理并发送。前端部分JavaScript代码如下:
var checkedActivities = $("#listBody input[type='checkbox']:checked");
// 封装数据
var checkedActivitiesIdArray = [];checkedActivities.each(function () {checkedActivitiesIdArray.push(this.value);
});if(window.confirm(confirmMessage)){// 用户确认删除,发送ajax请求$.ajax({url:"deleteActivitiesByIdArray.do",type:"POST",contentType: 'application/json',data: JSON.stringify(checkedActivitiesIdArray),success:function (data) {if(data.code === "1"){// 刷新市场活动的列表$("#searchBtn").click();$("#deleteConfirmMessage").text("");}else{alert(data.message);}}});
}

后端Controller如下:

@RequestMapping("/workbench/activity/deleteActivitiesByIdArray.do")@ResponseBodypublic Object deleteActivitiesByIdArray(@RequestBody List<String> ids){System.out.println(ids);// 做了一些事情}

当这样写的时候,在运行后,一旦前端发送ajax请求,就会报IllegalStateException错误;

java.lang.IllegalStateException: No primary or single unique constructor found for interface java.util.Listat org.springframework.beans.BeanUtils.getResolvableConstructor(BeanUtils.java:265)at org.springframework.validation.DataBinder.createObject(DataBinder.java:924)at org.springframework.validation.DataBinder.construct(DataBinder.java:903)at org.springframework.web.bind.ServletRequestDataBinder.construct(ServletRequestDataBinder.java:116)at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.constructAttribute(ServletModelAttributeMethodProcessor.java:157)
  1. 使用模态框时,在前端进行删除操作的时候,有一个诡异事件,就是服务器第一次启动时,删除任务可以正常进行,但是第二次删除时,后台可以删除数据,但是前端收到的反馈确实删除失败。
    前端页面代码如下:
<!-- 删除市场活动 -->
<div class="modal fade" id="deleteActivityConfirmModal" data-backdrop="static" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title" id="staticBackdropLabel">删除市场活动</h5><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button></div><div class="modal-body"><p id="confirmMessage"></p></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button><button type="button" class="btn btn-danger" id="deleteConfirmBtn">确认删除</button></div></div></div>
</div>

JavaScript代码如下:

// 给删除按钮绑定事件$("#deleteActivitiesBtn").on("click", function () {var checkedActivities;checkedActivities = $("#listBody input[type='checkbox']:checked");if (checkedActivities.length <= 0) {alert("不可以删除空气!")return;}const confirmMessage = "您确定要删除选中的 " + checkedActivities.length + " 条数据吗?";$("#confirmMessage").text(confirmMessage);$("#deleteActivityConfirmModal").modal("show");// 给删除确认按钮添加事件$("#deleteConfirmBtn").on("click", function () {// 定义一个数组,遍历选中的复选框,将其value值装入数组中var checkedActivitiesIdArray = [];checkedActivities.each(function () {checkedActivitiesIdArray.push(this.value);});console.log(checkedActivitiesIdArray);if (checkedActivities.length === checkedActivitiesIdArray.length) {// 用户确认删除,发送ajax请求$.ajax({url: "/crm-core/workbench/activity/deleteActivitiesByIdArray.do",type: "POST",contentType: 'application/json',data: JSON.stringify(checkedActivitiesIdArray),success: function (data) {console.log("ajax发送后的数组" + checkedActivitiesIdArray);if (data.code === "1") {checkedActivitiesIdArray = [];// 刷新市场活动的列表$("#searchBtn").click();$("#confirmMessage").text("");$("#deleteActivityConfirmModal").modal("hide");} else {alert(data.message);}}});} else {console.log("请求发送有问题!")}});});

原因分析

  1. ajax发送数组数据,后台接收不到的问题原因分析:
    这个从报错信息中可以看出原因,大致意思就是说List是一个接口,Spring框架无法确定如何实例化 java.util.List 接口的实例对象,所以需要用有具体实现类的类作为参数;我在这里使用了ArrayList<String>来接收前端传递来的数组数据,经过亲自验证,使用String[]数组来接收参数也是可以的。
  2. 使用模态框时,点击一次发送两次请求的诡异问题原因分析:
    查看日志:
# 第一次发送的删除请求
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e15312a]
JDBC Connection [org.mariadb.jdbc.Connection@23c57da9] will be managed by Spring
==>  Preparing: delete from tbl_activity where id in ( ? )
==> Parameters: 13e08e9d72ac4bd7abe4203abddb6a02(String)
<==    Updates: 1
Creating a new SqlSession
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@27c6725c]
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1f9813e2]
JDBC Connection [org.mariadb.jdbc.Connection@3e9bbae4] will be managed by Spring
JDBC Connection [org.mariadb.jdbc.Connection@623508ea] will be managed by Spring
# 一次发了两个请求,其中一个还是上一次已经删除过了的数据
==>  Preparing: delete from tbl_activity where id in ( ? )
==>  Preparing: delete from tbl_activity where id in ( ? )
==> Parameters: 7ef3f93c34504922be02f3a9b1de4526(String)
==> Parameters: 13e08e9d72ac4bd7abe4203abddb6a02(String)
<==    Updates: 0
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@27c6725c]
<==    Updates: 1

查看Mybatis日志后发现,每次前端一旦点击删除确认按钮,就会在发送本次选中的删除的项目时,将前一次已经删过的数据又向后台发送了一遍,已经删除过了,所以后台肯定就会报错。由于前面使用window.confirm()时功能是正常的,所以可以断定后端代码是没有问题,问题就出在前端JavaScript中。
在查看了前面的JavaScript代码后,发现有以下问题:
将$(“#deleteConfirmBtn”).on(“click”, function () {});写在了$(“#deleteActivitiesBtn”).on(“click”, function () {});函数中,这就导致了在点击删除按钮时,内部再次为删除确认按钮绑定了点击事件。这意味着每次点击删除按钮时,都会为删除确认按钮重复添加一次事件监听器。如果多次点击删除按钮,点击删除确认按钮时会执行多次ajax请求。


解决方案:

  1. ajax发送数组数据,后台接收不到的问题解决方案:
    避免使用List<>这种接口类型作为接收前端传递的数据,可以使用ArrayList<>集合或者String[]数组来接收前端传递的数组数据
	@RequestMapping("/workbench/activity/deleteActivitiesByIdArray.do")@ResponseBodypublic Object deleteActivitiesByIdArray(@RequestBody ArrayList<String> ids){// 做了一些事情
}
	@RequestMapping("/workbench/activity/deleteActivitiesByIdArray.do")@ResponseBodypublic Object deleteActivitiesByIdArray(@RequestBody String[] ids){// 做了一些事情
}
  1. 使用模态框时,点击一次发送两次请求的诡异问题解决方案
    针对事件绑定类操作,避免嵌套,应该独立放置,否则就会导致重复绑定。调整后的JavaScript代码如下:
// 定义在外面
var checkedActivities;
var checkedActivitiesIdArray = [];
// 给删除按钮绑定事件
$("#deleteActivitiesBtn").on("click", function () {checkedActivities = $("#listBody input[type='checkbox']:checked");if (checkedActivities.length <= 0) {alert("不可以删除空气!")return;}const confirmMessage = "您确定要删除选中的 " + checkedActivities.length + " 条数据吗?";$("#confirmMessage").text(confirmMessage);$("#deleteActivityConfirmModal").modal("show");
});
// 给删除确认按钮添加事件
$("#deleteConfirmBtn").on("click", function () {// 定义一个数组,遍历选中的复选框,将其value值装入数组中checkedActivities.each(function () {checkedActivitiesIdArray.push(this.value);});console.log(checkedActivitiesIdArray);if (checkedActivities.length === checkedActivitiesIdArray.length) {// 用户确认删除,发送ajax请求$.ajax({url: "/crm-core/workbench/activity/deleteActivitiesByIdArray.do",type: "POST",contentType: 'application/json',data: JSON.stringify(checkedActivitiesIdArray),success: function (data) {console.log("ajax发送后的数组" + checkedActivitiesIdArray);if (data.code === "1") {checkedActivitiesIdArray = [];// 刷新市场活动的列表$("#searchBtn").click();$("#confirmMessage").text("");$("#deleteActivityConfirmModal").modal("hide");} else {alert(data.message);}}});} else {console.log("请求发送有问题!")}
});
});

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

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

相关文章

《计算机英语》测试练习题

作业3 一、单选题 内存条 的英文翻译是 A. memory chip (内存条通常指的是内存条上的存储芯片&#xff0c;但整个内存条的英文翻译应为 "RAM"&#xff0c;即 Random Access Memory 随机存取存储器) capacitor的中文意思是 D. 电容器 relay 的解释是 A. 继电器 por…

基于CDMA的多用户水下无线光通信(2)——系统模型和基于子空间的延时估计

本文首先介绍了基于CDMA的多用户UOWC系统模型&#xff0c;并给出了多用户收发信号的数学模型。然后介绍基于子空间的延时估计算法&#xff0c;该算法只需要已知所有用户的扩频码&#xff0c;然后根据扩频波形的循环移位在观测空间的信号子空间上的投影进行延时估计。 1、基于C…

matplotlib之savefig函数

savefig函数 Matplotlib中&#xff0c;savefig函数用于保存图形为文件。通过该函数&#xff0c;你可以将绘制的图形保存为常见的图像文件格式&#xff0c;如PNG、JPEG、SVG等。 matplotlib.pyplot.savefig(fname, dpiNone, bbox_inchestight, pad_inches0.1, formatNone, tra…

分类接口开发

文章目录 1.查询所有一级分类1.sun-club-application-controller 控制层1.SubjectCategoryController.java 定义基础的queryPrimaryCategory&#xff0c;调用领域层 2.sun-club-domain 领域层1.SubjectCategoryDomainService.java2.SubjectCategoryConverter.java3.SubjectCate…

Python 算法交易实验72 QTV200第一步: 获取原始数据并存入队列

说明 最近的数据流往前进了一步&#xff0c;我觉得基本可以开始同步的推进QTV200了。上次规划了整体的数据流&#xff0c;现在开始第一步。 内容 1 结构位置 这是上次的总体图&#xff1a; 以下是这次要实现的一小部分&#xff1a; 从结构上&#xff0c;这个是整体数据流的…

力扣-接雨水

文章目录 概要题解解释代码比较左右高度处理右侧为什么双指针法有效 概要 原题链接&#xff1a;接雨水 题解 思路&#xff1a;双指针 核心思想&#xff1a;对于任意位置 i&#xff0c;能够存储的雨水量取决于位置 i 左侧和右侧的最大高度中的较小值减去 height[i]。即 min(le…

使用MySQL WorkBbench 连接远程服务器上的mysql教程(包含踩过的坑)

最近在学习MySQL&#xff0c;想要装一个可视化程序&#xff0c;但是希望把脏活累活留给服务器&#xff0c;于是自己电脑上安装了一个MySQL Workbench作为Client。下面记录一下配置的过程。 服务器端MySQL配置 安装MySQL这里就不赘述啦&#xff0c;可以参考 https://segmentfa…

路经总和-二叉树题

112. 路径总和 - 力扣&#xff08;LeetCode&#xff09; 1、用队列 两个队列&#xff0c;先进先出 node队列存节点&#xff1b; sum队列存每条路径走到这个节点的val的总和&#xff1b; 节点和总和对应着同时存入队列&#xff0c;同时出队列&#xff1b; class Solution …

springboot+vue+mybatis旅游管理+PPT+论文+讲解+售后

随着人民生活水平的提高,旅游业已经越来越大众化,而旅游业的核心是信息,不论是对旅游管理部门、对旅游企业,或是对旅游者而言,有效的获取旅游信息,都显得特别重要.旅游管理系统将使旅游相关信息管理工作规范化、信息化、程序化,提供旅游景点、旅游线路,旅游新闻等服务本文以jsp…

压力测试Monkey命令参数和报告分析

目录 常用参数 -p <测试的包名列表> -v 显示日志详细程度 -s 伪随机数生成器的种子值 --throttle < 毫秒> --ignore-crashes 忽略崩溃 --ignore-timeouts 忽略超时 --monitor-native-crashes 监视本地崩溃代码 --ignore-security-exceptions 忽略安全异常 …

如何使用ig507金融数据库的股票接口,股票API来获取MACD指标

一、MACD指标简介 MACD&#xff08;Moving Average Convergence Divergence&#xff0c;移动平均收敛/发散&#xff09;是一种趋势跟踪动量指标&#xff0c;用于分析股票或其他金融产品的价格趋势。MACD由两部分组成&#xff1a;差离值&#xff08;DIF&#xff09;和信号线&am…

借助ChatGPT降低学术论文重复率,使用技巧全攻略,实用有效,快速上手

大家好&#xff0c;感谢关注。我是七哥&#xff0c;一个在高校里不务正业&#xff0c;折腾学术科研AI实操的学术人。可以&#xff08;yida985&#xff09;交流学术写作或ChatGPT等AI领域相关问题&#xff0c;多多交流&#xff0c;相互成就&#xff0c;共同进步。 经常有学术同…

Python编程技巧:如何正确使用with语句(Python中with用法详解)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 基本语法📝 处理文件📝 处理网络连接📝 管理线程锁📝 管理数据库连接📝 管理临时目录和文件📝 使用上下文装饰器📝 自定义上下文管理器🎯 示例1🎯 示例2📝 使用多个上下文管理器📝 上下…

Visual Studio开发环境搭建

原文&#xff1a;https://blog.c12th.cn/archives/25.html Visual Studio开发环境搭建 测试&#xff1a;笔记本原装操作系统&#xff1a;Windows 10 家庭中文版 资源分享链接&#xff1a;提取码&#xff1a;qbt2 注意事项&#xff1a;注意查看本地硬盘是否够用&#xff0c;建议…

UE5开发游戏Tutorial

文章目录 PlayerStart 初始化设置默认 LevelBP_Character 初始化BP_Character 添加动画BP_Character 攻击BP_Enemy 初始化 以及 AI 运动Camera Collision 相机碰撞BP_Character 生命以及伤害Wave Spawner 波生成UI 初始化以及 Damage Screen指定位置随机生成添加声音环境 Envir…

茴香豆的使用

RAG RAG 模型的核心在于两大部分&#xff1a;检索器&#xff08;Retriever&#xff09;和生成器&#xff08;Generator&#xff09;。检索器的作用是从一个庞大的数据集中&#xff0c;根据输入的问题或者提示&#xff0c;快速有效地检索出最相关的信息或文档。这一步骤通常利用…

【算法专题--链表】两两交换链表中的节点 -- 高频面试题(图文详解,小白一看就懂!!!)

目录 一、前言 二、题目描述 三、解题方法 ⭐双指针 -- 采用哨兵位头节点 &#x1f95d; 什么是哨兵位头节点&#xff1f; &#x1f34d; 解题思路 &#x1f34d; 案例图解 四、总结与提炼 五、共勉 一、前言 两两交换链表中的节点 这道题&#xff0c;可以说…

【LLM之KG】CoK论文阅读笔记

研究背景 大规模语言模型&#xff08;LLMs&#xff09;在许多自然语言处理&#xff08;NLP&#xff09;任务中取得了显著进展&#xff0c;特别是在零样本/少样本学习&#xff08;In-Context Learning, ICL&#xff09;方面。ICL不需要更新模型参数&#xff0c;只需利用几个标注…

网站监控定时计划任务

网站监控是一种保护网站安全和稳定性的重要手段&#xff0c;而定时计划任务则是网站监控的一种常见方法。通过设置定时计划任务&#xff0c;可以定期对网站进行监测和检测&#xff0c;及时发现并解决潜在的问题&#xff0c;从而保障网站的正常运行。 首先&#xff0c;网站监控定…

卧槽,6。套死你猴子,Tomcat访问html页面显示源码?

卧槽&#xff0c;6。Tomcat访问html页面显示源码&#xff1f; 元凶text/explain //踩坑&#xff01;&#xff01;&#xff01;不能用 servletResponse.setContentType("text/explain&#xff0c;否则访问html会看到源码&#xff0c;而不是渲染页面; charsetUTF-8"…