Spring+SpringMVC+Mybatis实现增删改查--(四)SSM新增员工页面搭建
新增员工:
1.在index.jsp页面点击“新增”弹出新增对话框
2.去数据库查询部门列表,显示在新增对话框中
3.用户输入数据并进行校验(校验这里分成了三种)
jQuery前端校验、ajax用户名的重复校验、重要数据(后端校验(JR303),唯一约束)
4完成保存。
REST风格的URI
规定URI:
/emp/{id} GET 查询
/emp POST保存员工
/emp/{id} PUT 修改员工
/emp/{id} DELETE删除员工
新增员工的具体步骤:
1.新增弹出对话框
(1)在bootstrap中JavaScript插件找到模态对话框,参考官网的代码
(2)弹出模态对话框的方式(官网给出了两种方式)
(3)具体的代码实现方式
<!--员工添加的模态框 --> <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">×</span></button> <h4 class="modal-title" id="myModalLabel">员工添加</h4> </div> <div class="modal-body"> <!-- 表单输入框 --> <form class="form-horizontal"> <div class="form-group"> <label for="empName_add_input" 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 for="email_add_input" 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 protected]"> <span class="help-block"></span> </div> </div> <!-- 性别 --> <div class="form-group"> <label for="email_add_input" 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 for="email_add_input" 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>
2.获取部门的信息,显示在下拉列表中
(1)index.jsp发出ajax请求查出所有部门信息并显示在下拉列表中
//查出所有的部门信息并显示在下拉列表中 function getDepts(ele){ $(ele).empty(); $.ajax({ url:"${APP_PATH}/depts", type:"GET", success:function(result){ //{"code":0,"msg":"处理成功"," //data":{"depts":[{"deptId":1,"deptName":"开发部"},{"deptId":2,"deptName":"测试部"}]}} //显示部门信息在下拉列表中 $.each(result.data.depts,function(){ var optionEle=$("<option></option>").append(this.deptName).attr("value",this.deptId); optionEle.appendTo("#dept_add_select"); }); } }); }
(2)DepartmentService.java的代码
package com.lcz.crud.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.lcz.crud.bean.Department; import com.lcz.crud.dao.DepartmentMapper; @Service public class DepartmentService { @Autowired private DepartmentMapper departmentMapper; public List<Department> getDepts() { List<Department> list = departmentMapper.selectByExample(null); return list; } }
(3)DepartmentController.java用来获取部门的信息
package com.lcz.crud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.lcz.crud.bean.Department; import com.lcz.crud.bean.Msg; import com.lcz.crud.service.DepartmentService; /** * 处理和部门有关的请求 * @author LvChaoZhang * */ @Controller public class DepartmentController { @Autowired private DepartmentService departmentService; /** * 返回所有的部门信息 */ @RequestMapping("/depts") @ResponseBody public Msg getDepts() { //查出所有的部门信息 List<Department> list=departmentService.getDepts(); return Msg.success().add("depts", list); } }
3.数据校验
(1)jQuery前端校验新建对话框的用户名、密码
/校验表单数据的方法 function validate_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 regEmail=/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/; if (!regEmail.test(email)) { //alert("邮箱格式不正确"); //清空这个元素之前的样式 show_validate_msg("#email_add_input","error","邮箱格式不正确"); return false; }else{ show_validate_msg("#email_add_input","success",""); } return true; }
(2)ajax请求用户名是否重复
a.index.jsp发出ajax请求
//校验用户名是否可用 $("#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==0){ show_validate_msg("#empName_add_input","success","用户名可用"); $("#emp_save_btn").attr("ajax-va","success"); }else{ show_validate_msg("#empName_add_input","error",result.data.va_msg); $("#emp_save_btn").attr("ajax-va","error"); } } }); });
b.EmployeeService.java中检验用户名是否可用的方法
/** * 校验用户名是否可用 * @param empName * @return true 可用 false不可用 */ public boolean checkUser(String empName) { EmployeeExample example=new EmployeeExample(); Criteria criteria = example.createCriteria(); criteria.andEmpNameEqualTo(empName); long count=employeeMapper.countByExample(example); return count==0; }
c.EmployeeController.java中调用检查用户名
/** * 检查用户名是否可用 * @param empName * @return */ @ResponseBody @RequestMapping("/checkuser") public Msg checkUser(@RequestParam("empName")String empName) { //先判断用户名是合法的表达式 String regex="(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})"; if(!empName.matches(regex)) { 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", "用户名不可用"); } }
(3)后端数据JR303校验
a.pom.xml中导入hibernate-validator包
<!-- JSR303数据校验支持 tomcat7及以上的服务器直接导入即可 tomcat7以下的服务器,el表达式,额外的给服务器的lib包中替换新的el--> <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.7.Final</version> </dependency>
b.Employee.java写入@Pattern
@Pattern(regexp="(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})",message="用户名必须是2-5位中文或者6-16位英文和数字的组合") private String empName; private String gender; //@Email @Pattern(regexp="^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$",message="邮箱格式不正确") private String email;
c.保存按钮的事件
EmployeeService的保存方法
/** * 员工保存 * 1.支持JSR303校验 * 导入hibernate validator * @param employee */ public void saveEmp(Employee employee) { employeeMapper.insertSelective(employee); }
EmployeeController的保存方法外加校验
/** * 员工保存 * @return */ @RequestMapping(value="/emp",method=RequestMethod.POST) @ResponseBody public Msg saveEmp(@Valid Employee employee,BindingResult result) {//因为表单中name中的值跟employee对象的值一样,所以自动封装 if(result.hasErrors()) { //校验失败,返回失败,在模态框中显示校验失败的错误信息 Map<String, Object>map=new HashMap<String, Object>(); List<FieldError> errors = result.getFieldErrors(); for(FieldError fieldError:errors) { System.out.println("错误的字段名"+fieldError.getField()); System.out.println("错误的信:"+fieldError.getDefaultMessage()); map.put(fieldError.getField(), fieldError.getDefaultMessage()); } return Msg.fail().add("errorFields", map); }else { employeeService.saveEmp(employee); return Msg.success(); } }
4.保存按钮事件
正常保存之后会跳转到最后一页
给出这一节完整的index.jsp,功能是通过JavaScript的封装库jquery来实现功能的,功能上都有代码解释,可以参考
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>员工列表</title> <% pageContext.setAttribute("APP_PATH", request.getContextPath()); %> <!-- web路径: 不以/开始的相对路径,找资源,以当前资源的路径为基准,经常容易出问题。 以/开始的相对路径,找资源,以服务器的路径为标准(http://localhost:8080);需要加上项目名 http://localhost:3306/crud --> <script type="text/javascript" src="${APP_PATH }/static/js/jquery-3.3.1.min.js"></script> <link href="${APP_PATH }/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"> <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">×</span></button> <h4 class="modal-title" id="myModalLabel">员工添加</h4> </div> <div class="modal-body"> <!-- 表单输入框 --> <form class="form-horizontal"> <div class="form-group"> <label for="empName_add_input" 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 for="email_add_input" 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 protected]"> <span class="help-block"></span> </div> </div> <!-- 性别 --> <div class="form-group"> <label for="email_add_input" 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 for="email_add_input" 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> <br> <!-- 显示表格数据 --> <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 totalRecord;//总记录数 //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_table(result); //2、解析并显示分页信息 build_page_info(result); //3、解析显示分页条数据 build_page_nav(result); } }); } //解析并显示员工数据 function build_emps_table(result){ //清空table表格 $("#emps_table tbody").empty(); var emps=result.data.pageInfo.list;//所有的员工数据 //遍历所有的员工数据 $.each(emps,function(index,item){ //alert(item.empName); //构建表格 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 edit_btn"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> 编辑 </button> */ var editBtn=$("<button></button>").addClass("btn btn-primary btn-sm edit_btn") .append($("<span></span>").addClass("glyphicon glyphicon-pencil")).append("编辑"); var delBtn=$("<button></button>").addClass("btn btn-danger btn-sm delete_btn") .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.data.pageInfo.pageNum+"页,总共"+result.data.pageInfo.pages+"页,总共"+result.data.pageInfo.total+"记录数"); totalRecord=result.data.pageInfo.total;//将总记录数保存到全局变量中 } /** <nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#">5</a></li> <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav> */ //解析并显示分页条,点击分页能去下一页.. function build_page_nav(result){ //page_nav_area //清空列表 $("#page_nav_area").empty(); var ul=$("<ul></ul>").addClass("pagination"); //首页 var firstPageLi=$("<li></li>").append($("<a></a>").append("首页").attr("href","#")); //前一页 var prePageLi = $("<li></li>").append($("<a></a>").append("«")); //如果没有前页的话,首页和前页隐藏 if(result.data.pageInfo.hasPreviousPage == false){ firstPageLi.addClass("disabled"); prePageLi.addClass("disabled"); }else{ //为元素添加点击翻页的事件 //首页的点击事件 firstPageLi.click(function(){ to_page(1); }); //前一页的点击事件 prePageLi.click(function(){ to_page(result.data.pageInfo.pageNum -1); }); } //后一页 var nextPageLi = $("<li></li>").append($("<a></a>").append("»")); //末页 var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#")); //如果没有下一页的话,下一页的末页隐藏 if(result.data.pageInfo.hasNextPage == false){ nextPageLi.addClass("disabled"); lastPageLi.addClass("disabled"); }else{ //下一页的点击事件 nextPageLi.click(function(){ to_page(result.data.pageInfo.pageNum +1); }); //末页的点击事件 lastPageLi.click(function(){ to_page(result.data.pageInfo.pages); }); } //添加首页和前一页 ul.append(firstPageLi).append(prePageLi); //遍历给ul添加页码提示 $.each(result.data.pageInfo.navigatepageNums,function(index,item){ var numLi = $("<li></li>").append($("<a></a>").append(item)); //按钮加深颜色 if(result.data.pageInfo.pageNum==item){ numLi.addClass("active"); } //页码的点击事件 numLi.click(function () { to_page(item); }); //遍历给ul添加页码提示 ul.append(numLi); }); //添加下一页和末页的提示 ul.append(nextPageLi).append(lastPageLi); //把ul加入到nav元素中 var navEle=$("<nav></nav>").append(ul); //把nav元素放到div中 navEle.appendTo("#page_nav_area"); } //表单重置方法清空表单样式及内容 function reset_form(ele){ $(ele)[0].reset();//清空表单内容 //清空表单样式 $(ele).find("*").removeClass("has-error has-success"); $(ele).find(".help-block").text(""); } //点击新增按钮弹出新增对话框的点击事件 $("#emp_add_modal_btn").click(function () { //清除表单数据(表单完整重置(表单的数据,表单的样式)) reset_form("#empAddModal form"); //发送ajax请求,查出部门信息,显示在下拉列表中 getDepts("#empAddModal select"); //弹出模态框 $("#empAddModal").modal({ backrop:"static" }); }); //查出所有的部门信息并显示在下拉列表中 function getDepts(ele){ $(ele).empty(); $.ajax({ url:"${APP_PATH}/depts", type:"GET", success:function(result){ //{"code":0,"msg":"处理成功"," //data":{"depts":[{"deptId":1,"deptName":"开发部"},{"deptId":2,"deptName":"测试部"}]}} //显示部门信息在下拉列表中 $.each(result.data.depts,function(){ var optionEle=$("<option></option>").append(this.deptName).attr("value",this.deptId); optionEle.appendTo("#dept_add_select"); }); } }); } //校验表单数据的方法 function validate_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 regEmail=/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/; if (!regEmail.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("success"==status){ $(ele).parent().addClass("has-success"); $(ele).next("span").text(msg); }else if ("error"==status) { $(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==0){ show_validate_msg("#empName_add_input","success","用户名可用"); $("#emp_save_btn").attr("ajax-va","success"); }else{ show_validate_msg("#empName_add_input","error",result.data.va_msg); $("#emp_save_btn").attr("ajax-va","error"); } } }); }); //新增对话框中的保存按钮事件,保存按钮 $("#emp_save_btn").click(function () { //0.对要提交给服务器的表单数据进行校验 if(!validate_add_form()){ return false; }; //0.判断之前的ajax用户名校验是否成功,如果成功才往下走 if($(this).attr("ajax-va")=="error"){ return; } //1.新增对话框中填写的表单信息提交给服务器进行保存 //2.发送ajax请求保存员工 //alert($("#empAddModal form").serialize()); $.ajax({ url:"${APP_PATH}/emp", type:"POST", data:$("#empAddModal form").serialize(), success:function(result){ //alert(result.msg); if (result.code==0) { //员工保存成功之后,关闭模态框 ,来到最后一页显示刚才保存的数据 //1.关闭模态框 $("#empAddModal").modal('hide'); //2.来到最后一页,显示最后一页 to_page(totalRecord); }else{ //显示失败信息 //console.log(result); //有哪个字段的错误信息就显示哪个字段的 //{"code":1,"msg":"失败","data":{"errorFields":{"email":"邮箱格式不正确"}}} if(undefined!=result.data.errorFields.email){ //显示邮箱错误信息 show_validate_msg("#email_add_input","error",result.data.errorFields.email); } if(undefined!=result.data.errorFields.empName){ //显示员工名字的错误信息 show_validate_msg("#empName_add_input","error",result.data.errorFields.empName); } } } }); }); </script> </body> </html>