• SSM-CRUD入门项目——新增与校验


    新增

      分析:

        在Index.jsp页面点击新增,弹出对话框(模态框)

        数据库查询部门列表显示在模态框中

        用户输入数据完成操作

      我们先把模态框构建出来,并对新增按钮添加事件,点击按钮弹出模态框:

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" 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 for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-2">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
        
                        </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">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(genderTd)
                        .append(emailTd)
                        .append(deptNameTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //增加员工的事件
            $("#addBtn_modal").click(function(){
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
        </script>
    </body>
    </html>
    View Code

      由于部门信息是变动的,在弹出模态框之前我们添加发送ajax请求查询部门信息进行显示,核心添加代码如下:

    //增加员工的事件
            $("#addBtn_modal").click(function(){
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
    View Code

      由于发送了相关的请求,我们完善的对应的controller如下:DeptController.java

    package cn.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 cn.crud.bean.Department;
    import cn.crud.bean.Msg;
    import cn.crud.service.DeptService;
    
    /**
     * 处理和部门有关的请求的controller
     * @author Administrator
     *
     */
    @Controller
    public class DeptController {
    
        //controller中注入service
        @Autowired
        private DeptService deptService;
        
        /**
         * 返回部门信息的controller方法
         * @return
         */
        @RequestMapping("/depts")
        @ResponseBody
        public Msg getDepts(){
            //查出所有部门信息
            List<Department> deptList = deptService.getDepts();
            //调用Msg的静态方法,返回我们自定义的数据
            return Msg.success().add("deptList", deptList);
        }
    }
    View Code

      相应的service:

    package cn.crud.service;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import cn.crud.bean.Department;
    import cn.crud.dao.DepartmentMapper;
    
    /**
     * 处理部门的service
     * @author Administrator
     *
     */
    @Service
    public class DeptService {
    
        //注入mapper
        @Autowired
        private DepartmentMapper departmentMapper;
        /**
         * 返回所有部门信息的方法
         * @return
         */
        public List<Department> getDepts() {
            List<Department> deptList = departmentMapper.selectByExample(null);
            return deptList;
        }
    
        
    }
    View Code

      

      其他的ajax请求也是这么个流程,接下来把添加员工的ajax请求完成一下:

    这里引入REST的风格的URI

      /emp/{id}   GET请求 查询员工

      /emp         POST请求 保存员工

      /emp/{id}   DELETE请求 删除员工

      /emp/{id}   PUT请求 修改员工

    //序列化表单数据的jQuery方法:

        serialize()——详细介绍请参见API

      这样,我们的添加的逻辑的页面如下:

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加员工</h4>
              </div>
              <div class="modal-body">
                <form class="form-horizontal">
                  <!-- 输入员工姓名 -->
                  <div class="form-group">
                    <label for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-4" style="120px">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
                            
                        </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_saveBtn">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(genderTd)
                        .append(emailTd)
                        .append(deptNameTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //增加员工的事件
            $("#addBtn_modal").click(function(){
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
            //为添加员工的保存按钮绑定单击事件
            $("#emp_saveBtn").click(function(){
                //模态框中保存按钮发送ajax请求
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/emp",
                    //请求要带的数据,这里是模态框中的值,
                    //这里应该采用的是jQuery的序列化表单的方法进行提取表单数据,serialize();
                    //表单序列化的数据:$("#addEmpModal form").serialize();
                    data:$("#addEmpModal form").serialize(),
                    //请求成功的回调函数
                    success : function(result) {
                        alert("保存成功!");
                    }
                });
            });
        </script>
    </body>
    </html>
    View Code

     【更新】:jQuery表单的序列化

        1..serialize()——序列化为:a=1&b=2&c=3&d=4&e=5 格式的字符串(springMVC中可直接通过POJO形参接收)

        2.serializeArray()——序列化为:
    [ 
      {name: 'firstname', value: 'Hello'}, 
      {name: 'lastname', value: 'World'},
      {name: 'alias'}, // 值为空
    ]
    详细请参见:http://www.w3school.com.cn/jquery/jquery_ref_ajax.asp

       相应的controller:

    package cn.crud.controller;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    
    import cn.crud.bean.Employee;
    import cn.crud.bean.Msg;
    import cn.crud.service.EmpService;
    
    /**
     * 处理员工的CRUD请求
     * @author Administrator
     *
     */
    @Controller
    public class EmpController {
        
        @Autowired
        private EmpService empService;
        
        /**
         * 处理添加员工的ajax请求的方法
         * @return
         */
        @RequestMapping(value="/emp",method=RequestMethod.POST)
        @ResponseBody
        public Msg saveEmp(Employee employee){
            empService.saveEmp(employee);
            return Msg.success();
        }
        
        /**
         * 分页信息的AJAX请求
         * @ResponseBody可以将返回的对象转为JSON字符串
         * 此注解需要引入jackson的包(以及注解驱动的配置等,这里已经进行配置)
         * 将返回信息包装在msg里
         */
        @RequestMapping("/emps")
        @ResponseBody
        public Msg getEmpsWithJson(@RequestParam(value="pn",defaultValue="1") Integer pn, Model model){
            //改造为一个分页查询
            //在查询之前传入分页参数:起始页和每页记录数
            PageHelper.startPage(pn, 5);
            //后面紧跟的查询就是分页查询
            List<Employee> empList = empService.getAll();
            //用PageInfo对结果进行包装,只需要将PageInfo交给页面即可,这里面封装了详细的信息,第二个参数为需要连续显示的记录数
            PageInfo page = new PageInfo(empList,5);
            //直接将pageInfo对象进行返回
            //将pageInfo放在msg里进行返回,链式操作返回对象本身
            return Msg.success().add("pageInfo", page);
        }
        
        /**
         * 分页查询员工数据
         */
        //@RequestMapping("/emps")
        public String getEmps(@RequestParam(value="pn",defaultValue="1") Integer pn, Model model){
            //改造为一个分页查询
            //在查询之前传入分页参数:起始页和每页记录数
            PageHelper.startPage(pn, 5);
            //后面紧跟的查询就是分页查询
            List<Employee> empList = empService.getAll();
            //用PageInfo对结果进行包装,只需要将PageInfo交给页面即可,这里面封装了详细的信息,第二个参数为需要连续显示的记录数
            PageInfo page = new PageInfo(empList,5);
            model.addAttribute("pageInfo", page);
            return "list";
        }
    }
    View Code

      service:

    package cn.crud.service;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import cn.crud.bean.Employee;
    import cn.crud.dao.EmployeeMapper;
    /**
     * 处理员工的service
     * @author Administrator
     *
     */
    @Service
    public class EmpService {
        
        @Autowired
        private EmployeeMapper employeeMapper;
    
        /**
         * 查询所有员工
         * @return
         */
        public List<Employee> getAll() {
            /**
             * 没有查询条件的查询所有,带部门信息
             */
            return employeeMapper.selectByExampleWithDept(null);
        }
        /**
         * 增加员工
         * @param employee
         */
        public void saveEmp(Employee employee) {
            //我们选择有选择的保存,因为ID是自增的
            employeeMapper.insertSelective(employee);
            
        }
    
    
    }
    View Code

      我们进行简单的测试:

    //我们容易发现一点小问题:

      1.保存成功后模态框应该关闭

      2.列表应该来到最后一页

      我们来进行完善:

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加员工</h4>
              </div>
              <div class="modal-body">
                <form class="form-horizontal">
                  <!-- 输入员工姓名 -->
                  <div class="form-group">
                    <label for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-4" style="120px">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
                            
                        </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_saveBtn">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //全局总记录数,用于查最后一页
            var golbalTotalCount;
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(genderTd)
                        .append(emailTd)
                        .append(deptNameTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                //给全局记录数赋值
                golbalTotalCount = result.map.pageInfo.total;
                
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //增加员工的事件
            $("#addBtn_modal").click(function(){
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
            //为添加员工的保存按钮绑定单击事件
            $("#emp_saveBtn").click(function(){
                //模态框中保存按钮发送ajax请求
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/emp",
                    //请求要带的数据,这里是模态框中的值,
                    //这里应该采用的是jQuery的序列化表单的方法进行提取表单数据,serialize();
                    //表单序列化的数据:$("#addEmpModal form").serialize();
                    data:$("#addEmpModal form").serialize(),
                    //请求成功的回调函数
                    success : function(result) {
                        //alert(result.msg);
                        //1.成功完成模态框
                        $("#addEmpModal").modal('hide')
                        //2.来到列表最后一页
                        //发送ajax请求,显示最后一页,因为插件做了参数合理化配置,可以配置一个比较大的数字
                        //这样,查到的总是最后一页记录,我们使用全局的总记录数
                        toPage(golbalTotalCount);
                        
                    }
                });
            });
        </script>
    </body>
    </html>
    View Code

      //主要做的事情是两个函数的处理,这里利用分页插件的合理化参数进行简化操作

       这样,我们基本添加功能就完成了!

     

      接下来,我们进行添加功能的前端校验,在完成保存添加之前,进行表单数据校验:

    //更新jQuery的获取表单数据的三个方法,详细请参见w3school API (复习jQuery)

    • text() - 设置或返回所选元素的文本内容
    • html() - 设置或返回所选元素的内容(包括 HTML 标记)
    • val() - 设置或返回表单字段的值

      我们对校验部分进行完成:

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加员工</h4>
              </div>
              <div class="modal-body">
                <form class="form-horizontal">
                  <!-- 输入员工姓名 -->
                  <div class="form-group">
                    <label for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-4" style="120px">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
                            
                        </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_saveBtn">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //全局总记录数,用于查最后一页
            var golbalTotalCount;
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(emailTd)
                        .append(genderTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                //给全局记录数赋值
                golbalTotalCount = result.map.pageInfo.total;
                
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //增加员工的事件
            $("#addBtn_modal").click(function(){
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
            //添加表单数据的校验
            function validate_add_form(){
                //1.获取需要校验的值
                //2.使用jQuery正则(api中常用正则)进行校验(校验插件的使用待更新)
                var empNameVal = $("#input_empName").val();
                //校验的正则表达式(可以搜索常用正则)
                var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)/;
                //开始校验用户名
                if(!regName.test(empNameVal)){
                    alert("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    return false;
                }
                //同理,校验邮箱
                var empEmailVal = $("#input_email").val();
                var regEmail = /^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/;
                //开始校验邮箱
                if(!regEmail.test(empEmailVal)){
                    alert("邮箱不合法!");
                    return false;
                }
                return true;
            }
            //为添加员工的保存按钮绑定单击事件
            $("#emp_saveBtn").click(function(){
                //1.进行表单数据的校验
                if(!validate_add_form()){
                    return false;
                }
                //2.模态框中保存按钮发送ajax请求
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/emp",
                    //请求要带的数据,这里是模态框中的值,
                    //这里应该采用的是jQuery的序列化表单的方法进行提取表单数据,serialize();
                    //表单序列化的数据:$("#addEmpModal form").serialize();
                    data:$("#addEmpModal form").serialize(),
                    //请求成功的回调函数
                    success : function(result) {
                        //alert(result.msg);
                        //1.成功完成模态框
                        $("#addEmpModal").modal('hide')
                        //2.来到列表最后一页
                        //发送ajax请求,显示最后一页,因为插件做了参数合理化配置,可以配置一个比较大的数字
                        //这样,查到的总是最后一页记录,我们使用全局的总记录数
                        toPage(golbalTotalCount);
                        
                    }
                });
            });
        </script>
    </body>
    </html>
    View Code

      简单测试:

      当然,这种样式与体验是比较不好的,我们使用bootstrap的样式进行改善:

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加员工</h4>
              </div>
              <div class="modal-body">
                <form class="form-horizontal">
                  <!-- 输入员工姓名 -->
                  <div class="form-group">
                    <label for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-4" style="120px">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
                            
                        </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_saveBtn">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //全局总记录数,用于查最后一页
            var golbalTotalCount;
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(emailTd)
                        .append(genderTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                //给全局记录数赋值
                golbalTotalCount = result.map.pageInfo.total;
                
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //增加员工的事件
            $("#addBtn_modal").click(function(){
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
            //添加表单数据的校验
            function validate_add_form(){
                //1.获取需要校验的值
                //2.使用jQuery正则(api中常用正则)进行校验(校验插件的使用待更新)
                var empNameVal = $("#input_empName").val();
                //校验的正则表达式(可以搜索常用正则)
                var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)/;
                //开始校验用户名
                if(!regName.test(empNameVal)){
                    //alert("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //将提示信息优化,使用bootstrap的样式,给父元素添加相应的类即可
                    $("#input_empName").parent().addClass("has-error");
                    $("#input_empName").next(".help-block").text("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    return false;
                }else{
                    $("#input_empName").parent().addClass("has-success");
                    $("#input_empName").next(".help-block").text("用户名正确!");
                }
                //同理,校验邮箱
                var empEmailVal = $("#input_email").val();
                var regEmail = /^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/;
                //开始校验邮箱
                if(!regEmail.test(empEmailVal)){
                    //alert("邮箱不合法!");
                    $("#input_email").parent().addClass("has-error");
                    $("#input_email").next(".help-block").text("邮箱不合法!");
                    return false;
                }else{
                    $("#input_email").parent().addClass("has-success");
                    $("#input_email").next(".help-block").text("邮箱格式正确!");
                }
                return true;
            }
            //为添加员工的保存按钮绑定单击事件
            $("#emp_saveBtn").click(function(){
                //1.进行表单数据的校验
                if(!validate_add_form()){
                    return false;
                }
                //2.模态框中保存按钮发送ajax请求
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/emp",
                    //请求要带的数据,这里是模态框中的值,
                    //这里应该采用的是jQuery的序列化表单的方法进行提取表单数据,serialize();
                    //表单序列化的数据:$("#addEmpModal form").serialize();
                    data:$("#addEmpModal form").serialize(),
                    //请求成功的回调函数
                    success : function(result) {
                        //alert(result.msg);
                        //1.成功完成模态框
                        $("#addEmpModal").modal('hide')
                        //2.来到列表最后一页
                        //发送ajax请求,显示最后一页,因为插件做了参数合理化配置,可以配置一个比较大的数字
                        //这样,查到的总是最后一页记录,我们使用全局的总记录数
                        toPage(golbalTotalCount);
                    }
                });
            });
        </script>
    </body>
    </html>
    View Code

      这样,我们得到校验的结果:

      很明显,这个校验存在问题,

         我们右键,检查,查看原因:

    //我们可以发现,这里是进行了追加,而不是替换,我们需要进行改善:

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加员工</h4>
              </div>
              <div class="modal-body">
                <form class="form-horizontal">
                  <!-- 输入员工姓名 -->
                  <div class="form-group">
                    <label for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-4" style="120px">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
                            
                        </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_saveBtn">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //全局总记录数,用于查最后一页
            var golbalTotalCount;
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(emailTd)
                        .append(genderTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                //给全局记录数赋值
                golbalTotalCount = result.map.pageInfo.total;
                
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //增加员工的事件
            $("#addBtn_modal").click(function(){
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
            //添加表单数据的校验
            function validate_add_form(){
                //1.获取需要校验的值
                //2.使用jQuery正则(api中常用正则)进行校验(校验插件的使用待更新)
                var empNameVal = $("#input_empName").val();
                //校验的正则表达式(可以搜索常用正则)
                var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)/;
                //开始校验用户名
                if(!regName.test(empNameVal)){
                    //alert("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //将提示信息优化,使用bootstrap的样式,给父元素添加相应的类即可
                    vilidate_form("#input_empName","error","用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //$("#input_empName").parent().addClass("has-error");
                    //$("#input_empName").next(".help-block").text("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    return false;
                }else{
                    vilidate_form("#input_empName","success","用户名正确!");
                    //$("#input_empName").parent().addClass("has-success");
                    //$("#input_empName").next(".help-block").text("用户名正确!");
                }
                //同理,校验邮箱
                var empEmailVal = $("#input_email").val();
                var regEmail = /^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/;
                //开始校验邮箱
                if(!regEmail.test(empEmailVal)){
                    //alert("邮箱不合法!");
                    vilidate_form("#input_email","error","邮箱不合法!");
                    //$("#input_email").parent().addClass("has-error");
                    //$("#input_email").next(".help-block").text("邮箱不合法!");
                    return false;
                }else{
                    vilidate_form("#input_email","success","邮箱格式正确!");
                    //$("#input_email").parent().addClass("has-success");
                    //$("#input_email").next(".help-block").text("邮箱格式正确!");
                }
                return true;
            }
            //重新抽取校验函数完成之前重复样式的清除工作
            function vilidate_form(ele,status,msg){
                    //清除当前校验状态
                    $(ele).parent().removeClass("has-success has-error");
                    $(ele).next(".help-block").text("");
                if("success" == status){
                    $(ele).parent().addClass("has-success");
                    $(ele).next(".help-block").text(msg);
                }else if("error" == status){
                    $(ele).parent().addClass("has-error");
                    $(ele).next(".help-block").text(msg);
                }
            }
            //为添加员工的保存按钮绑定单击事件
            $("#emp_saveBtn").click(function(){
                //1.进行表单数据的校验
                if(!validate_add_form()){
                    return false;
                }
                //2.模态框中保存按钮发送ajax请求
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/emp",
                    //请求要带的数据,这里是模态框中的值,
                    //这里应该采用的是jQuery的序列化表单的方法进行提取表单数据,serialize();
                    //表单序列化的数据:$("#addEmpModal form").serialize();
                    data:$("#addEmpModal form").serialize(),
                    //请求成功的回调函数
                    success : function(result) {
                        //alert(result.msg);
                        //1.成功完成模态框
                        $("#addEmpModal").modal('hide')
                        //2.来到列表最后一页
                        //发送ajax请求,显示最后一页,因为插件做了参数合理化配置,可以配置一个比较大的数字
                        //这样,查到的总是最后一页记录,我们使用全局的总记录数
                        toPage(golbalTotalCount);
                    }
                });
            });
        </script>
    </body>
    </html>
    View Code

      简单测试:

      这样我们前端校验就到此结束!但是用户名呢不能重复,前端是操作不了这个的,我们进行后端的校验。

      接下来我们进行后端员工姓名重复的后端校验!

        我们通过前台发送ajax请求检查是否用户名是否可用,我们先编写相关的controller:

    package cn.crud.controller;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    
    import cn.crud.bean.Employee;
    import cn.crud.bean.Msg;
    import cn.crud.service.EmpService;
    
    /**
     * 处理员工的CRUD请求
     * @author Administrator
     *
     */
    @Controller
    public class EmpController {
        
        @Autowired
        private EmpService empService;
        
        /**
         * 校验用户名是否重复,是否可用的方法
         * @return 返回的是我们包装的对象
         */
        @RequestMapping("/vadEmpName")
        @ResponseBody
        public Msg vadEmpName(@RequestParam("empName") String empName){
            boolean isRepet = empService.vadEmpName(empName);
            if(isRepet){
                return Msg.success();
            }else{
                return Msg.fail();
            }
            
        }
        
        /**
         * 处理添加员工的ajax请求的方法
         * @return
         */
        @RequestMapping(value="/emp",method=RequestMethod.POST)
        @ResponseBody
        public Msg saveEmp(Employee employee){
            empService.saveEmp(employee);
            return Msg.success();
        }
        
        /**
         * 分页信息的AJAX请求
         * @ResponseBody可以将返回的对象转为JSON字符串
         * 此注解需要引入jackson的包(以及注解驱动的配置等,这里已经进行配置)
         * 将返回信息包装在msg里
         */
        @RequestMapping("/emps")
        @ResponseBody
        public Msg getEmpsWithJson(@RequestParam(value="pn",defaultValue="1") Integer pn, Model model){
            //改造为一个分页查询
            //在查询之前传入分页参数:起始页和每页记录数
            PageHelper.startPage(pn, 5);
            //后面紧跟的查询就是分页查询
            List<Employee> empList = empService.getAll();
            //用PageInfo对结果进行包装,只需要将PageInfo交给页面即可,这里面封装了详细的信息,第二个参数为需要连续显示的记录数
            PageInfo page = new PageInfo(empList,5);
            //直接将pageInfo对象进行返回
            //将pageInfo放在msg里进行返回,链式操作返回对象本身
            return Msg.success().add("pageInfo", page);
        }
        
        /**
         * 分页查询员工数据
         */
        //@RequestMapping("/emps")
        public String getEmps(@RequestParam(value="pn",defaultValue="1") Integer pn, Model model){
            //改造为一个分页查询
            //在查询之前传入分页参数:起始页和每页记录数
            PageHelper.startPage(pn, 5);
            //后面紧跟的查询就是分页查询
            List<Employee> empList = empService.getAll();
            //用PageInfo对结果进行包装,只需要将PageInfo交给页面即可,这里面封装了详细的信息,第二个参数为需要连续显示的记录数
            PageInfo page = new PageInfo(empList,5);
            model.addAttribute("pageInfo", page);
            return "list";
        }
    }
    View Code

        这里注意相关的service是如何实现的:

    package cn.crud.service;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import cn.crud.bean.Employee;
    import cn.crud.bean.EmployeeExample;
    import cn.crud.bean.EmployeeExample.Criteria;
    import cn.crud.dao.EmployeeMapper;
    /**
     * 处理员工的service
     * @author Administrator
     *
     */
    @Service
    public class EmpService {
        
        @Autowired
        private EmployeeMapper employeeMapper;
    
        /**
         * 查询所有员工
         * @return
         */
        public List<Employee> getAll() {
            /**
             * 没有查询条件的查询所有,带部门信息
             */
            return employeeMapper.selectByExampleWithDept(null);
        }
        /**
         * 增加员工
         * @param employee
         */
        public void saveEmp(Employee employee) {
            //我们选择有选择的保存,因为ID是自增的
            employeeMapper.insertSelective(employee);
            
        }
        /**
         * 检验用户名是否可用
         * @param empName
         * @return
         */
        public boolean vadEmpName(String empName) {
            /*按要求统计符合条件记录数,返回一个整数*/
            //构建example
            EmployeeExample example = new EmployeeExample();
            //构建查询条件 criteria
            Criteria criteria = example.createCriteria();
            //构建条件
            criteria.andEmpNameEqualTo(empName);
            //返回符合条件的记录数,==0时可用
            long count = employeeMapper.countByExample(example);
            return count == 0;
        }
    
    
    }
    View Code

        前台就相应的完成:

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加员工</h4>
              </div>
              <div class="modal-body">
                <form class="form-horizontal">
                  <!-- 输入员工姓名 -->
                  <div class="form-group">
                    <label for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-4" style="120px">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
                            
                        </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_saveBtn">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //全局总记录数,用于查最后一页
            var golbalTotalCount;
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(emailTd)
                        .append(genderTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                //给全局记录数赋值
                golbalTotalCount = result.map.pageInfo.total;
                
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //增加员工的事件
            $("#addBtn_modal").click(function(){
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
            //添加表单数据的前段校验
            function validate_add_form(){
                //1.获取需要校验的值
                //2.使用jQuery正则(api中常用正则)进行校验(校验插件的使用待更新)
                var empNameVal = $("#input_empName").val();
                //校验的正则表达式(可以搜索常用正则)
                var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)/;
                //开始校验用户名
                if(!regName.test(empNameVal)){
                    //alert("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //将提示信息优化,使用bootstrap的样式,给父元素添加相应的类即可
                    vilidate_form("#input_empName","error","用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //$("#input_empName").parent().addClass("has-error");
                    //$("#input_empName").next(".help-block").text("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    return false;
                }else{
                    vilidate_form("#input_empName","success","用户名正确!");
                    //$("#input_empName").parent().addClass("has-success");
                    //$("#input_empName").next(".help-block").text("用户名正确!");
                }
                //同理,校验邮箱
                var empEmailVal = $("#input_email").val();
                var regEmail = /^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/;
                //开始校验邮箱
                if(!regEmail.test(empEmailVal)){
                    //alert("邮箱不合法!");
                    vilidate_form("#input_email","error","邮箱不合法!");
                    //$("#input_email").parent().addClass("has-error");
                    //$("#input_email").next(".help-block").text("邮箱不合法!");
                    return false;
                }else{
                    vilidate_form("#input_email","success","邮箱格式正确!");
                    //$("#input_email").parent().addClass("has-success");
                    //$("#input_email").next(".help-block").text("邮箱格式正确!");
                }
                return true;
            }
            //重新抽取校验函数完成之前重复样式的清除工作
            function vilidate_form(ele,status,msg){
                    //清除当前校验状态
                    $(ele).parent().removeClass("has-success has-error");
                    $(ele).next(".help-block").text("");
                if("success" == status){
                    $(ele).parent().addClass("has-success");
                    $(ele).next(".help-block").text(msg);
                }else if("error" == status){
                    $(ele).parent().addClass("has-error");
                    $(ele).next(".help-block").text(msg);
                }
            }
            //为添加员工姓名输入框添加change事件,完成用户名重复的后端校验
            $("#input_empName").change(function(){
                //发送ajax请求,查询用户名是否重复
                var empName = this.value;
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/vadEmpName",
                    //请求要带的数据
                    data:"empName="+empName,
                    //请求成功的回调函数
                    success : function(result) {
                        if(result.code == 100){//成功,用户名可用
                            vilidate_form("#input_empName","success","用户名可用!");
                        }else{//失败,用户名不可用
                            vilidate_form("#input_empName","error","用户名已被占用!");
                        }
                    }
                });
            });
            //为添加员工的保存按钮绑定单击事件
            $("#emp_saveBtn").click(function(){
                //1.进行表单数据的校验
                if(!validate_add_form()){
                    return false;
                }
                //2.模态框中保存按钮发送ajax请求
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/emp",
                    //请求要带的数据,这里是模态框中的值,
                    //这里应该采用的是jQuery的序列化表单的方法进行提取表单数据,serialize();
                    //表单序列化的数据:$("#addEmpModal form").serialize();
                    data:$("#addEmpModal form").serialize(),
                    //请求成功的回调函数
                    success : function(result) {
                        //alert(result.msg);
                        //1.成功完成模态框
                        $("#addEmpModal").modal('hide')
                        //2.来到列表最后一页
                        //发送ajax请求,显示最后一页,因为插件做了参数合理化配置,可以配置一个比较大的数字
                        //这样,查到的总是最后一页记录,我们使用全局的总记录数
                        toPage(golbalTotalCount);
                    }
                });
            });
        </script>
    </body>
    </html>
    View Code

        简单测试:

         当然,这里会有个问题,即使用户名被占用了,只要邮箱正确,依旧可以保存!我们查看我们的代码可以发现,我们校验后只是进行了提示信息的显示,我们需要进行改善:

        这里我们可以将被占用的校验结果进行保存,然后用这个结果去禁用保存按钮,失败则使得按钮无法生效!

          这里采用的方式是给按钮添加自定义属性,再进行自定义属性的内容校验:

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加员工</h4>
              </div>
              <div class="modal-body">
                <form class="form-horizontal">
                  <!-- 输入员工姓名 -->
                  <div class="form-group">
                    <label for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-4" style="120px">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
                            
                        </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_saveBtn">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //全局总记录数,用于查最后一页
            var golbalTotalCount;
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(emailTd)
                        .append(genderTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                //给全局记录数赋值
                golbalTotalCount = result.map.pageInfo.total;
                
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //增加员工的事件
            $("#addBtn_modal").click(function(){
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
            //添加表单数据的前段校验
            function validate_add_form(){
                //1.获取需要校验的值
                //2.使用jQuery正则(api中常用正则)进行校验(校验插件的使用待更新)
                var empNameVal = $("#input_empName").val();
                //校验的正则表达式(可以搜索常用正则)
                var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)/;
                //开始校验用户名
                if(!regName.test(empNameVal)){
                    //alert("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //将提示信息优化,使用bootstrap的样式,给父元素添加相应的类即可
                    vilidate_form("#input_empName","error","用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //$("#input_empName").parent().addClass("has-error");
                    //$("#input_empName").next(".help-block").text("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    return false;
                }else{
                    vilidate_form("#input_empName","success","用户名正确!");
                    //$("#input_empName").parent().addClass("has-success");
                    //$("#input_empName").next(".help-block").text("用户名正确!");
                }
                //同理,校验邮箱
                var empEmailVal = $("#input_email").val();
                var regEmail = /^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/;
                //开始校验邮箱
                if(!regEmail.test(empEmailVal)){
                    //alert("邮箱不合法!");
                    vilidate_form("#input_email","error","邮箱不合法!");
                    //$("#input_email").parent().addClass("has-error");
                    //$("#input_email").next(".help-block").text("邮箱不合法!");
                    return false;
                }else{
                    vilidate_form("#input_email","success","邮箱格式正确!");
                    //$("#input_email").parent().addClass("has-success");
                    //$("#input_email").next(".help-block").text("邮箱格式正确!");
                }
                return true;
            }
            //重新抽取校验函数完成之前重复样式的清除工作
            function vilidate_form(ele,status,msg){
                    //清除当前校验状态
                    $(ele).parent().removeClass("has-success has-error");
                    $(ele).next(".help-block").text("");
                if("success" == status){
                    $(ele).parent().addClass("has-success");
                    $(ele).next(".help-block").text(msg);
                }else if("error" == status){
                    $(ele).parent().addClass("has-error");
                    $(ele).next(".help-block").text(msg);
                }
            }
            //为添加员工姓名输入框添加change事件,完成用户名重复的后端校验
            $("#input_empName").change(function(){
                //发送ajax请求,查询用户名是否重复
                var empName = this.value;
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/vadEmpName",
                    //请求要带的数据
                    data:"empName="+empName,
                    //请求成功的回调函数
                    success : function(result) {
                        if(result.code == 100){//成功,用户名可用
                            vilidate_form("#input_empName","success","用户名可用!");
                            $("#emp_saveBtn").attr("ajax-vad","success");
                        }else{//失败,用户名不可用
                            vilidate_form("#input_empName","error","用户名已被占用!");
                            $("#emp_saveBtn").attr("ajax-vad","error");
                        }
                    }
                });
            });
            //为添加员工的保存按钮绑定单击事件
            $("#emp_saveBtn").click(function(){
                //1.5发送ajax请求之前进行用户名是否可用的校验:
                if($(this).attr("ajax-vad")=="error"){
                    return false;
                }
                //1.进行表单数据的校验
                if(!validate_add_form()){
                    return false;
                }
                
                //2.模态框中保存按钮发送ajax请求
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/emp",
                    //请求要带的数据,这里是模态框中的值,
                    //这里应该采用的是jQuery的序列化表单的方法进行提取表单数据,serialize();
                    //表单序列化的数据:$("#addEmpModal form").serialize();
                    data:$("#addEmpModal form").serialize(),
                    //请求成功的回调函数
                    success : function(result) {
                        //alert(result.msg);
                        //1.成功完成模态框
                        $("#addEmpModal").modal('hide')
                        //2.来到列表最后一页
                        //发送ajax请求,显示最后一页,因为插件做了参数合理化配置,可以配置一个比较大的数字
                        //这样,查到的总是最后一页记录,我们使用全局的总记录数
                        toPage(golbalTotalCount);
                    }
                });
            });
        </script>
    </body>
    </html>
    View Code

          测试这里暂时略去

          这里还有个问题是:由于我们是ajax,页面没有刷新,如果直接再次直接添加,原来输入框的内容不做修改,直接点击保存也会保存成功!

      这样就造成了重复添加,原因呢是页面没有刷新,二校验用户可用的事件是change()事件,如果输入框内容没有change,而原来的内容又可以通过校验,就造成了重复添加!

          我们解决方案是在添加之前进行重置,当然jQuery是没有reset方法,我们使用js的reset()方法,完成了表单的重置!:

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加员工</h4>
              </div>
              <div class="modal-body">
                <form class="form-horizontal">
                  <!-- 输入员工姓名 -->
                  <div class="form-group">
                    <label for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-4" style="120px">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
                            
                        </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_saveBtn">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //全局总记录数,用于查最后一页
            var golbalTotalCount;
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(emailTd)
                        .append(genderTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                //给全局记录数赋值
                golbalTotalCount = result.map.pageInfo.total;
                
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //清空表单样式及内容
            function reset_form(ele){
                $(ele)[0].reset();
                //清空表单样式
                $(ele).find("*").removeClass("has-error has-success");
                $(ele).find(".help-block").text("");
            }
            //增加员工的事件,弹出员工模态框
            $("#addBtn_modal").click(function(){
                //重置表单:
                reset_form("#addEmpModal form");
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
            //添加表单数据的前段校验
            function validate_add_form(){
                //1.获取需要校验的值
                //2.使用jQuery正则(api中常用正则)进行校验(校验插件的使用待更新)
                var empNameVal = $("#input_empName").val();
                //校验的正则表达式(可以搜索常用正则)
                var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)/;
                //开始校验用户名
                if(!regName.test(empNameVal)){
                    //alert("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //将提示信息优化,使用bootstrap的样式,给父元素添加相应的类即可
                    vilidate_form("#input_empName","error","用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //$("#input_empName").parent().addClass("has-error");
                    //$("#input_empName").next(".help-block").text("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    return false;
                }else{
                    vilidate_form("#input_empName","success","用户名正确!");
                    //$("#input_empName").parent().addClass("has-success");
                    //$("#input_empName").next(".help-block").text("用户名正确!");
                }
                //同理,校验邮箱
                var empEmailVal = $("#input_email").val();
                var regEmail = /^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/;
                //开始校验邮箱
                if(!regEmail.test(empEmailVal)){
                    //alert("邮箱不合法!");
                    vilidate_form("#input_email","error","邮箱不合法!");
                    //$("#input_email").parent().addClass("has-error");
                    //$("#input_email").next(".help-block").text("邮箱不合法!");
                    return false;
                }else{
                    vilidate_form("#input_email","success","邮箱格式正确!");
                    //$("#input_email").parent().addClass("has-success");
                    //$("#input_email").next(".help-block").text("邮箱格式正确!");
                }
                return true;
            }
            //重新抽取校验函数完成之前重复样式的清除工作
            function vilidate_form(ele,status,msg){
                    //清除当前校验状态
                    $(ele).parent().removeClass("has-success has-error");
                    $(ele).next(".help-block").text("");
                if("success" == status){
                    $(ele).parent().addClass("has-success");
                    $(ele).next(".help-block").text(msg);
                }else if("error" == status){
                    $(ele).parent().addClass("has-error");
                    $(ele).next(".help-block").text(msg);
                }
            }
            //为添加员工姓名输入框添加change事件,完成用户名重复的后端校验
            $("#input_empName").change(function(){
                //发送ajax请求,查询用户名是否重复
                var empName = this.value;
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/vadEmpName",
                    //请求要带的数据
                    data:"empName="+empName,
                    //请求成功的回调函数
                    success : function(result) {
                        if(result.code == 100){//成功,用户名可用
                            vilidate_form("#input_empName","success","用户名可用!");
                            $("#emp_saveBtn").attr("ajax-vad","success");
                        }else{//失败,用户名不可用
                            vilidate_form("#input_empName","error","用户名已被占用!");
                            $("#emp_saveBtn").attr("ajax-vad","error");
                        }
                    }
                });
            });
            //为添加员工的保存按钮绑定单击事件
            $("#emp_saveBtn").click(function(){
                
                //1.5发送ajax请求之前进行用户名是否可用的校验:
                if($(this).attr("ajax-vad")=="error"){
                    return false;
                }
                //1.进行表单数据的校验
                if(!validate_add_form()){
                    return false;
                }
                //2.模态框中保存按钮发送ajax请求
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/emp",
                    //请求要带的数据,这里是模态框中的值,
                    //这里应该采用的是jQuery的序列化表单的方法进行提取表单数据,serialize();
                    //表单序列化的数据:$("#addEmpModal form").serialize();
                    data:$("#addEmpModal form").serialize(),
                    //请求成功的回调函数
                    success : function(result) {
                        //alert(result.msg);
                        //1.成功完成模态框
                        $("#addEmpModal").modal('hide')
                        //2.来到列表最后一页
                        //发送ajax请求,显示最后一页,因为插件做了参数合理化配置,可以配置一个比较大的数字
                        //这样,查到的总是最后一页记录,我们使用全局的总记录数
                        toPage(golbalTotalCount);
                    }
                });
            });
        </script>
    </body>
    </html>
    View Code

          

    //再次点击新增,完成了新增前表单信息的清空

         但是我们多测试几次,会发现校验逻辑会有一点问题,比如前面提示用户名可用(不重复),后面提交时又会出现格式不正确,造成校验信息的混乱!我们再次完善:

      解决方案是让前后台统一校验顺序与规则,当格式不正确时不进行重复性校验:

         前台完成表单内容和样式的移除,以及后台校验回来的校验信息的更改:

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加员工</h4>
              </div>
              <div class="modal-body">
                <form class="form-horizontal">
                  <!-- 输入员工姓名 -->
                  <div class="form-group">
                    <label for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-4" style="120px">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
                            
                        </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_saveBtn">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //全局总记录数,用于查最后一页
            var golbalTotalCount;
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(emailTd)
                        .append(genderTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                //给全局记录数赋值
                golbalTotalCount = result.map.pageInfo.total;
                
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //清空表单样式及内容
            function reset_form(ele){
                $(ele)[0].reset();
                //清空表单样式
                $(ele).find("*").removeClass("has-error has-success");
                $(ele).find(".help-block").text("");
            }
            //增加员工的事件,弹出员工模态框
            $("#addBtn_modal").click(function(){
                //重置表单:
                reset_form("#addEmpModal form");
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
            //添加表单数据的前段校验
            function validate_add_form(){
                //1.获取需要校验的值
                //2.使用jQuery正则(api中常用正则)进行校验(校验插件的使用待更新)
                var empNameVal = $("#input_empName").val();
                //校验的正则表达式(可以搜索常用正则)
                var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)/;
                //开始校验用户名
                if(!regName.test(empNameVal)){
                    //alert("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //将提示信息优化,使用bootstrap的样式,给父元素添加相应的类即可
                    vilidate_form("#input_empName","error","用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //$("#input_empName").parent().addClass("has-error");
                    //$("#input_empName").next(".help-block").text("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    return false;
                }else{
                    vilidate_form("#input_empName","success","用户名正确!");
                    //$("#input_empName").parent().addClass("has-success");
                    //$("#input_empName").next(".help-block").text("用户名正确!");
                }
                //同理,校验邮箱
                var empEmailVal = $("#input_email").val();
                var regEmail = /^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/;
                //开始校验邮箱
                if(!regEmail.test(empEmailVal)){
                    //alert("邮箱不合法!");
                    vilidate_form("#input_email","error","邮箱不合法!");
                    //$("#input_email").parent().addClass("has-error");
                    //$("#input_email").next(".help-block").text("邮箱不合法!");
                    return false;
                }else{
                    vilidate_form("#input_email","success","邮箱格式正确!");
                    //$("#input_email").parent().addClass("has-success");
                    //$("#input_email").next(".help-block").text("邮箱格式正确!");
                }
                return true;
            }
            //重新抽取校验函数完成之前重复样式的清除工作
            function vilidate_form(ele,status,msg){
                    //清除当前校验状态
                    $(ele).parent().removeClass("has-success has-error");
                    $(ele).next(".help-block").text("");
                if("success" == status){
                    $(ele).parent().addClass("has-success");
                    $(ele).next(".help-block").text(msg);
                }else if("error" == status){
                    $(ele).parent().addClass("has-error");
                    $(ele).next(".help-block").text(msg);
                }
            }
            //为添加员工姓名输入框添加change事件,完成用户名重复的后端校验
            $("#input_empName").change(function(){
                //发送ajax请求,查询用户名是否重复
                var empName = this.value;
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/vadEmpName",
                    //请求要带的数据
                    data:"empName="+empName,
                    //请求成功的回调函数
                    success : function(result) {
                        if(result.code == 100){//成功,用户名可用
                            vilidate_form("#input_empName","success","用户名可用!");
                            $("#emp_saveBtn").attr("ajax-vad","success");
                        }else{//失败,用户名不可用
                            vilidate_form("#input_empName","error",result.map.vadFailMeg);
                            $("#emp_saveBtn").attr("ajax-vad","error");
                        }
                    }
                });
            });
            //为添加员工的保存按钮绑定单击事件
            $("#emp_saveBtn").click(function(){
                
                //1.5发送ajax请求之前进行用户名是否可用的校验:
                if($(this).attr("ajax-vad")=="error"){
                    return false;
                }
                //1.进行表单数据的校验
                if(!validate_add_form()){
                    return false;
                }
                //2.模态框中保存按钮发送ajax请求
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/emp",
                    //请求要带的数据,这里是模态框中的值,
                    //这里应该采用的是jQuery的序列化表单的方法进行提取表单数据,serialize();
                    //表单序列化的数据:$("#addEmpModal form").serialize();
                    data:$("#addEmpModal form").serialize(),
                    //请求成功的回调函数
                    success : function(result) {
                        //alert(result.msg);
                        //1.成功完成模态框
                        $("#addEmpModal").modal('hide')
                        //2.来到列表最后一页
                        //发送ajax请求,显示最后一页,因为插件做了参数合理化配置,可以配置一个比较大的数字
                        //这样,查到的总是最后一页记录,我们使用全局的总记录数
                        toPage(golbalTotalCount);
                    }
                });
            });
        </script>
    </body>
    </html>
    View Code

        后台校验加格式的校验和错误信息:

    package cn.crud.controller;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    
    import cn.crud.bean.Employee;
    import cn.crud.bean.Msg;
    import cn.crud.service.EmpService;
    
    /**
     * 处理员工的CRUD请求
     * @author Administrator
     *
     */
    @Controller
    public class EmpController {
        
        @Autowired
        private EmpService empService;
        
        /**
         * 校验用户名是否重复,是否可用的方法
         * @return 返回的是我们包装的对象
         */
        @RequestMapping("/vadEmpName")
        @ResponseBody
        public Msg vadEmpName(@RequestParam("empName") String empName){
            //在判断是否重复之前,先进行格式是否正确的校验
            //校验的正则表达式(可以搜索常用正则)
            //特别注意这里的正则和js的正则不一样,加 / 包裹的是js的写法
            String regName = "(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)";
            boolean b = empName.matches(regName);
            if(!b){
                return Msg.fail().add("vadFailMeg", "用户名格式错误!");
            }
            //后端用户名重复性校验
            boolean isRepet = empService.vadEmpName(empName);
            if(isRepet){
                return Msg.success();
            }else{
                return Msg.fail().add("vadFailMeg", "用户名已被占用!");
            }
            
        }
        
        /**
         * 处理添加员工的ajax请求的方法
         * @return
         */
        @RequestMapping(value="/emp",method=RequestMethod.POST)
        @ResponseBody
        public Msg saveEmp(Employee employee){
            empService.saveEmp(employee);
            return Msg.success();
        }
        
        /**
         * 分页信息的AJAX请求
         * @ResponseBody可以将返回的对象转为JSON字符串
         * 此注解需要引入jackson的包(以及注解驱动的配置等,这里已经进行配置)
         * 将返回信息包装在msg里
         */
        @RequestMapping("/emps")
        @ResponseBody
        public Msg getEmpsWithJson(@RequestParam(value="pn",defaultValue="1") Integer pn, Model model){
            //改造为一个分页查询
            //在查询之前传入分页参数:起始页和每页记录数
            PageHelper.startPage(pn, 5);
            //后面紧跟的查询就是分页查询
            List<Employee> empList = empService.getAll();
            //用PageInfo对结果进行包装,只需要将PageInfo交给页面即可,这里面封装了详细的信息,第二个参数为需要连续显示的记录数
            PageInfo page = new PageInfo(empList,5);
            //直接将pageInfo对象进行返回
            //将pageInfo放在msg里进行返回,链式操作返回对象本身
            return Msg.success().add("pageInfo", page);
        }
        
        /**
         * 分页查询员工数据
         */
        //@RequestMapping("/emps")
        public String getEmps(@RequestParam(value="pn",defaultValue="1") Integer pn, Model model){
            //改造为一个分页查询
            //在查询之前传入分页参数:起始页和每页记录数
            PageHelper.startPage(pn, 5);
            //后面紧跟的查询就是分页查询
            List<Employee> empList = empService.getAll();
            //用PageInfo对结果进行包装,只需要将PageInfo交给页面即可,这里面封装了详细的信息,第二个参数为需要连续显示的记录数
            PageInfo page = new PageInfo(empList,5);
            model.addAttribute("pageInfo", page);
            return "list";
        }
    }
    View Code

        测试这里就暂时略去。

        到这里,前端校验就暂时告一段落,其实我们可以发现,前端校验是给不做坏事的用户的温馨的提示的,但是如果有人捣蛋,通过伪装一些参数,通过查看源代码,修改相关的样式甚至是禁用一些JS就可以跳过一些前端的校验,也就是说,前端校验是防君子不妨小人。这里,我们开始引入正式的后端校验:JSR303后端校验!

      关于JSR303的校验这里不详细展开,暂时只做简单介绍:

        1.要支持JSR303,需要导入hibernate-validator的包(JSR303的一个实现)

    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.4.1.Final</version>
    </dependency>
    View Code

        2.在实体类上加上相应的注解(详细API请查看官网文档)

          Employee实体类:

    package cn.crud.bean;
    
    import javax.validation.constraints.Pattern;
    
    public class Employee {
        
        public Employee() {
            super();
        }
    
        public Employee(Integer empId, String empName, String gender, String email, Integer dId) {
            super();
            this.empId = empId;
            this.empName = empName;
            this.gender = gender;
            this.email = email;
            this.dId = dId;
        }
    
        private Integer empId;
    
        /*使用JSR303完成后端校验*/
        //使用自定义校验正则表达式
        @Pattern(regexp="(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)"
                    ,message="用户名只能是6-16位英文数字或2-5位汉字组合!")
        private String empName;
    
        private String gender;
    
        //可以使用JSR的email校验,@Email
        //这里特别注意正则表达式的写法,遇到真正要用时需要双 \
        @Pattern(regexp="^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$"
                ,message="邮箱格式不正确")
        private String email;
    
        private Integer dId;
        
        private Department department;
    
        public Integer getEmpId() {
            return empId;
        }
    
        public void setEmpId(Integer empId) {
            this.empId = empId;
        }
    
        public String getEmpName() {
            return empName;
        }
    
        public void setEmpName(String empName) {
            this.empName = empName == null ? null : empName.trim();
        }
    
        public String getGender() {
            return gender;
        }
    
        public void setGender(String gender) {
            this.gender = gender == null ? null : gender.trim();
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email == null ? null : email.trim();
        }
    
        public Integer getdId() {
            return dId;
        }
    
        public void setdId(Integer dId) {
            this.dId = dId;
        }
    
        public Department getDepartment() {
            return department;
        }
    
        public void setDepartment(Department department) {
            this.department = department;
        }
    }
    View Code

        3.如何使用?在相关的方法入参使用对应的注解:我们看保存方法的后端校验

    package cn.crud.controller;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.validation.Valid;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.validation.BindingResult;
    import org.springframework.validation.FieldError;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    
    import cn.crud.bean.Employee;
    import cn.crud.bean.Msg;
    import cn.crud.service.EmpService;
    
    /**
     * 处理员工的CRUD请求
     * @author Administrator
     *
     */
    @Controller
    public class EmpController {
        
        @Autowired
        private EmpService empService;
        
        /**
         * 校验用户名是否重复,是否可用的方法
         * @return 返回的是我们包装的对象
         */
        @RequestMapping("/vadEmpName")
        @ResponseBody
        public Msg vadEmpName(@RequestParam("empName") String empName){
            //在判断是否重复之前,先进行格式是否正确的校验
            //校验的正则表达式(可以搜索常用正则)
            //特别注意这里的正则和js的正则不一样,加 / 包裹的是js的写法
            String regName = "(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)";
            boolean b = empName.matches(regName);
            if(!b){
                return Msg.fail().add("vadFailMeg", "用户名格式错误!");
            }
            //后端用户名重复性校验
            boolean isRepet = empService.vadEmpName(empName);
            if(isRepet){
                return Msg.success();
            }else{
                return Msg.fail().add("vadFailMeg", "用户名已被占用!");
            }
            
        }
        
        /**
         * 处理添加员工的ajax请求的方法
         *  1.要支持JSR303后端校验,需要导入hibernate-validate的包
         * 2.在bean的属性中添加相关的注解
         * 3.在方法入参添加相关的注解
         *     @Valid后跟需要校验的对象,BindingResult时校验的结果
         * @return
         */
        @RequestMapping(value="/emp",method=RequestMethod.POST)
        @ResponseBody
        public Msg saveEmp(@Valid Employee employee,BindingResult result){
            if(result.hasErrors()){//若存在错误,校验失败
                //保存错误信息的map,便于封装
                Map<String,Object> errors = new HashMap<String,Object>();
                //返回错误信息
                List<FieldError> fieldErrors = result.getFieldErrors();
                for (FieldError fieldError : fieldErrors) {//遍历错误信息
                    //错误的字段名:
                    System.out.println("错误的字段名:"+fieldError.getField());
                    //错误的提示信息
                    System.out.println("错误信息:"+fieldError.getDefaultMessage());
                    //封装错误信息
                    errors.put(fieldError.getField(), fieldError.getDefaultMessage());
                }
                //最后封装如Msg的map中进行返回
                return Msg.fail().add("fieldErrors", errors);
            }else{
                empService.saveEmp(employee);
                return Msg.success();
            }
            
        }
        
        /**
         * 分页信息的AJAX请求
         * @ResponseBody可以将返回的对象转为JSON字符串
         * 此注解需要引入jackson的包(以及注解驱动的配置等,这里已经进行配置)
         * 将返回信息包装在msg里
         */
        @RequestMapping("/emps")
        @ResponseBody
        public Msg getEmpsWithJson(@RequestParam(value="pn",defaultValue="1") Integer pn, Model model){
            //改造为一个分页查询
            //在查询之前传入分页参数:起始页和每页记录数
            PageHelper.startPage(pn, 5);
            //后面紧跟的查询就是分页查询
            List<Employee> empList = empService.getAll();
            //用PageInfo对结果进行包装,只需要将PageInfo交给页面即可,这里面封装了详细的信息,第二个参数为需要连续显示的记录数
            PageInfo page = new PageInfo(empList,5);
            //直接将pageInfo对象进行返回
            //将pageInfo放在msg里进行返回,链式操作返回对象本身
            return Msg.success().add("pageInfo", page);
        }
        
        /**
         * 分页查询员工数据
         */
        //@RequestMapping("/emps")
        public String getEmps(@RequestParam(value="pn",defaultValue="1") Integer pn, Model model){
            //改造为一个分页查询
            //在查询之前传入分页参数:起始页和每页记录数
            PageHelper.startPage(pn, 5);
            //后面紧跟的查询就是分页查询
            List<Employee> empList = empService.getAll();
            //用PageInfo对结果进行包装,只需要将PageInfo交给页面即可,这里面封装了详细的信息,第二个参数为需要连续显示的记录数
            PageInfo page = new PageInfo(empList,5);
            model.addAttribute("pageInfo", page);
            return "list";
        }
    }
    View Code

        4.在前端使用校验信息:在保存的操作中进行

    <%@ 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("path",request.getContextPath());
    %>
    <!-- 推荐以 / 开始的相对路径(以服务器的根路径为相对路径) -->
    <link href="${path}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <!-- 先引入jQuery,再引入js -->
    <script type="text/javascript" src="${path}/static/bootstrap/js/jquery.min.js"> </script>
    <script src="${path}/static/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
        <!-- 员工新增模态框 -->
        <div class="modal fade" id="addEmpModal" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title" id="myModalLabel">添加员工</h4>
              </div>
              <div class="modal-body">
                <form class="form-horizontal">
                  <!-- 输入员工姓名 -->
                  <div class="form-group">
                    <label for="input_empName" class="col-sm-2 control-label">empName</label>
                    <div class="col-sm-10">
                      <input type="text" name="empName" class="form-control" id="input_empName" placeholder="empName">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 输入员工邮箱 -->
                  <div class="form-group">
                    <label for="input_email" class="col-sm-2 control-label">email</label>
                    <div class="col-sm-10">
                      <input type="text" name="email" class="form-control" id="input_email" placeholder="email">
                      <span class="help-block"></span>
                    </div>
                  </div>
                  <!-- 选择员工性别 -->
                  <div class="form-group">
                      <label class="col-sm-2 control-label">gender</label>
                    <div class="col-sm-2">
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="M" checked></label>
                        </div>
                        <div class="radio">
                          <label>
                            <input type="radio" name="gender" id="input_gender" value="F"></label>
                        </div>
                    </div>
                 </div>
                 <!-- 部门名称 -->
                 <div class="form-group">
                      <label class="col-sm-2 control-label">deptName</label>
                   <div class="col-sm-4" style="120px">    
                        <!-- 部门名称是变动的,这里保存员工是只保存ID的形式 -->
                        <select class="form-control" name="dId">
                            
                        </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_saveBtn">保存</button>
              </div>
            </div>
          </div>
        </div>
        <div class="container">
            <!-- 分为四大行 -->
            <!-- 标题 -->
            <div class="row">
                 <div class="col-md-12">
                    <font size="20">SSM-CRUD</font>
                 </div>
            </div>
            <!-- 按钮 -->
            <div class="row">
                <!-- 偏移4列 -->
                <div class="col-md-4 col-md-offset-8">
                    <button type="button" class="btn btn-primary" id="addBtn_modal">新增</button>
                    <button type="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>empEmail</th>
                                <th>gender</th>
                                <th>deptName</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                        
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- 分页信息 -->
            <div class="row">
                <!-- 分页文字信息,其中分页信息都封装在pageInfo中 -->
                <div class="col-md-6" id="page_info">
                    
                </div>
                <!-- 分页条 -->
                <div class="col-md-6" id="page_nav">
                    
                </div>
            </div>
        </div>
        <script type="text/javascript">
            //全局总记录数,用于查最后一页
            var golbalTotalCount;
            //页面加载完成后直接发送ajax请求,取得分页数据
            $(function(){
                //加载完页面就通过这个函数发ajax请求
                toPage(1);
            });
            //跳转到某页的函数
            function toPage(pn){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/emps",
                    //请求要带的数据
                    data :"pn="+pn,
                    //请求成功的回调函数
                    success : function(result) {
                        //1.解析JSON返回员工数据
                        build_emps_table(result);
                        //2.解析生成分页信息(分页条与分页导航)
                        build_pages_info(result);
                        build_pages_nav(result);
                    }
                });
            }
            //解析员工数据
            function build_emps_table(result){
                //清空表格数据
                $("#emps_table tbody").empty();
                //员工数据
                var emps = result.map.pageInfo.list;
                //使用jQuery遍历数组,遍历的是取出来的json数组,可以通过开发工具查看JSON结构
                $.each(emps,function(idx,item){
                    //使用jQuery生成各列
                    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);
                    //添加操作按钮,通过jQuery的一些操作(例如CSS的追加CSS操作),完成按钮的构建
                    var editBtn = $("<button></button>").addClass("btn btn-info btn-sm")
                                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil"))
                                    .append("编辑");
                    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);
                    //链式操作完成列的添加(链式操作由于jQuery返回的是原元素)
                    $("<tr></tr>").append(empIdTd)
                        .append(empNameTd)
                        .append(emailTd)
                        .append(genderTd)
                        .append(deptNameTd)
                        .append(btnTd)
                        .appendTo($("#emps_table tbody"));
                });
            }
            //生成分页信息
            function build_pages_info(result){
                //清空分页数据
                $("#page_info").empty();
                //当前页
                var currentPage = result.map.pageInfo.pageNum;
                //总页数
                var totalPage = result.map.pageInfo.pages;
                //总记录数
                var totalCount = result.map.pageInfo.total;
                //给全局记录数赋值
                golbalTotalCount = result.map.pageInfo.total;
                
                $("#page_info").append("当前第:"+currentPage+"页,"+"总共:"+totalPage+"页,"+"总共:"+totalCount+"条记录");
            }
            //生成分页导航信息
            function build_pages_nav(result){
                //清空分页导航信息
                $("#page_nav").empty();
                //导航条外层的Ul
                var navUl = $("<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.map.pageInfo.hasPreviousPage == false){
                    firstPageLi.addClass("disabled");
                    prePageLi.addClass("disabled");
                }else{
                    //添加首页和前一页翻页的单机事件
                    firstPageLi.click(function(){
                        toPage(1);
                    });
                    prePageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum-1);
                    });
                }
                
                //后一页
                var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
                //末页
                var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
                //判断是否有末页
                if(result.map.pageInfo.hasNextPage == false){
                    lastPageLi.addClass("disabled");
                    nextPageLi.addClass("disabled");
                }else{
                    //添加末页和后一页翻页的单机事件
                    lastPageLi.click(function(){
                        toPage(result.map.pageInfo.pages);
                    });
                    nextPageLi.click(function(){
                        toPage(result.map.pageInfo.pageNum+1);
                    });
                }
                
                //添加到ul
                navUl.append(firstPageLi).append(prePageLi);
                
                //遍历页码数
                $.each(result.map.pageInfo.navigatepageNums,function(idx,item){
                    var numLi = $("<li></li>").append($("<a></a>").append(item));
                    //如果当前页为正在遍历的页,则高亮显示,采用增加类的方法完成
                    if(result.map.pageInfo.pageNum == item){
                        numLi.addClass("active");
                    }
                    //给每个页码添加单击绑定事件
                    numLi.click(function(){
                        toPage(item);
                    });
                    navUl.append(numLi);
                });
                //li加入ul,ul加入nav
                navUl.append(nextPageLi).append(lastPageLi);
                var navEle = $("<nav></nav>").append(navUl);
                $("#page_nav").append(navEle);
            }
            //清空表单样式及内容
            function reset_form(ele){
                $(ele)[0].reset();
                //清空表单样式
                $(ele).find("*").removeClass("has-error has-success");
                $(ele).find(".help-block").text("");
            }
            //增加员工的事件,弹出员工模态框
            $("#addBtn_modal").click(function(){
                //重置表单:
                reset_form("#addEmpModal form");
                //发送ajax请求查询部门信息
                getDepts();
                //弹出模态框
                $('#addEmpModal').modal({
                    backdrop:false
                });
            });
            //得到部门信息的函数
            function getDepts(){
                $.ajax({
                    //请求方式
                    type : "GET", 
                    //请求url
                    url : "${path}/depts",
                    //请求要带的数据,这里无需带数据
                    //请求成功的回调函数
                    success : function(result) {
                        $.each(result.map.deptList,function(){
                            //这里换用不传参的方式,采用this引用正在遍历的对象
                            var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                            optionEle.appendTo("#addEmpModal select");
                        });
                    }
                });
            }
            //添加表单数据的前段校验
            function validate_add_form(){
                //1.获取需要校验的值
                //2.使用jQuery正则(api中常用正则)进行校验(校验插件的使用待更新)
                var empNameVal = $("#input_empName").val();
                //校验的正则表达式(可以搜索常用正则)
                var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[u2E80-u9FFF]{2,5}$)/;
                //开始校验用户名
                if(!regName.test(empNameVal)){
                    //alert("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //将提示信息优化,使用bootstrap的样式,给父元素添加相应的类即可
                    vilidate_form("#input_empName","error","用户名只能是6-16位英文数字或2-5位汉字组合!");
                    //$("#input_empName").parent().addClass("has-error");
                    //$("#input_empName").next(".help-block").text("用户名只能是6-16位英文数字或2-5位汉字组合!");
                    return false;
                }else{
                    vilidate_form("#input_empName","success","用户名正确!");
                    //$("#input_empName").parent().addClass("has-success");
                    //$("#input_empName").next(".help-block").text("用户名正确!");
                }
                //同理,校验邮箱
                var empEmailVal = $("#input_email").val();
                var regEmail = /^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/;
                //开始校验邮箱
                if(!regEmail.test(empEmailVal)){
                    //alert("邮箱不合法!");
                    vilidate_form("#input_email","error","邮箱不合法!");
                    //$("#input_email").parent().addClass("has-error");
                    //$("#input_email").next(".help-block").text("邮箱不合法!");
                    return false;
                }else{
                    vilidate_form("#input_email","success","邮箱格式正确!");
                    //$("#input_email").parent().addClass("has-success");
                    //$("#input_email").next(".help-block").text("邮箱格式正确!");
                }
                return true;
            }
            //重新抽取校验函数完成之前重复样式的清除工作
            function vilidate_form(ele,status,msg){
                    //清除当前校验状态
                    $(ele).parent().removeClass("has-success has-error");
                    $(ele).next(".help-block").text("");
                if("success" == status){
                    $(ele).parent().addClass("has-success");
                    $(ele).next(".help-block").text(msg);
                }else if("error" == status){
                    $(ele).parent().addClass("has-error");
                    $(ele).next(".help-block").text(msg);
                }
            }
            //为添加员工姓名输入框添加change事件,完成用户名重复的后端校验
            $("#input_empName").change(function(){
                //发送ajax请求,查询用户名是否重复
                var empName = this.value;
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/vadEmpName",
                    //请求要带的数据
                    data:"empName="+empName,
                    //请求成功的回调函数
                    success : function(result) {
                        if(result.code == 100){//成功,用户名可用
                            vilidate_form("#input_empName","success","用户名可用!");
                            $("#emp_saveBtn").attr("ajax-vad","success");
                        }else{//失败,用户名不可用
                            vilidate_form("#input_empName","error",result.map.vadFailMeg);
                            $("#emp_saveBtn").attr("ajax-vad","error");
                        }
                    }
                });
            });
            //为添加员工的保存按钮绑定单击事件
            $("#emp_saveBtn").click(function(){
                
                //1.5发送ajax请求之前进行用户名是否可用的校验:
                if($(this).attr("ajax-vad")=="error"){
                    return false;
                }
                //1.进行表单数据的校验
                 if(!validate_add_form()){
                    return false;
                } 
                //2.模态框中保存按钮发送ajax请求
                $.ajax({
                    //请求方式
                    type : "POST", 
                    //请求url
                    url : "${path}/emp",
                    //请求要带的数据,这里是模态框中的值,
                    //这里应该采用的是jQuery的序列化表单的方法进行提取表单数据,serialize();
                    //表单序列化的数据:$("#addEmpModal form").serialize();
                    data:$("#addEmpModal form").serialize(),
                    //请求成功的回调函数
                    success : function(result) {
                        //alert(result.msg);
                        //添加一个后端校验:
                        if(result.code == 100){//校验成功
                            //1.成功完成模态框则关闭
                            $("#addEmpModal").modal('hide')
                            //2.来到列表最后一页
                            //发送ajax请求,显示最后一页,因为插件做了参数合理化配置,可以配置一个比较大的数字
                            //这样,查到的总是最后一页记录,我们使用全局的总记录数
                            toPage(golbalTotalCount);
                        }else{//校验失败
                            //console.log(result);
                            var emailErrorMsg = result.map.fieldErrors.email;
                            var empNameErrorMsg = result.map.fieldErrors.empName;
                            //有哪个字段的信息就显示哪个
                            if(undefined != emailErrorMsg){
                                //显示邮箱错误信息(之前已经抽象为 方法)
                                vilidate_form("#input_email","error",emailErrorMsg);
                            }
                            if(undefined != empNameErrorMsg){
                                //显示名称错误信息
                                vilidate_form("#input_empName","error",empNameErrorMsg);
                            }
                        }
                        
                    }
                });
            });
        </script>
    </body>
    </html>
    View Code

        至此,新增告一段落,我们接下来看修改!

  • 相关阅读:
    Oracle 常用的V$ 视图脚本
    Oracle11g新特性
    深入浅出Oracle:Redo的作用
    oracle表空间操作详解
    Oracle Directory
    linux下手动删除数据库实例
    Oracle OS认证以及口令文件
    监控Oracle数据库的常用shell脚本
    Oracle 帐号基本管理
    Oracle小知识
  • 原文地址:https://www.cnblogs.com/jiangbei/p/7087127.html
Copyright © 2020-2023  润新知