保存

URI:

  • /emp/{id} GET 查询员工

  • /emp POST保存员工

  • /emp/{id} PUT修改员工

  • /emp/{id} DELETE删除员工

首先添加一个点击事件,点击保存的时候,完成保存事件

1
2
3
$("#emp_save_btn").click(function () {
//1.模态框中填写的表单数据提交给服务器进行保存
});

给保存按钮添加上id=emp_save_btn

接着在EmployeeController中添加方法

1
2
3
4
5
6
@RequestMapping(value = "/emp",method = RequestMethod.POST)
@ResponseBody
public Msg saveEmp(Employee employee){
employeeService.saveEmp(employee);
return Msg.success();
}

EmployeeService中对应的写方法

1
2
3
4
5
6
/**
* 员工保存方法
*/
public void saveEmp(Employee employee){
employeeMapper.insertSelective(employee);
}

接着完善点击事件

由于需要ajax请求保存员工,但是一个一个取出员工数据太过于麻烦,所以就需要请出一生噩梦,序列化与反序列化

1
2
3
4
5
6
//alert($("#empAddModal form").serialize());

$.ajax({
url:"${APP_PATH}/emp",
type:"POST",
data:$("#empAddModal form").serialize()

我们还想要再点击保存之后关闭模态框并且转到最后一页来显示刚才的数据

访问一下bootstarp模态框
找到关闭模态框的方法

1
$("#empAddModal").modal('hide');

来到最后一页要面临一个问题就是当该页已经有5个数据,再添加一个数据,页码就会加一,这个时候不用担心,插件会自动帮我们完成,我们只需要发送ajax请求最后一页数据即可,但是又担心调用to_page方法不够保险,就可以请求总记录数当页码

定义一个全局遍历totalRecords

1
totalRecords = result.extend.pageInfo.total;

然后用to_page请求就好了
1
to_page(totalRecords);

完整的保存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$("#emp_save_btn").click(function () {
//1.模态框中填写的表单数据提交给服务器进行保存
//2.发送ajax请求保存员工
// alert($("#empAddModal form").serialize());
$.ajax({
url:"${APP_PATH}/emp",
type:"POST",
data:$("#empAddModal form").serialize(),
success:function (result) {
//alert(result.msg);
//员工保存成功:
//1. 关闭模态框
$("#empAddModal").modal('hide');
//2. 来到最后一页,显示刚才保存的数据
//发送ajax请求显示最后一页数据即可
//可以将总记录数当作页码
to_page(totalRecords);
}
});
});

这下点击保存之后,就会自动跳转到最后一页并关闭模态框了

但是目前只是基本完成了保存功能,但是没有校验输入的信息,这就需要编写一下娇艳的逻辑了

校验

合法性校验

输入数据以后不能直接完成保存,必须要进行校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

//校验表单数据
function validata_add_form(){
//1. 拿到要检验的数据,使用正则表达式
var empName = $("#empName_add_input").val();
var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/;
if(!regName.test(empName)){
alert("用户名可以是2-5位中文或6-16位英文和数字的组合");
return false;
};
//2. 校验邮箱信息
var email = $("#email_add_input").val();
var regEmaill = /^([a-zA-Z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/ ;
if(!regEmaill.test(email)){
alert("邮箱格式不正确");
return false;
};
return true;
}
1
2
3
4
5
6
7
//点击保存,保存员工
$("#emp_save_btn").click(function () {
//1.模态框中填写的表单数据提交给服务器进行保存
//2.先对要提交给服务器的数据进行校验
if(!validata_add_form()){
return false;
};

这样我们的逻辑就完成了,用户名和邮箱都需要正确才允许提交ajax请求

但是alert太难看了,可以在bootstrap表单校验状态找到相应的操作

我们抽取一个方法show_validate_msg

1
2
3
4
5
6
7
8
9
10
11
12
13
function show_validate_msg(ele,status,msg){
//清空这个元素之前的样式
$(ele).parent().removeClass("has-success has-error");
$(ele).next("span").text("");

if(status == "success"){
$(ele).parent().addClass("has-success");
$(ele).next("span").text(msg);
}else if(status == "error"){
$(ele).parent().addClass("has-error");
$(ele).next("span").text(msg);
}
}

validata_add_form也要修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//校验表单数据
function validata_add_form(){
//1. 拿到要检验的数据,使用正则表达式
var empName = $("#empName_add_input").val();
var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/;
if(!regName.test(empName)){
// alert("用户名可以是2-5位中文或6-16位英文和数字的组合");
//清空这个元素之前的样式
show_validate_msg("#empName_add_input","error","用户名可以是2-5位中文或6-16位英文和数字的组合");
return false;
}else{
show_validate_msg("#empName_add_input","success","");
};

//2. 校验邮箱信息
var email = $("#email_add_input").val();
var regEmaill = /^([a-zA-Z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/ ;
if(!regEmaill.test(email)){
// alert("邮箱格式不正确");
show_validate_msg("#email_add_input","error","邮箱格式不正确");
return false;
}else{
show_validate_msg("#email_add_input","success","");
};
return true;
}

这样就完成了一个好看的检验信息,但是现在只是校验了合法性,但是并没有查重,所以接下来就需要进行一个查重的校验

重复校验

基本逻辑就是当查到重复的时候要提示出错误信息,并且不能保存,利用change事件来编写

首先需要编写一个checkUser方法

在EmployeeController中添加

1
2
3
4
5
6
7
8
9
10
11
//检查用户名是否可用
@ResponseBody
@RequestMapping("/checkUser")
public Msg checkUser(@RequestParam("empName") String empName){
boolean b = employeeService.checkUser(empName);
if(b){
return Msg.success();
}else{
return Msg.fail();
}
}

对应的Service中添加
1
2
3
4
5
6
7
public boolean checkUser(String empName) {
EmployeeExample example = new EmployeeExample();
EmployeeExample.Criteria criteria = example.createCriteria();
criteria.andEmpNameEqualTo(empName);
long count = employeeMapper.countByExample(example);
return count==0;
}

接着在index.jsp中添加上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//校验用户名是否可用
$("#empName_add_input").change(function () {
//发送ajax请求校验用户名是否可用
var empName = this.value;
$.ajax({
url:"${APP_PATH}/checkUser",
data:"empName="+empName,
type:"POST",
success:function (result) {
if(result.code == 200){
show_validate_msg("#empName_add_input","success","用户名可用");
$("#emp_save_btn").attr("ajax-va","success");
}else{
show_validate_msg("#empName_add_input","error","用户名不可用");
$("#emp_save_btn").attr("ajax-va","error");
}
}
});
});

这里利用一个自定义的属性ajax-va来判断是否可用
保存事件也要添加上
1
2
3
4
5
6
7
8
9
10
$("#emp_save_btn").click(function () {
//1.模态框中填写的表单数据提交给服务器进行保存
//2.先对要提交给服务器的数据进行校验
if(!validata_add_form()){
return false;
};
//3.判断之前的ajax用户名校验是否成功
if($(this).attr("ajax-va")=="error"){
return false;
};

因为使用的是change事件,只有内容发生改变的时候,才会执行此校验,所以为了防止绕过该校验信息,就需要每次提交后都重置表单

1
2
3
$("#emp_add_modal_btn").click(function () {
//清除数据,表单重置
$("#empAddModal form")[0].reset();

这样一来,一个完整的前端校验就完成了

前端校验

依旧是用正则表达式
在EmployeeController中修改checkUser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//检查用户名是否可用
@ResponseBody
@RequestMapping("/checkUser")
public Msg checkUser(@RequestParam("empName") String empName){
//先判断用户名是否是合法的表达式;
String regx = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})";
if(!empName.matches(regx)){
return Msg.fail().add("va_msg","用户名必须是6到16位数字和字母的组合或2-5位中文");
}
//数据库用户名重复校验
boolean b = employeeService.checkUser(empName);
if(b){
return Msg.success();
}else{
return Msg.fail().add("va_msg","用户名不可用");
}
}

同时修改index.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//校验用户名是否可用
$("#empName_add_input").change(function () {
//发送ajax请求校验用户名是否可用
var empName = this.value;
$.ajax({
url:"${APP_PATH}/checkUser",
data:"empName="+empName,
type:"POST",
success:function (result) {
if(result.code == 200){
show_validate_msg("#empName_add_input","success","用户名可用");
$("#emp_save_btn").attr("ajax-va","success");
}else{
show_validate_msg("#empName_add_input","error",result.extend.va_msg);
$("#emp_save_btn").attr("ajax-va","error");
}
}
});
});

同时还有一个问题,就是清楚掉表单的样式

抽取一个方法reset_form

1
2
3
4
5
6
7
//清空表单样式及内容
function reset_form(ele){
$(ele)[0].reset();
//清空样式
$(ele).find("*").removeClass("has-success has-error");
$(ele).find(".help-block").text("");
}

弹出模态框的事件也要修改

1
2
3
$("#emp_add_modal_btn").click(function () {
//清除数据,表单重置
reset_form($("#empAddModal form"));

当前的index.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
<%--
web路径:
不以/开始的相对路径,找资源,以当前资源的路径为基准,经常容易出现问题
以/开始的相对路径,找资源,以服务器的路径为标准(http://localhost:3306)需要加上项目名
http://localhost:3306/crud
--%>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>员工列表</title>
<%
pageContext.setAttribute("APP_PATH",request.getContextPath());
%>

<link href="${APP_PATH}/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
<script src="${APP_PATH}/static/js/jquery-3.5.1.min.js" type="text/javascript"></script>
<script src="${APP_PATH}/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>

</head>
<body>

<!-- 员工添加的模态框 -->
<div class="modal fade" id="empAddModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">员工添加</h4>
</div>
<div class="modal-body">
<form class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">empName</label>
<div class="col-sm-10">
<input type="text" name="empName" class="form-control" id="empName_add_input" placeholder="empName">
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">email</label>
<div class="col-sm-10">
<input type="text" name="email" class="form-control" id="email_add_input" placeholder="email@qq.com">
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">gender</label>
<div class="col-sm-10">
<label class="radio-inline">
<input type="radio" name="gender" id="gender1_add_input" value="M" checked="checked">
</label>
<label class="radio-inline">
<input type="radio" name="gender" id="gender2_add_input" value="F">
</label>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">deptName</label>
<div class="col-sm-4">
<%-- 部门提交部门id即可--%>
<select class="form-control" name="dId" id="dept_add_select">
<%-- 部门名称--%>
</select>
</div>
</div>

</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" id="emp_save_btn">保存</button>
</div>
</div>
</div>
</div>


<div class="container">
<%--标题--%>
<div class="row">
<div class="col-md-12">
<h1>SSM-CRUD</h1>
</div>
</div>
<%--按钮--%>
<div class="row">
<div class="col-md-4 col-md-offset-8">
<button class="btn btn-primary" id="emp_add_modal_btn">新增</button>
<button class="btn btn-danger">删除</button>
</div>
</div>
<%--显示表格数据--%>
<div class="row">
<div class="col-md-12">
<table class="table table-hover" id="emps_table">
<thead>
<tr>
<th>#</th>
<th>empName</th>
<th>gender</th>
<th>email</th>
<th>deptName</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<%-- 员工数据等--%>
</tbody>

</table>
</div>
</div>
<%--显示分页信息--%>
<div class="row">
<%-- 分页文字信息--%>
<div class="col-md-6" id="page_info_area">
<%-- 显示页码等信息--%>
</div>
<%-- 分页条信息--%>
<div class="col-md-6" id="page_nav_area">
<%-- 显示分页条信息--%>
</div>
</div>
</div>

<script type="text/javascript">

var totalRecords;

//1.页面加载完成以后,直接去发送一个ajax请求,要到分页数据
$(function (){
//去首页
to_page(1);
});

function to_page(pn) {
$.ajax({
url:"${APP_PATH}/emps",
data:"pn="+pn,
type:"GET",
success:function (result){
// console.log(result);
//1.解析并显示员工数据
build_emps_tables(result);
//2.解析并显示分页信息
build_page_info(result);
//3.解析并显示分页条数据
build_page_nav(result);
}
});
}

function build_emps_tables(result) {
//清空table
$("#emps_table tbody").empty();

var emps=result.extend.pageInfo.list;
$.each(emps,function (index,item) {
var empIdTd = $("<td></td>").append(item.empId);
var empNameTd = $("<td></td>").append(item.empName);
var genderTd = $("<td></td>").append(item.gender=='M'?"男":"女");
var emailTd = $("<td></td>").append(item.email);
var deptNameTd = $("<td></td>").append(item.department.deptName);
/**
* <button class="btn btn-primary btn-sm">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
编辑
</button>
*/
var editBtn = $("<button></button>").addClass("btn btn-primary btn-sm")
.append($("<span></span>").addClass("glyphicon glyphicon-pencil")).append("编辑");
/**
* <button class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-trash" aria-hidden="true" /></span>
删除
</button>
*/
var delBtn = $("<button></button>").addClass("btn btn-danger btn-sm")
.append($("<span></span>").addClass("glyphicon glyphicon-trash")).append("删除");

var btnTd = $("<td></td>").append(editBtn).append(" ").append(delBtn);

//append方法执行完成之后还是返回原来的元素
$("<tr></tr>").append(empIdTd)
.append(empNameTd)
.append(genderTd)
.append(emailTd)
.append(deptNameTd)
.append(btnTd)
.appendTo("#emps_table tbody")
});
}
//解析显示分页信息
function build_page_info(result){
//清空分页信息
$("#page_info_area").empty();

$("#page_info_area").append("当前"+result.extend.pageInfo.pageNum+"页,总"
+result.extend.pageInfo.pages+"页,总"
+result.extend.pageInfo.total+"条记录");
totalRecords = result.extend.pageInfo.total;
}
//解析显示分页条,点击分页要能去下一页等等....
function build_page_nav(result) {
//清空
$("#page_nav_area").empty();

//page_nav_area
var ul = $("<ul></ul>").addClass("pagination");

//构建元素
var firstPageLi = $("<li></li>").append($("<a></a>").append("首页").attr("href","#"));
var prePageLi = $("<li></li>").append($("<a></a>").append("&laquo;"));
if(result.extend.pageInfo.hasPreviousPage == false){
firstPageLi.addClass("disabled");
prePageLi.addClass("disabled");
}else{
//为元素添加点击翻页的事件
firstPageLi.click(function () {
to_page(1);
});
prePageLi.click(function () {
to_page(result.extend.pageInfo.pageNum-1);
});
}

//构建元素
var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
if(result.extend.pageInfo.hasNextPage == false){
nextPageLi.addClass("disabled");
lastPageLi.addClass("disabled");
}else{
//为元素添加点击翻页的事件
nextPageLi.click(function () {
to_page(result.extend.pageInfo.pageNum+1);
});
lastPageLi.click(function () {
to_page(result.extend.pageInfo.pages);
});
}

//添加首页和前一页的提示
ul.append(firstPageLi).append(prePageLi);
//1,2,3....遍历给ul中添加页码提示
$.each(result.extend.pageInfo.navigatepageNums,function (index,item) {
var numLi = $("<li></li>").append($("<a></a>").append(item));
if(result.extend.pageInfo.pageNum == item){
numLi.addClass("active");
}
numLi.click(function () {
to_page(item);
});
ul.append(numLi);
});
//添加后一页和末页的提示
ul.append(nextPageLi).append(lastPageLi);

//把ul加入到nav元素中
var navEle = $("<nav></nav>").append(ul);
navEle.appendTo("#page_nav_area");
}

//清空表单样式及内容
function reset_form(ele){
$(ele)[0].reset();
//清空样式
$(ele).find("*").removeClass("has-success has-error");
$(ele).find(".help-block").text("");
}

//点击新增按钮弹出模态框
$("#emp_add_modal_btn").click(function () {
//清除数据,表单重置
reset_form($("#empAddModal form"));
//发送ajax请求,查出部门信息,显示在下拉列表
getDepts();

//弹出模态框
$("#empAddModal").modal({
backdrop:"static"
});
});

//查出所有的部门信息并显示在下拉列表中
function getDepts() {
$.ajax({
url:"${APP_PATH}/depts",
type:"GET",
success:function (result) {
// console.log(result)
//显示部门信息在下拉列表中
// $("#dept_add_select").append("")
$.each(result.extend.depts,function () {
var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
optionEle.appendTo("#dept_add_select")
});
}
});
};


//校验表单数据
function validata_add_form(){
//1. 拿到要检验的数据,使用正则表达式
var empName = $("#empName_add_input").val();
var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/;
if(!regName.test(empName)){
// alert("用户名可以是2-5位中文或6-16位英文和数字的组合");
//清空这个元素之前的样式
show_validate_msg("#empName_add_input","error","用户名可以是2-5位中文或6-16位英文和数字的组合");
return false;
}else{
show_validate_msg("#empName_add_input","success","");
};

//2. 校验邮箱信息
var email = $("#email_add_input").val();
var regEmaill = /^([a-zA-Z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/ ;
if(!regEmaill.test(email)){
// alert("邮箱格式不正确");
show_validate_msg("#email_add_input","error","邮箱格式不正确");
return false;
}else{
show_validate_msg("#email_add_input","success","");
};
return true;
}

//显示校验信息
function show_validate_msg(ele,status,msg){
//清空这个元素之前的样式
$(ele).parent().removeClass("has-success has-error");
$(ele).next("span").text("");

if(status == "success"){
$(ele).parent().addClass("has-success");
$(ele).next("span").text(msg);
}else if(status == "error"){
$(ele).parent().addClass("has-error");
$(ele).next("span").text(msg);
}
}

//校验用户名是否可用
$("#empName_add_input").change(function () {
//发送ajax请求校验用户名是否可用
var empName = this.value;
$.ajax({
url:"${APP_PATH}/checkUser",
data:"empName="+empName,
type:"POST",
success:function (result) {
if(result.code == 200){
show_validate_msg("#empName_add_input","success","用户名可用");
$("#emp_save_btn").attr("ajax-va","success");
}else{
show_validate_msg("#empName_add_input","error",result.extend.va_msg);
$("#emp_save_btn").attr("ajax-va","error");
}
}
});
});

//点击保存,保存员工
$("#emp_save_btn").click(function () {
//1.模态框中填写的表单数据提交给服务器进行保存
//2.先对要提交给服务器的数据进行校验
if(!validata_add_form()){
return false;
};
//3.判断之前的ajax用户名校验是否成功
if($(this).attr("ajax-va")=="error"){
return false;
};
//4.发送ajax请求保存员工
// alert($("#empAddModal form").serialize());
$.ajax({
url:"${APP_PATH}/emp",
type:"POST",
data:$("#empAddModal form").serialize(),
success:function (result) {
//alert(result.msg);
//员工保存成功:
//1. 关闭模态框
$("#empAddModal").modal('hide');
//2. 来到最后一页,显示刚才保存的数据
//发送ajax请求显示最后一页数据即可
//可以将总记录数当作页码
to_page(totalRecords);
}
});
});


</script>

</body>
</html>