说明:本代码只是为了本人练习前后端联动技术,包含html,jquery,thymeleaf模板、ajax请求及后端功能联动,方便自己查找及使用。
@
- 代码场景
- 场景1.table批量查询功能(有默认值),点击"查询最新数据"从后台查询覆盖默认显示的数据
- 场景2.新增,点击“新建”显示form表单,提交成功后隐藏form表单
- 场景3.更新,单选一条数据->弹窗->更新值->提交->更新页面
- 场景4.删除功能
- 报错场景说明
- 1.jquery调用post请求,后台一直报400,显示:JSON Parse error: Unrecognized token
- 2.清空form表单问题,例如input和checkbox标签
- 3.引入Bootstrap和Jquery显示404找不到文件
- 4.radio对应的性别想实现,点击男,则女取消勾选,实际情况是取消勾选不了,且男女都会选中,具体如图
- 5.删除功能报错 java.util.ConcurrentModificationException: null
- 6.更新功能报错 java.util.ConcurrentModificationException: null
- 本人相关其他文章链接
代码场景
场景1.table批量查询功能(有默认值),点击"查询最新数据"从后台查询覆盖默认显示的数据
默认table展示的数据
前端代吗
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"xmlns:th="http://www.thymeleaf.org">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title></title><!--先加载css,再加载js,否则可能出错--><link th:href="@{bootstrap-3.4.1-dist/css/bootstrap.css}" rel="stylesheet" /><link th:href="@{bootstrap-3.4.1-dist/css/bootstrap-theme.css}" rel="stylesheet" /><!--切记:先加载jquery的js,再加载bootstrap.js--><script th:src="@{jquery/jquery3.6.0.js}"></script><script th:src="@{bootstrap-3.4.1-dist/js/bootstrap.js}"></script>
</head>
<body><div class="col-md-8"><button type="submit" id="getTeacherList" class="btn btn-default">查询最新的数据</button><button type="button" id="addTeacher" class="btn btn-success">新建</button><button type="button" id="updateTeacher" class="btn btn-info">修改</button><button type="button" id="deleteTeacher" class="btn btn-warning">删除</button></div><!--表格--><div id="myTable" class="bs-example col-md-8" data-example-id="hoverable-table"><table class="table table-hover" ><thead><tr><th><input type="checkbox" value="" id="mycheckbox"></th><th>#</th><th>姓名</th><th>班级</th><th>所属学院</th><th>别名</th><th>性别</th></tr></thead><tbody id="myTbody1"><tr><th><input type="checkbox" value=""></th><th scope="row">1</th><td>Mark</td><td>Otto</td><td>@mdo</td><td>Otto</td><td>男</td></tr><tr><th><input type="checkbox" value=""></th><th scope="row">2</th><td>Jacob</td><td>Thornton</td><td>@fat</td><td>Thornton</td><td>女</td></tr><tr><th><input type="checkbox" value=""></th><th scope="row">3</th><td>Larry</td><td>the Bird</td><td>@twitter</td><td>the Bird</td><td>女</td></tr></tbody></table></table></div>
</body>
<script type="text/javascript">//查询$("#getTeacherList").click(function () {var params = {};$.ajax({type:"GET",url:"/getTeacherList",async: true,dataType: "json",data: params,contentType: "application/json; charset=UTF-8",success : function (response) {if (response.code === 200) {//清空table内容$("#myTbody1").html("");var tr;$.each(response.info, function (index, value) {tr = tr + ["<tr>","<th><input type='checkbox' value=''></th>","<th scope='row'>"+ value.id +"</th>","<td>"+ value.name +"</td>","<td>"+ value.classes +"</td>","<td>"+ value.college +"</td>","<td>"+ value.alias +"</td>",];if (value.sex === 0) {tr = tr + "<td> 女 </td>";} else {tr = tr + "<td> 男</td>";}$("#myTbody1").append("</tr><tr>");});$("#myTbody1").append(tr);}}});});
</script>
</html>
后端代码
PracticeControllerpackage com.example.demo.controller;import com.example.demo.bean.Teacher;
import com.example.demo.response.Response;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;/*** @Author 211145187* @Date 2022/2/25 13:54**/
@Controller
public class PracticeController {private ConcurrentHashMap<String, List<Teacher>> cache = new ConcurrentHashMap<>();//首页@GetMapping(value = "")public String index() {return "index";}@PostConstructpublic void initCache() {List<Teacher> teacherList = new ArrayList<>();Teacher teacher1 = new Teacher();teacher1.setId(1);teacher1.setName("周杰伦");teacher1.setClasses("三年二班");teacher1.setCollege("魔法学院");teacher1.setAlias("Jay Chou");teacher1.setSex(1);teacherList.add(teacher1);Teacher teacher2 = new Teacher();teacher2.setId(2);teacher2.setName("丽萨");teacher2.setClasses("三年二班");teacher2.setCollege("魔法学院");teacher2.setAlias("Lisa");teacher2.setSex(0);teacherList.add(teacher2);cache.put("list", teacherList);}//查询@GetMapping(value = "/getTeacherList")@ResponseBodypublic Response<List<Teacher>> getTeacherList(Model model) {List<Teacher> teacherList = cache.get("list");model.addAttribute("teacherList", teacherList);model.addAttribute("flag", true);teacherList.stream().forEach(System.out::println);return Response.success(teacherList);}
}
-----------------------------------------------------------------------------------------------
Teacherpackage com.example.demo.bean;import lombok.Data;/*** @Author 211145187* @Date 2022/2/23 09:32**/
@Data
public class Teacher {//idprivate Integer id;//姓名private String name;//班级private String classes;//所属学院private String college;//别名private String alias;//性别【0:女 1:男】private Integer sex;
}
点击后效果
场景2.新增,点击“新建”显示form表单,提交成功后隐藏form表单
点击“新建”弹窗form
说明:点击“新建”按钮,显示form表单且有默认值,提交成功后关闭form,内容为空提示错误提示
前端代吗
<div class="col-md-8"><!--表单--><form id="myForm" style="display: none"><div class="form-group" style="display: none"><label for="name">id</label><input type="text" class="form-control" id="id" value=""><span id="errorId" style="color: orangered"></span></div><div class="form-group"><label for="name">姓名</label><input type="text" class="form-control" id="name" placeholder="please input name" value="测试姓名"><span id="errorName" style="color: orangered"></span></div><div class="form-group"><label for="classes">班级</label><input type="text" class="form-control" id="classes" placeholder="please input classes" value="测试班级"><span id="errorClasses" style="color: orangered"></span></div><div class="form-group"><label for="college">所属学院</label><input type="text" class="form-control" id="college" placeholder="please input college" value="测试所属学院"><span id="errorCollege" style="color: orangered"></span></div><div class="form-group"><label for="alias">别名</label><input type="text" class="form-control" id="alias" placeholder="please input alias" value="测试别名"><span id="errorAlias" style="color: orangered"></span></div><div class="form-group"><label >性别</label></div><div class="checkbox"><label id="sex"><input type="radio" name="sex" value=1>男 <input type="radio" name="sex" value=0 checked="checked">女</label></div><span id="errorMyFormMessage" style="color: orangered"></span><button type="button" id="myFormSubmit" class="btn btn-success">提交</button><button type="button" id="myFormClose" class="btn btn-danger">关闭</button><!--y隐藏域,用于判断执行的是【1:增、2:改、3:删】--><input type="hidden" id="submitType" th:value=0></form></div>
----------------------------------------------------------------------------
//点击“关闭按钮”关闭窗口$("#myFormClose").click(function () {$("#myForm").hide();});
----------------------------------------------------------------------------
//校验form
var vertifyForm = function () {var flag = true;if ($("#name").val() == "") {$("#errorName").html("name 不能为空");flag = false;}if ($("#classes").val() == "") {$("#errorClasses").html("classes 不能为空");flag = false;}if ($("#college").val() == "") {$("#errorCollege").html("college 不能为空");flag = false;}if ($("#alias").val() == "") {$("#errorAlias").html("alias 不能为空");flag = false;}return flag;
}
----------------------------------------------------------------------------
//新增
$("#addTeacher").click(function () {$("#name").val("测试姓名");$("#classes").val("测试班级");$("#college").val("测试所属学院");$("#alias").val("测试别名");$("#myForm").show();$("#submitType").val(1);
});
----------------------------------------------------------------------------//新增/修改/删除-提交
$("#myFormSubmit").click(function () {flag = vertifyForm();//校验,成功则提交请求,失败则不提交并显示错误提示信息if (!flag) return;//判断【增加/修改】操作//新增if ($("#submitType").val() == 1) {var params = {"name":$("#name").val(),"classes":$("#classes").val(),"college":$("#college").val(),"alias":$("#alias").val(),"sex":$("#sex :radio").val()};$.ajax({type:"POST",url:"/addTeacher",async: true,dataType: "json",//注意:ajax提交post请求时,必须使用JSON.stringify(data) 序列化请求参数,否则报400data: JSON.stringify(params),contentType: "application/json; charset=UTF-8",success : function (response) {if (response.code === 200) {var tr = ["<tr>","<th><input type='checkbox' value=''></th>","<th scope='row'>" + response.info.id + "</th>","<td>"+ response.info.name +"</td>","<td>"+ response.info.classes +"</td>","<td>"+ response.info.college +"</td>","<td>"+ response.info.alias +"</td>",];if (response.info.sex === 0) {tr = tr + "<td> 女 </td>";} else {tr = tr + "<td> 男</td>";}$("#myTbody1").append("</tr><tr>").append(tr);$("#myForm").hide();}}});}//修改else if ($("#submitType").val() == 2) {//$("#myTbody1 :input:checked").length 用于获取checkbox的选中条数if ($("#myTbody1 :input:checked").length == 1) {$("#errorMyFormMessage").html("")var params = {"id": $("#myTbody1 :input:checked").parent().parent().children().eq(1).html(),"name":$("#name").val(),"classes":$("#classes").val(),"college":$("#college").val(),"alias":$("#alias").val(),"sex":$("#sex :radio:checked").val()};$.ajax({type:"PUT",url:"/updateTeacher",async: true,dataType: "json",//注意:ajax提交post请求时,必须使用JSON.stringify(data) 序列化请求参数,否则报400data: JSON.stringify(params),contentType: "application/json; charset=UTF-8",success : function (response) {if (response.code === 200) {$("#myTbody1 :input:checked").parent().parent().children().eq(2).html(response.info.name)$("#myTbody1 :input:checked").parent().parent().children().eq(3).html(response.info.classes)$("#myTbody1 :input:checked").parent().parent().children().eq(4).html(response.info.college)$("#myTbody1 :input:checked").parent().parent().children().eq(5).html(response.info.alias)if (response.info.sex == 0) {$("#myTbody1 :input:checked").parent().parent().children().eq(6).html("女")} else {$("#myTbody1 :input:checked").parent().parent().children().eq(6).html("男")}$("#myForm").hide();}}});} else {$("#errorMyFormMessage").html("只能选中一条记录提交!")return;}}
});
后端代码
//新增
@PostMapping(value = "/addTeacher")
@ResponseBody
public Response<Teacher> addTeacher(@RequestBody Teacher teacher) {List<Teacher> teacherList = cache.get("list");Integer maxId = 0;for (Teacher item : teacherList) {if (item.getId() > maxId) maxId = item.getId();}//模拟id自增teacher.setId(++maxId);teacherList.add(teacher);cache.put("list", teacherList);cache.get("list").stream().forEach(System.out::println);return Response.success(teacher);
}
提交成功后
场景3.更新,单选一条数据->弹窗->更新值->提交->更新页面
说明:更新和删除都是只能选中一条记录进行操作,否则警告弹窗
说明:先点击左侧勾选框-》如果选中一条记录则可再点击“更新”,并显示弹窗,如果选中多条会弹出警告
前端代吗
//全选或者全不选
$("#mycheckbox").click(function () {//判断全选框是勾选还是非勾选if ($(this).prop('checked')) {$("#myTable input[type=checkbox]").prop("checked", true);} else {$("#myTable input[type=checkbox]").prop("checked", false);}
});----------------------------------------------------------------------------
//修改
$("#updateTeacher").click(function () {if ($("#myTbody1 :input:checked").length != 1) {alert("请选则其中一条数据");return;}$("#name").val($("#myTbody1 :input:checked").parent().parent().children().eq(2).html());$("#classes").val($("#myTbody1 :input:checked").parent().parent().children().eq(3).html());$("#college").val($("#myTbody1 :input:checked").parent().parent().children().eq(4).html());$("#alias").val($("#myTbody1 :input:checked").parent().parent().children().eq(5).html());if ($("#myTbody1 :input:checked").parent().parent().children().eq(6).html() == "男") {$("#sex").children().eq(0).prop("checked", true);} else {$("#sex").children().eq(1).prop("checked", true);}$("#myForm").show();$("#submitType").val(2);
});
后端代码
//修改@PutMapping(value = "/updateTeacher")@ResponseBodypublic Response<Teacher> updateTeacher(@RequestBody Teacher teacher) {List<Teacher> teacherList = cache.get("list");List<Teacher> newTeacherList = new ArrayList<>();Teacher teacherNew = null;Iterator<Teacher> iterator = teacherList.iterator();while(iterator.hasNext()){Teacher item = iterator.next();if (item.getId() == teacher.getId()) {teacherNew = new Teacher();teacherNew.setId(teacher.getId());teacherNew.setName(teacher.getName());teacherNew.setClasses(teacher.getClasses());teacherNew.setCollege(teacher.getCollege());teacherNew.setAlias(teacher.getAlias());teacherNew.setSex(teacher.getSex());iterator.remove();newTeacherList.add(teacherNew);continue; //跳过此次循环进入下一次循环中}newTeacherList.add(item);}cache.put("list", newTeacherList);cache.get("list").stream().forEach(System.out::println);return Response.success(teacherNew);}
场景4.删除功能
说明:更新和删除都是只能选中一条记录进行操作,否则警告弹窗
前端代码
//删除
$("#deleteTeacher").click(function () {console.log("***************");console.log($("#myTbody1 :input:checked").length)$("#submitType").val(3);//$("#myTbody1 :input:checked").length 用于获取checkbox的选中条数if ($("#myTbody1 :input:checked").length == 1) {$("#errorMyFormMessage").html("")var params = {};$.ajax({type:"DELETE",url:"/deleteTeacher?id=" + $("#myTbody1 :input:checked").parent().parent().children().eq(1).html(),async: true,dataType: "json",//注意:ajax提交post请求时,必须使用JSON.stringify(data) 序列化请求参数,否则报400data: params,contentType: "application/json; charset=UTF-8",success : function (response) {if (response.code === 200) {$("#myTbody1 :input:checked").closest('tr').remove();$("#myForm").hide();}}});} else {alert("请选则其中一条数据");return;}
});
后端代码
//删除
@DeleteMapping(value = "/deleteTeacher")
@ResponseBody
public Response<Teacher> deleteTeacher(@RequestParam Integer id) {List<Teacher> teacherList = cache.get("list");Iterator<Teacher> iterator = teacherList.iterator();while(iterator.hasNext()){Teacher item = iterator.next();if (item.getId() == id) {iterator.remove(); //注意这个地方}}cache.put("list", teacherList);cache.get("list").stream().forEach(System.out::println);return Response.success();
}
报错场景说明
1.jquery调用post请求,后台一直报400,显示:JSON Parse error: Unrecognized token
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'name': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'name': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')<EOL> at [Source: (PushbackInputStream); line: 1, column: 6]]
错误代码:
//新增
$("#addTeacher").click(function () {// $("#myForm").show()0987;flag = vertifyForm();var params = {"name":$("#name").val(),"classes":$("#classes").val(),"college":$("#college").val(),"alias":$("#alias").val(),"sex":$("#sex :checkbox").val()};$.ajax({type:"POST",url:"/addTeacher",async: true,dataType: "json",//ajax提交post请求时,必须使用JSON.stringify(data) 序列化请求参数,否则报400data: params,// data: JSON.stringify(params),contentType: "application/json; charset=UTF-8",success : function (response) {if (response.code === 200) {console.log("***************");console.log(response);}}});});
解决办法:ajax提交post请求时,使用JSON.stringify(data) 序列化请求参数(data为请求接口的数据)
正确代码:data: JSON.stringify(params),
2.清空form表单问题,例如input和checkbox标签
之前碰到的问题:标签checkbox一直无法清除
//清空form - 这里是正确的代吗
var emptyForm = function () {$("#name").val("");$("#classes").val("");$("#college").val("");$("#alias").val("");$("#sex :checkbox").removeAttr("checked"); //该方式可清楚选中
}
3.引入Bootstrap和Jquery显示404找不到文件
说明:引入css和第三方js顺序,先加载css,再加载jquery的js,最后加载bootstrap.js,否则加载顺序不对可能出错
发生错误原因:我写的绝对路径和相对路径都不对,另外我也不确信相对路径
究竟是从哪里开始算,所以一直报404
正确的图片路径及代吗如下
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title></title><!--先加载css,再加载js,否则可能出错--><link th:href="@{bootstrap-3.4.1-dist/css/bootstrap.css}" rel="stylesheet" /><link th:href="@{bootstrap-3.4.1-dist/css/bootstrap-theme.css}" rel="stylesheet" /><!--切记:先加载jquery的js,再加载bootstrap.js--><script th:src="@{jquery/jquery3.6.0.js}"></script><script th:src="@{bootstrap-3.4.1-dist/js/bootstrap.js}"></script>
</head>
会议详情
重要信息
- 大会官网:https://ais.cn/u/vEbMBz
大会介绍
第四届公共管理与大数据分析国际学术会议 (PMBDA 2024)将于2024年12月20-22日在中国青岛召开。会议主题主要围绕公共管理与大数据分析等相关研究领域展开讨论,旨在为相关研究方向的专家学者及企业发展人提供一个分享研究成果、讨论存在的问题与挑战、探索前沿科技的国际性合作交流平台。现诚邀国内外高校、科研机构专家、学者,企业界人士及其他相关人员踊跃投稿并参会交流。
4.radio对应的性别想实现,点击男,则女取消勾选,实际情况是取消勾选不了,且男女都会选中,具体如图
前端代吗如下
<div class="checkbox"><label id="sex"><input type="radio" value=1>男 <input type="radio" value=0 checked="checked">女</label>
</div>
问题产生原因: 没设置name属性造成
解决办法:两个input份别补充name属性即可默认实现每次只能选中一个,另外往后初始化标签栏,属性id和name最好默认都给上,防止莫名出错
<label id="sex"><input type="radio" name="sex" value=1>男 <input type="radio" name="sex" value=0 checked="checked">女
</label>
5.删除功能报错 java.util.ConcurrentModificationException: null
出错场景描述:
后台模拟一个本地缓存ConcurrentHashMap来存放list信息,页面点击删除按钮时后台删除list里面的某个记录,举例代码如下,该问题报错点在于,当既遍历list,同时又想操作删除某个元素时,就会产生这个报错
private ConcurrentHashMap<String, List<Teacher>> cache = new ConcurrentHashMap<>();@PostConstruct
public void initCache() {List<Teacher> teacherList = new ArrayList<>();Teacher teacher1 = new Teacher();teacher1.setId(1);teacher1.setName("周杰伦");teacher1.setClasses("三年二班");teacher1.setCollege("魔法学院");teacher1.setAlias("Jay Chou");teacher1.setSex(1);teacherList.add(teacher1);Teacher teacher2 = new Teacher();teacher2.setId(2);teacher2.setName("丽萨");teacher2.setClasses("三年二班");teacher2.setCollege("魔法学院");teacher2.setAlias("Lisa");teacher2.setSex(0);teacherList.add(teacher2);cache.put("list", teacherList);
}//删除@DeleteMapping(value = "/deleteTeacher")@ResponseBodypublic Response<Teacher> deleteTeacher(@RequestParam Integer id) {List<Teacher> teacherList = cache.get("list");for (Teacher item : teacherList) {if (item.getId() == id) {teacherList.remove(item);}}cache.put("list", teacherList);cache.get("list").stream().forEach(System.out::println);return Response.success();}
解决办法,不使用teacherList.remove(item);方法,而使用迭代器的iterator.remove();
//删除
@DeleteMapping(value = "/deleteTeacher")
@ResponseBody
public Response<Teacher> deleteTeacher(@RequestParam Integer id) {List<Teacher> teacherList = cache.get("list");Iterator<Teacher> iterator = teacherList.iterator();while(iterator.hasNext()){Teacher item = iterator.next();if (item.getId() == id) {iterator.remove(); //注意这个地方}}cache.put("list", teacherList);cache.get("list").stream().forEach(System.out::println);return Response.success();
}
6.更新功能报错 java.util.ConcurrentModificationException: null
更新和删除功能类型,想遍历list进行删除或者添加操作,
思路:便利list碰到匹配的就删除,用form传过来的新值添加进list中,从而达到更新目的,
问题出在:如果操作同一个list,哪怕用迭代器也会报错,正确思路是,从新创建个list,便利碰到不同的直接添加,碰到匹配的就保存到新的实体对象中,再添加到list中
本人相关其他文章链接
1.JQuery选择器+DOM操作+事件+DOM与JQuery对象间的转化
2.个人练习前端技术使用Bootstrap、JQuery、thymeleaf
3.JavaScript入门及基础知识介绍
4.AJax(XHR+Get和Post+AJax的封装)
5.SpringBoot项目的html页面使用axios进行get post请求