项目三 员工后台管理系统

  1. CRUD :create retrieve update delete
  2. 功能点:
  • 分页
  • 数据校验 (jquery前端校验+JSR303后端校验)
  • ajax
  • Rest风格URI,使用http资源请求的动词 GET(查询) POST(新增) PUT(修改) DELETE(删除)
  1. 技术点:
  • 基础框架 ssm
  • 数据库 mysql
  • 前端框架 – bootstrap
  • 项目依赖管理 – Maven
  • 分页 – pagehelper
  • 逆向工程 – Mybatis Generator

基础环境搭建

1. 创建一个maven工程
2. 引入项目依赖的jar包
• spring
• springmvc
• mybatis
• 数据库连接池,驱动包
• 其他(jstl,servlet-api,junit)
3. 引入bootstrap前端框架

  • 在web工程下,创建static文件夹,引入bootstrap(前端样式)和js
    在这里插入图片描述
    在index.jsp中引入样式 在<head>标签中,将上述的地址写进去就可以了
<head>
    <title>$Title$</title>
<%--    引入js样式--%>
    <script type="text/javascript" src="static/js/jquery-3.1.1.js"></script>
<%--    引入bootstrap样式--%>
    <link href="static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
</head>

4. 编写ssm整合的关键配置文件
web.xml,spring,springmvc,mybatis,

  • 在web.xml中配置
<!--    1.启动spring-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

<!--    配置监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

<!--    2.配置springMVC的前端控制器-->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/l</url-pattern>
    </servlet-mapping>

<!--    3.字符编码过滤器-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

<!--    4.使用rest风格URI 将普通的post请求转换为指定的delete或者put请求-->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--  将请求体中的数据解析包装成map-->
    <filter>
        <filter-name>HttpPutFormContentFilter</filter-name>
        <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HttpPutFormContentFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  • 配置dispatcherServlet.xml 主要是springmvc
<!--    SpringMVC的配置文件,包含网站跳转逻辑的控制 use-default-filters="false"禁用默认过滤规则 -->
    <context:component-scan base-package="crud" use-default-filters="false">
<!--        只扫描控制器  -->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

<!--    配置视图解析器,方便页面返回-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

<!-- 两个标配  -->
<!--    将SpringMVC不能处理的请求交给Tomcat-->
    <mvc:default-servlet-handler/>
<!--    能支持SpringMVC更高级的一些功能,比如JSR303校验,快捷的ajax请求,映射动态请求-->
    <mvc:annotation-driven/>

在这里插入图片描述
配置applicationContext.xml文件

  1. spring配制文件,主要配置和业务逻辑有关的
  2. 配置mybatis整合
  3. 配置扫描器,将mybatis接口的实现加入到ioc容器中
  4. 事务控制
<!--    *******************************************************************************************************-->


<!--    spring配制文件,主要配置和业务逻辑有关的-->
    <conrtext:component-scan base-package="crud">
        <conrtext:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </conrtext:component-scan>
<!--    引入外部数据源-->
    <conrtext:property-placeholder location="classpath:dbconfig.properties"/>
    <bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>


<!--    *******************************************************************************************************-->


                                        <!--    配置mybatis整合-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--        引用数据源-->
        <property name="dataSource" ref="pooledDataSource"></property>
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
    </bean>


<!--    *******************************************************************************************************-->


    <!--    配置扫描器,将mybatis接口的实现加入到ioc容器中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--        扫描crud包下所有接口的实现-->
        <property name="basePackage" value="crud.dao"></property>
    </bean>


<!--    *******************************************************************************************************-->

                                        <!--    事务控制-->

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--        控制数据源-->
        <property name="dataSource" ref="pooledDataSource"></property>
    </bean>

<!--    开启基于注解的事务和xml配置形式-->
    <!--    开启基于注解的事务,使用xml配置形式的事务(必要主要的都是使用配置式)-->
    <aop:config>
        <!--        切入点表达式      -->
        <aop:pointcut id="txPoint" expression="execution(* crud.service..*(..))"/>
        <!--        配置事务增强 (通知器,告诉计算机切点和增强在哪)     -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
    </aop:config>

    <!--    配置事务增强,事务如何切入-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--            *代表所有方法都是事务方法-->
            <tx:method name="*"/>
            <!--            以get开始的所有方法-->
            <tx:method name="get*" read-only="true"/>
        </tx:attributes>
    </tx:advice>

使用mybatis的逆向工程生成对应的bean以及mapper

  1. 测试mapper

项目底层逻辑

bean.java

写入与数据库对应的 Employee 和 Department 表的相关数据

Department.java

public class Department {
    private Integer deptId;

    private String deptName;

    public Integer getDeptId() {
        return deptId;
    }

    public Department() {
    }

    public Department(Integer deptId, String deptName) {
        this.deptId = deptId;
        this.deptName = deptName;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName == null ? null : deptName.trim();
    }
}

Employee.java

public class Employee {

    private Integer empId;

    private String email;

    public Employee() {
    }

    public Employee(Integer empId, String empName, String gender, String email, Integer dId) {
        this.empId = empId;
        this.empName = empName;
        this.gender = gender;
        this.email = email;
        this.dId = dId;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "empId=" + empId +
                ", empName='" + empName + '\'' +
                ", gender='" + gender + '\'' +
                ", email='" + email + '\'' +
                ", dId=" + dId +
                ", department=" + department +
                '}';
    }

    private Integer dId;

//    希望查询员工的同时也查询部门信息
    private Department department;

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.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;
    }
}

dao层

dao层与数据库连接,分为 DepartmentMapper.java 和 EmployeeMapper.java

public interface DepartmentMapper {
    long countByExample(DepartmentExample example);

    int deleteByExample(DepartmentExample example);

    int deleteByPrimaryKey(Integer deptId);

    int insert(Department record);

    int insertSelective(Department record);

    List<Department> selectByExample(DepartmentExample example);

    Department selectByPrimaryKey(Integer deptId);

    int updateByExampleSelective(@Param("record") Department record, @Param("example") DepartmentExample example);

    int updateByExample(@Param("record") Department record, @Param("example") DepartmentExample example);

    int updateByPrimaryKeySelective(Department record);

    int updateByPrimaryKey(Department record);
}
public interface EmployeeMapper {


    Employee selectByPrimaryKeyWithDept(Integer empId);

    //    模糊查询
    List<Employee> selectByVague(String empName);

//======================================================================================

    long countByExample(EmployeeExample example);

    int deleteByExample(EmployeeExample example);

    int deleteByPrimaryKey(Integer empId);

    int insert(Employee record);

    int insertSelective(Employee record);

    List<Employee> selectByExample(EmployeeExample example);

    Employee selectByPrimaryKey(Integer empId);

//带部门的员工查询
    List<Employee> selectByExampleWithDept(EmployeeExample example);

    int updateByExampleSelective(@Param("record") Employee record, @Param("example") EmployeeExample example);

    int updateByExample(@Param("record") Employee record, @Param("example") EmployeeExample example);

    int updateByPrimaryKeySelective(Employee record);

    int updateByPrimaryKey(Employee record);


}

写DepartmentMapper.xml 和EmployeeMapper.xml(Mybatis层写逻辑),与数据库相连接

service层

注入dao层

@Service
public class DepartmentService {

    @Autowired
    private DepartmentMapper departmentMapper;

    public List<Department> getDepts() {
//        查询所有部门,不用加条件
        List<Department> list = departmentMapper.selectByExample(null);
        return list;
    }
}

@Service
public class EmployeeService {


    @Autowired
    EmployeeMapper employeeMapper;


    /**
     * 根据姓名或id搜索员工
     */
    public List<Employee> getEmpByVague(String empName){
        return employeeMapper.selectByVague(empName);
    }



    //    按照员工id查询员工,并且加上部门信息
    public Employee getEmpWithDept(Integer id) {
        Employee employee = employeeMapper.selectByPrimaryKeyWithDept(id);
        return employee;
    }

    /**
     * 查询所有员工
     * @return
     */
    public List<Employee> getAll(){
        return employeeMapper.selectByExampleWithDept(null);
    }

    /**
     * 员工保存方法
     * @param employee
     */
    public void saveEmp(Employee employee) {
        employeeMapper.insertSelective(employee);
    }

    /**
     * 检验用户名是否可用
     * @param empName
     * @return true代表姓名可用,false代表不可用
     */
    public boolean checkUser(String empName) {

        EmployeeExample example = new EmployeeExample();
        EmployeeExample.Criteria criteria = example.createCriteria();
        criteria.andEmpNameEqualTo(empName);
        long count = employeeMapper.countByExample(example);
//        如果count=0,返回true
        return count == 0;
    }

//    按照员工id查询员工
    public Employee getEmp(Integer id) {
        Employee employee = employeeMapper.selectByPrimaryKey(id);
        return employee;
    }

    /**
     * 员工更新
     * @param employee
     */
    public void updateEmp(Employee employee) {
        employeeMapper.updateByPrimaryKeySelective(employee);

    }


    /**
     * 员工删除
     * @param id
     */
    public void deleteEmp(Integer id) {
        employeeMapper.deleteByPrimaryKey(id);
    }

    /**
     * 批量删除
     * @param ids
     */
    public void deleteBatch(List<Integer> ids) {

        EmployeeExample example = new EmployeeExample();
        EmployeeExample.Criteria criteria = example.createCriteria();
//        delete from tbl_employee where emp_id in (1,2,...)
        criteria.andEmpIdIn(ids);
        employeeMapper.deleteByExample(example);
    }
}

查询

  1. 访问index.jsp页面
  2. index.jsp页面发送出查询员工列表请求
  3. EmployeeController来接受请求,查出员工数据
  4. 来到list.jsp页面进行展示

EmployeeService.java中注入dao,dao与mybatis映射文件相关联

@Autowired
EmployeeMapper employeeMapper;
/**
     * 查询所有员工
     */
public List<Employee> getAll(){
    return employeeMapper.selectByExampleWithDept(null);
}

EmployeeController.java中,注入service,用pageHelper进行分页处理

 @Autowired
    EmployeeService employeeService;

//    查询员工数据
    @RequestMapping("/emps")
    public String getEmps(@RequestParam(value = "pn",defaultValue = "1")Integer pn,Model model){
//        这不是一个分页查询,所以我们引入PageHelper插件
//        在查询之前,传入页码和分页中每页的大小
        PageHelper.startPage(pn,5);
        List<Employee> emps = employeeService.getAll();
//        使用pageInfo包装,只要将pageInfo交给页面就可以了,封装了详细的分页信息,包括我们查询的数据
//
        PageInfo page = new PageInfo(emps);
        model.addAttribute("pageInfo",page);
        return "list";
    }

跳转到 list.jsp页面

<html>
<head>
    <title>员工列表</title>

<%
    pageContext.setAttribute("APP_PATH", request.getContextPath());
%>

<%--   web路径:
            不以/开始的相对路径,找资源是以当前资源的路径为基准,经常容易出问题
            而以/开始的相对路径,是以服务器的路径为标注的(http://localhost:3306),需要加上项目名
                    http://localhost:3306/crud
   --%>
    <script src="${APP_PATH}/static/js/jquery-3.1.1.js"></script>
    <link href="${APP_PATH}/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="${APP_PATH}/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>


</head>
<body>
<%--搭建显示页面--%>
    <div class="container">
<%--    标题--%>
        <div class="row">
            <div class="col-md-12">
                <h1>SSM-CRUD</h1>
            </div>
        </div>

<%--    新增/删除 按钮--%>
        <div class="row">
            <div class="col-md-4 col-md-offset-8">
                <button class="btn btn-info">新增</button>
                <button class="btn btn-danger">删除</button>
            </div>
        </div>

<%--    显示表格数据--%>
        <div class="row">
            <div class="col-md-12">
                <table class="table table-hover">
                    <tr>
                        <th>#</th>
                        <th>empName</th>
                        <th>gender</th>
                        <th>email</th>
                        <th>deptName</th>
                        <th>操作</th>
                    </tr>

                    <c:forEach items="${pageInfo.list}" var="emp">
                        <tr>
                            <th>${emp.empId}</th>
                            <th>${emp.empName}</th>
                            <th>${emp.gender == "M" ? "男" : "女"}</th>
                            <th>${emp.email}</th>
                            <th>${emp.department.deptName}</th>
                            <th>
                                <button class="btn btn-info btn-sm">
                                    <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
                                    编辑
                                </button>
                                <button class="btn btn-danger btn-sm">
                                    <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
                                    删除
                                </button>
                            </th>
                        </tr>
                    </c:forEach>

                </table>
            </div>
        </div>

<%--    显示分页信息--%>
        <div class="row">
<%--            分页文字信息--%>
            <div class="col-md-6">
                当前第${pageInfo.getPageNum()}/${pageInfo.getPages()}页,共${pageInfo.getTotal()}条记录。
            </div>

<%--            分页条信息--%>
            <div class="col-md-6">

                <nav aria-label="Page navigation">
                    <ul class="pagination">
                        <li><a href="${APP_PATH}/emps?pn=1">首页</a></li>

<%--                        判断是否有上一页(是否是第一页),如果是,则不显示该标签,如果不是,点击可以跳转到上一页--%>
                        <c:if test="${pageInfo.hasPreviousPage}">
                            <li>
                                <a href="${APP_PATH}/emps?pn=${pageInfo.pageNum - 1}" aria-label="Previous">
                                    <span aria-hidden="true">&laquo;</span>
                                </a>
                            </li>
                        </c:if>

<%--                        循环遍历分页条--%>
                        <c:forEach items="${pageInfo.navigatepageNums}" var="page_num">
<%--                            判断页码是否等于当前页码,如果等于就让他高亮显示,并且点击无效--%>
                            <c:if test="${page_num == pageInfo.pageNum}">
                                <li class="active"><a href="#">${page_num}</a></li>
                            </c:if>
<%--                            如果不等于就正常显示,点击可以正常跳转--%>
                            <c:if test="${page_num != pageInfo.pageNum}">
<%--                               href="${APP_PATH}/emps?pn=${page_num}跳转到点击的页码 --%>
                                <li><a href="${APP_PATH}/emps?pn=${page_num}">${page_num}</a></li>
                            </c:if>
                        </c:forEach>

<%--                        判断是否有下一页(是否是最后一页),如果是,则不显示该标签,如果不是,点击可以跳转到下一页--%>
                        <c:if test="${pageInfo.hasNextPage}">
                            <li>
                                <a href="${APP_PATH}/emps?pn=${pageInfo.pageNum + 1}" aria-label="Next">
                                    <span aria-hidden="true">&raquo;</span>
                                </a>
                            </li>
                        </c:if>

                        <li><a href="${APP_PATH}/emps?pn=${pageInfo.pages}">尾页</a></li>
                    </ul>
                </nav>

            </div>
        </div>
    </div>

</body>
</html>

但是,我们上面写的只适用于浏览器服务器端模型(B/S),如果有安卓,ios客户端发送请求服务器怎么处理呢?采用ajax解决上述问题
0

  1. index.jsp页面直接发送ajax请求进行员工分页数据的查询
  2. 服务器将查出的数据,以json字符串的形式返回给浏览器
  3. 浏览器收到js字符串。可以使用js对json进行解析,使用js通过dom增删改改变页面。
  4. 返回json。实现客户端的无关性。

在EmployeeController.java中,将之前写的getEmps方法注释掉,用新的方法,这个方法返回json字符串,最后返回的不是list页面,而是

/**
     *  返回json数据
     * @ResponseBody要能正常工作,需要导入jackson包
*/
    @ResponseBody
    @RequestMapping("/emps")
    public Msg getEmpsWithJson(@RequestParam(value = "pn",defaultValue = "1") Integer pn){

//        引入pageHelper分页查询,
//        在查询之前只需要调用PageHelper.startPage(),传入页码,以及每一页显示的数量
        PageHelper.startPage(pn,10);
//        分页完之后的查询就是分页查询
        List<Employee> emps = employeeService.getAll();

//        分页查询完之后,可以使用pageInfo来包装查询后的结果,
//        只需要将pageInfo交给页面就行
//        pageInfo封装了详细的分页信息,包括我们查询出来的数据
//        比如总共有多少页,当前是第几页等。。。
//        想要连续显示5页,就加上参数5即可
        PageInfo pageInfo = new PageInfo(emps,5);
        return Msg.success().add("pageInfo", pageInfo);
    }

这里public Msg getEmpsWithJson 返回的是Msg类型的数据,我们事先定义好一个Msg类,里面用来接收返回的状态,这样后面做增删改就知道是否成功了,方便处理
在bean下创建 Msg.java

/**
 * 用来返回json的数据的通用类
 */
public class Msg {

//    状态码,100成功,200失败
    private int code;
//    提示信息
    private String msg;
//    用户要返回给浏览器的数据
    private Map<String, Object> extend = new HashMap<String, Object>();

//    返回成功方法
    public static Msg success(){
        Msg res = new Msg();
        res.setCode(100);
        res.setMsg("处理成功!");
        return res;
    }
//      返回失败方法
    public static Msg fail(){
        Msg res = new Msg();
        res.setCode(200);
        res.setMsg("处理失败!");
        return res;
    }

    public Msg add(String key, Object value){
        this.getExtend().put(key, value);
        return this;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Map<String, Object> getExtend() {
        return extend;
    }

    public void setExtend(Map<String, Object> extend) {
        this.extend = extend;
    }
}

上传json字符串给服务器端,通过ajax显示到前端页面

<script type="text/javascript">
<%--        1、页面加载完成以后,直接发送一个ajax请求,获取分页数据--%>

        <%-- 总记录数,用于跳转到最后一页。
        由于有了分页插件,当跳转页面大于总页面数的时候,就会跳转到最后一页 --%>
        var totalRecordCount;
        //当前页数,用于修改完员工信息之后跳转到本页面。
        var currentPage;


        $(function () {
            //去首页
            to_page(1);

        });

        //实现页面跳转,想跳到第几页就传参数
        function to_page(page) {
            //每次页面跳转时,都将全选/全不选设置为false
            $("#check_all").prop("checked", false);

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

        // 1、解析并显示员工数据
        function build_emps_table(res) {
            //清空table表格,如果不清空,当页面刷新的时候新的数据不会覆盖旧数据,造成页面混乱
            $("#emps_table tbody").empty();

            //获取所有员工数据
            var emps = res.extend.pageInfo.list;

            //遍历员工数据
            $.each(emps, function (index, item) {
                //在员工数据的最左边加上多选框
                var checkBoxTd = $("<td><input type='checkbox' class='check_item'/></td>");

                //把一个一个的id  name  gender取出来   放到表单里显示在前端页面上
                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);

                //编辑按钮
                var editBtn = $("<button></button>").addClass("btn btn-info btn-sm edit_btn")
                    .append($("<span></span>").addClass("glyphicon glyphicon-pencil").append("编辑"));
                //为编辑按钮添加一个自定义的属性,来表示当前员工id
                editBtn.attr("edit-id", item.empId);

                //删除按钮
                var delBtn = $("<button></button>").addClass("btn btn-danger btn-sm delete_btn")
                    .append($("<span></span>").addClass("glyphicon glyphicon-trash").append("删除"));
                //为删除按钮添加一个自定义的属性,来表示当前员工id
                delBtn.attr("del-id", item.empId);

                //把两个按钮放到一个单元格中,并且按钮之间留点空隙
                var btnTd = $("<td></td>").append(editBtn).append(" ").append(delBtn);

                //append方法执行完成以后还是会返回原来的元素,所以可以一直.append添加元素,
                //将上面的td(姓名邮箱性别等)添加到同一个tr(方便展示)里
                $("<tr></tr>").append(checkBoxTd)
                    .append(empIdTd)
                    .append(empNameTd)
                    .append(genderTd)
                    .append(emailTd)
                    .append(deptNameTd)
                    .append(btnTd)
                    .appendTo("#emps_table tbody");
                //将tr添加到tbody标签中
            });

        }

        // 2、解析并显示分页条
        function build_page_nav(res) {
            //清空分页条,如果不清空,当页面刷新的时候新的数据不会覆盖旧数据,造成页面混乱
            $("#page_nav_area").empty();

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



            //构建首页和上一页的标签
            var firstPageLi = $("<li></li>").append($("<a></a>").append("首页").attr("href","#"));
            var prePageLi = $("<li></li>").append($("<a></a>").append("&laquo;"));
            //如果没有上一页,就设置首页和上一页的按钮不可用
            if(res.extend.pageInfo.hasPreviousPage == false){
                firstPageLi.addClass("disabled");
                prePageLi.addClass("disabled");
            }else{
                //如果有上一页,才绑定单击事件
                //为首页标签添加单击事件
                firstPageLi.click(function () {
                    to_page(1);
                });
                //为上一页标签添加单击事件
                prePageLi.click(function () {
                    to_page(res.extend.pageInfo.pageNum - 1);
                });
            }


            //下一页和尾页
            var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
            var lastPageLi = $("<li></li>").append($("<a></a>").append("尾页").attr("href","#"));
            //如果没有下一页,就设置下一页和尾页按钮不可用
            if(res.extend.pageInfo.hasNextPage == false){
                nextPageLi.addClass("disabled");
                lastPageLi.addClass("disabled");
            }else{
                //如果有下一页,才绑定单击事件
                //为下一页标签添加单击事件
                nextPageLi.click(function () {
                    to_page(res.extend.pageInfo.pageNum + 1);
                });
                //为尾页标签添加单击事件
                lastPageLi.click(function () {
                    to_page(res.extend.pageInfo.pages);
                });
            }


            //添加首页和前一页到ul标签中
            ul.append(firstPageLi).append(prePageLi);

            //遍历,给ul中添加页码  index:索引, item:当前元素
            $.each(res.extend.pageInfo.navigatepageNums, function (index, item) {

                var numLi = $("<li></li>").append($("<a></a>").append(item));

                //绑定单击事件,点击页码进行跳转
                numLi.click(function () {
                    to_page(item);
                })

                //当前页数高亮显示
                if(res.extend.pageInfo.pageNum == item){
                    numLi.addClass("active");
                }

                ul.append(numLi);
            })

            //添加下一页和尾页到ul标签中
            ul.append(nextPageLi).append(lastPageLi);

            //把ul添加到nav标签中
            var navEle = $("<nav></nav>").append(ul).appendTo("#page_nav_area");

        }

        // 3、解析并显示分页文字信息
        function build_page_info(res) {
            //清空分页文字信息,如果不清空,当页面刷新的时候新的数据不会覆盖旧数据,造成页面混乱
            $("#page_info_area").empty();

            $("#page_info_area").append("当前第" + res.extend.pageInfo.pageNum + "/" +
                                                    res.extend.pageInfo.pages + "页,共" +
                                                    res.extend.pageInfo.total +"条记录。");

            // 赋值总记录数,方便后面调用
            totalRecordCount = res.extend.pageInfo.total;
            //赋值当前页数,方便后面调用
            currentPage = res.extend.pageInfo.pageNum;
        }
</script>

新增员工

  1. 在index.jsp页面点击”新增”
  2. 弹出新增对话框
  3. 去数据库查询部门列表,显示在对话框中
  4. 用户输入数据,并进行校验
    jquery前端校验,ajax用户名重复校验,重要数据(后端校验(JSR303),唯一约束);
  5. 完成保存
    在这里插入图片描述
    在这里插入图片描述
<%-- 搭建显示页面 --%>
    <div class="container">
        <%-- 标题 --%>
        <div class="row">
            <div class="col-md-12">
                <h1>SSM-CRUD</h1>
            </div>
        </div>
        <div class="row">
            <%-- 新增/删除 按钮 --%>
            <div class="col-md-4 col-md-offset-4">
                <button class="btn btn-info" id="emp_add_modal_btn">新增</button>
                <button class="btn btn-danger" id="emp_delete_batch_btn">删除</button>
            </div>
        </div>

点击新增按钮,为按钮添加单击事件

//点击新增按钮,弹出模态框(通过js方式调用)
        $("#emp_add_modal_btn").click(function () {
            //清除表单数据(表单重置,包括表单数据以及表单样式),防止出现点击保存之后再次点击新增,跳出的模态框还是保存上次添加的记录,避免重复添加。
            //取出dom对象,调用reset()方法
            // $("#empAddModal form")[0].reset();
            reset_form("#empAddModal form");

            //发送ajax请求,在弹出模态框之前查询部门信息,显示在下拉列表中
            getDepts("#empAddModal select");

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

创建员工添加模态框

<%------------------------------ 员工添加的模态框 ------------------------------%>
    <div class="modal fade" id="empAddModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                    <h4 class="modal-title" id="myModalLabel">新增员工</h4>
                </div>
                <div class="modal-body">

                    <%------------------------------ 表单 ------------------------------%>
                    <form class="form-horizontal">
                        <%-- empName --%>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">empName</label>
                            <div class="col-sm-10">
<%--        name="empName"        name="email"  与javaBean中一样  spring帮我们自动封装                --%>
                                <input type="text" name="empName" class="form-control" id="empName_add_input" placeholder="empName">
                                <span class="help-block"></span>
                            </div>
                        </div>
                        <%-- email --%>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">email</label>
                            <div class="col-sm-10">
                                <input type="text" name="email" class="form-control" id="email_add_input" placeholder="email@gmail.com">
                                <span class="help-block"></span>
                            </div>
                        </div>
                        <%-- gender --%>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">gender</label>
                            <div class="col-sm-10">
                                <%-- 内联单选 --%>
                                <label class="radio-inline">
                                    <input type="radio" name="gender" id="gender1_add_input" value="M" checked="checked"></label>
                                <label class="radio-inline">
                                    <input type="radio" name="gender" id="gender2_add_input" value="F"></label>
                            </div>
                        </div>
                        <%-- department --%>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">deptName</label>
                            <div class="col-sm-4">
                                <%-- 下拉列表,部门选项只要提交部门id即可 --%>
                                <select class="form-control" name="dId" id="dept_select"></select>
                            </div>
                        </div>
                    </form>
                    <%----------------------------------------------------------------%>

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

添加department时,部门有多个,需要从后台服务器中获取,

//查出所有部门信息并显示在下拉列表中
        function getDepts(ele) {
            //清空下拉菜单信息,如果不清空,当页面刷新的时候新的数据不会覆盖旧数据,造成页面混乱
            $(ele).empty();

            $.ajax({
                url:"${APP_PATH}/depts",
                type:"GET",
                success:function (res) {
                    // 点击添加后,最终返回的json字符串是这样的
                    // {"code":100,"msg":"处理成功!",
                    //     "extend":{"depts":[{"deptId":1,"deptName":"开发部"},{"deptId":2,"deptName":"测试部"}]}}

                    //遍历部门信息,在下拉列表中显示部门信息
                    $.each(res.extend.depts, function () {
                        //在遍历之前
                        var optionEle = $("<option></option>").append(this.deptName).attr("value", this.deptId);

                        //将option标签添加到empAddModal下的select标签中
                        //传入ele参数,调用时只需把对应id作为参数即可
                        optionEle.appendTo(ele);

                        //将option标签添加到empUpdateModal下的select标签中,用于编辑的模态框
                        // optionEle.appendTo("#empUpdateModal select");
                    });
                }
            });
        }

完成之后,点击保存按钮,id="emp_save_btn",为他添加单击事件(要校验姓名和邮箱)

$("#emp_save_btn").click(function () {
        //1、模态框中填写的表单数据提交给服务器进行保存
        //2、先对要提交给服务器的数据进行校验,并且判断之前的ajax用户名校验是否成功
        //    只要有一个校验失败,就无法保存
            if($(this).attr("ajax-value") == "error"){
                return false;
            }

            if(!validate_add_form() || !emailStatus){
                return false;
            }


        //3、校验之后,再发送ajax请求保存员工
        //     alert($("#empAddModal form").serialize());
            $.ajax({
                url:"${APP_PATH}/emp",
                type:"POST",
                data:$("#empAddModal form").serialize(),
                success:function (res) {
                    // alert(res.msg);

                    //判断状态码,如果是100(成功),才关闭模态框并进行跳转
                    if(res.code == 100){
                        // 员工保存陈宫之后,
                        //  1、关闭模态框
                        $('#empAddModal').modal('hide');

                        //  2、跳转到最后一页,显示刚才保存的数据
                        //   由于有了分页插件,当跳转的页面大于总页面数的时候,就会跳转到最后一页
                        to_page(totalRecordCount);
                    }else {
                        //显示失败信息
                        // console.log(res);
                        //有哪个字段的错误信息就显示哪个字段的

                        //如果邮箱有误
                        if (res.extend.errorField.email != undefined){
                        //    显示邮箱错误信息
                            show_validate_msg("#email_add_input", "error", res.extend.errorField.email);
                        }
                        //如果用户名有误
                        if(res.extend.errorField.empName != undefined){
                            //显示用户名错误信息
                            show_validate_msg("#empName_add_input", "error", res.extend.errorField.empName);
                        }

                    }
                }
            });
        });

发送ajax请求,请求emp地址,在controller层

/**
     * 如果uri为 /emp/{id} ,请求方式为GET,就查询员工
     * 如果uri为 /emp ,     请求方式为POST,就保存员工
     * 如果uri为 /emp/{id} ,请求方式为PUT,就修改员工
     * 如果uri为 /emp/{id} ,请求方式为DELETE,就删除员工
     */
    /**
     * 保存员工
     * 要支持JSR303,需要导入Hibernate-Validator包
     *
     * @Valid :封装对象之后,对数据进行校验
     * BindingResult :封装校验的结果
     * @return
*/
    @ResponseBody
    @RequestMapping(value = "/emp", method = RequestMethod.POST)
    public Msg saveEmp(@Valid Employee employee, BindingResult result){
        if(result.hasErrors()){
//            校验失败,在模态框中显示校验失败的错误信息

            Map<String, Object> map = new HashMap<>();
            List<FieldError> errors = result.getFieldErrors();
            for(FieldError fieldError : errors){
                System.out.println("错误的字段名:" + fieldError.getField());
                System.out.println("错误信息:" + fieldError.getDefaultMessage());
                map.put(fieldError.getField(), fieldError.getDefaultMessage());
            }
//            把错误信息返回给浏览器
            return Msg.fail().add("errorField", map);
        }else{
//            校验成功
            employeeService.saveEmp(employee);
            return Msg.success();
        }

    }

在提交之前,添加校验方法

        //校验方法,判断用户名是否重复或者不可用
        function validate_add_form(){

            // $("#empName_add_input").parent().removeClass("has-success has-error");
            // $("#empName_add_input").next("span").text("");
            // $("#email_add_input").parent().removeClass("has-success has-error");
            // $("#email_add_input").next("span").text("");

            // 拿到要校验的数据,使用正则表达式
            var empName = $("#empName_add_input").val();
            //允许数字字母以及_-,6-16位或者中文2-5位
            var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/;
            //1、校验用户名
            if(!regName.test(empName)){
                //失败
                // alert("用户名必须是6-16位数字,字母或者_-,也可以是2-5位中文组成");
                //添加错误样式到输入框
                // $("#empName_add_input").parent().addClass("has-error");
                //给empName_add_input所在标签的下一个span标签加上文本
                // $("#empName_add_input").next("span").text("用户名必须是6-16位数字,字母或者_-,也可以是2-5位中文组成");

                show_validate_msg("#empName_add_input", "error", "用户名必须是6-16位数字,字母或者_-,也可以是2-5位中文组成");
                return false;
            }else{
                //成功
                // $("#empName_add_input").parent().addClass("has-success");
                // $("#empName_add_input").next("span").text("");
                // console.log("1");

                show_validate_msg("#empName_add_input", "success", "");
            }

            //2、校验邮箱
            var email = $("#email_add_input").val();
            var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
            if(!regEmail.test(email)){
                // alert("邮箱格式不正确!");
                // $("#email_add_input").parent().addClass("has-error");
                // $("#email_add_input").next("span").text("邮箱格式不正确!");

                show_validate_msg("#email_add_input", "error", "邮箱格式不正确!");
                return false;
            }else{
                // $("#email_add_input").parent().addClass("has-success");
                // $("#email_add_input").next("span").text("");

                show_validate_msg("#email_add_input", "success", "");
            }

            return true;
        }

验证邮箱是否可用

//设置email的校验状态
        var emailStatus;

        //校验邮箱是否可用
        $("#email_add_input").change(function () {
            if(!validate_add_form()){
                show_validate_msg("#email_add_input", "error", "邮箱格式错误");
                emailStatus = false;
            }else{
                show_validate_msg("#email_add_input", "success","");
                emailStatus = true;
            }
        })

验证用户名

//校验用户名是否可用
        $("#empName_add_input").change(function () {
        //    发送ajax请求校验用户名是否可用
        //  输入框中的值
            var empName = this.value;

            $.ajax({
                url:"${APP_PATH}/checkuser",
                data:"empName=" + empName,
                type:"POST",
                success:function (res) {
                    if(res.code == 100){
                    //成功
                        show_validate_msg("#empName_add_input", "success", "用户名可用");
                    //    如果用户名可用,将success标志保存到ajax-value属性中
                        $("#emp_save_btn").attr("ajax-value", "success");
                    }else{
                    //失败
                        show_validate_msg("#empName_add_input", "error", res.extend.va_msg);
                    //    如果用户名不可用,将error标志保存到ajax-value属性中
                        $("#emp_save_btn").attr("ajax-value", "error");
                    }
                }
            })
        })

在controller中写函数

/**
     * 检查用户名是否可用
     * @param empName
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/checkuser")
    public Msg checkuser(@RequestParam("empName") String empName){
//        先判断用户名是否是合法的表达式,再判断是否重复
        String regx = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})";
        if(!empName.matches(regx)){
            return Msg.fail().add("va_msg", "用户名必须是6-16位数字,字母或者_-,也可以是2-5位中文组成");
        }else{
//            数据库用户名重复校验
            boolean b = employeeService.checkUser(empName);
            if(b){
                return Msg.success();
            }else{
                return Msg.fail().add("va_msg", "用户名已存在");
            }
        }

    }

后端校验姓名和邮箱
在bean类(Employee.java)中在姓名属性和邮箱属性上添加注解

public class Employee {
    
//    姓名   自定义校验规则
    @Pattern(regexp = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})",
            message = "(后端Employee)用户名必须是6-16位数字,字母或者_-,也可以是2-5位中文组成")
    private String empName;

//    Email   自定义校验规则
    @Pattern(regexp = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$",
            message = "(后端Employee)邮箱格式不正确!")
    private String email;

    private String gender;
    
    private Integer empId;
  }

在congtroller中 ,校验员工信息方法上添加注解即可

/**
     * 如果uri为 /emp/{id} ,请求方式为GET,就查询员工
     * 如果uri为 /emp ,     请求方式为POST,就保存员工
     * 如果uri为 /emp/{id} ,请求方式为PUT,就修改员工
     * 如果uri为 /emp/{id} ,请求方式为DELETE,就删除员工
     */
    /**
     * 保存员工
     * 要支持JSR303,需要导入Hibernate-Validator包
     *
     * @Valid :封装对象之后,对数据进行校验
     * BindingResult :封装校验的结果
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/emp", method = RequestMethod.POST)
    public Msg saveEmp(@Valid Employee employee, BindingResult result){
        if(result.hasErrors()){
//            校验失败,在模态框中显示校验失败的错误信息

            Map<String, Object> map = new HashMap<>();
//            提取每个字段的错误信息,遍历
            List<FieldError> errors = result.getFieldErrors();
            for(FieldError fieldError : errors){
                System.out.println("错误的字段名:" + fieldError.getField());
                System.out.println("错误信息:" + fieldError.getDefaultMessage());
                map.put(fieldError.getField(), fieldError.getDefaultMessage());
            }
//            把错误信息返回给浏览器
            return Msg.fail().add("errorField", map);
        }else{
//            校验成功
            employeeService.saveEmp(employee);
            return Msg.success();
        }

    }

员工修改

  1. 点击编辑
  2. 弹出用户修改的模态框(显示用户信息)
  3. 点击更新,完成用户修改

在这里插入图片描述后端代码
首先 根据员工的id来找其他的信息

service创建getEmp方法,传入员工的id

//    按照员工id查询员工
    public Employee getEmp(Integer id) {
        Employee employee = employeeMapper.selectByPrimaryKey(id);
        return employee;
    }

// <%------------------------------------------------------------------%>
    @ResponseBody
    @RequestMapping(value = "/emp/{empId}", method = RequestMethod.PUT)
    public Msg updateEmp(Employee employee, HttpServletRequest request){
        System.out.println("将要更新的员工数据:" + employee);
        employeeService.updateEmp(employee);
        return Msg.success();
    }

controller层

/**
     * 如果uri为 /emp/{id} ,请求方式为GET,就查询员工
     * 如果uri为 /emp ,     请求方式为POST,就保存员工
     * 如果uri为 /emp/{id} ,请求方式为PUT,就修改员工
     * 如果uri为 /emp/{id} ,请求方式为DELETE,就删除员工
     */
/**
     * 根据id查询员工
     * @param id
     * @return
     */
//    @PathVariable 从路径中取出id
    @RequestMapping(value = "/emp/{id}", method = RequestMethod.GET)
    @ResponseBody
    public Msg getEmp(@PathVariable("id") Integer id){
        Employee employee = employeeService.getEmp(id);
        return Msg.success().add("emp", employee);
    }
// <%------------------------------------------------------------------%>

 @ResponseBody
    @RequestMapping(value = "/emp/{empId}", method = RequestMethod.PUT)
    public Msg updateEmp(Employee employee, HttpServletRequest request){
        System.out.println("将要更新的员工数据:" + employee);
        employeeService.updateEmp(employee);
        return Msg.success();
    }

前端代码
页面展示,点击按钮后弹出修改模态框

<%------------------------------ 员工修改的模态框 -----------------------------%>
    <div class="modal fade" id="empUpdateModal" 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">员工修改</h4>
                </div>
                <div class="modal-body">

                    <%------------------------------ 表单 ------------------------------%>
                    <form class="form-horizontal">
                        <%-- empName --%>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">empName</label>
                            <div class="col-sm-10">
                                <p class="form-control-static" id="empName_update_static"></p>
                            </div>
                        </div>
                        <%-- email --%>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">email</label>
                            <div class="col-sm-10">
                                <input type="text" name="email" class="form-control" id="email_update_input" placeholder="email@gmail.com">
                                <span class="help-block"></span>
                            </div>
                        </div>
                        <%-- gender --%>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">gender</label>
                            <div class="col-sm-10">
                                <%-- 内联单选 --%>
                                <label class="radio-inline">
                                    <input type="radio" name="gender" id="gender1_update_input" value="M" checked="checked"></label>
                                <label class="radio-inline">
                                    <input type="radio" name="gender" id="gender2_update_input" value="F"></label>
                            </div>
                        </div>
                        <%-- department --%>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">deptName</label>
                            <div class="col-sm-4">
                                <%-- 下拉列表,部门选项只要提交部门id即可 --%>
                                <select class="form-control" name="dId" id="dept_select"></select>
                            </div>
                        </div>
                    </form>
                    <%------------------------------------------------------------------%>

                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                    <button type="button" class="btn btn-primary" id="emp_update_btn">更新</button>
                </div>
            </div>
        </div>
    </div>
    <%----------------------------------------------------------------------------------------%>

empUpdateModal绑定单击事件绑定单击事件

 //为每个员工的编辑按钮绑定单击事件
        //但是,这里的单击事件是在编辑按钮被创建出来之前就已经开始绑定了,所以这里无法绑定单击事件
        //有两种办法
        //     1)可以在创建按钮的时候就给他绑定单击事件
        //     2)绑定单击.live(),而新版jQuery没有live方法,而是用on进行替代
        $(document).on("click", ".edit_btn", function () {

            //1、通过edit-id属性查出员工信息,显示员工信息
            getEmp($(this).attr("edit-id"));

            //2、查出部门信息,并显示部门列表
            getDepts("#empUpdateModal select");


            //把员工的id传递给模态框的更新按钮,方便点击修改后获取员工id
            $("#emp_update_btn").attr("edit-id", $(this).attr("edit-id"));
            //弹出模态框,
            $("#empUpdateModal").modal({
                backdrop:"static"
            });
        })

        //员工姓名回显
        function getEmp(id) {
            $.ajax({
                url:"${APP_PATH}/emp/" + id,
                type:"GET",
                success:function (res) {
                    // console.log(res);
                    //获取员工数据
                    var empData = res.extend.emp;
                    //添加到标签文本中
                    $("#empName_update_static").text(empData.empName);
                    //显示邮箱
                    $("#email_update_input").val(empData.email);
                    //选中性别单选框
                    $("#empUpdateModal input[name = gender]").val([empData.gender]);
                    //选中部门
                    $("#empUpdateModal select").val([empData.dId]);

                }
            });
        }


        //修改员工时,校验邮箱是否可用
        $("#email_update_input").change(function () {
            validate_update_email();
        })

        function validate_update_email(){
            var email = $("#email_update_input").val();
            var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
            if(!regEmail.test(email)){
                show_validate_msg("#email_update_input", "error", "邮箱格式不正确!");
                return false;
            }else{
                show_validate_msg("#email_update_input", "success", "");
            }
            return true;
        }

    //    点击更新,更新员工信息
        $("#emp_update_btn").click(function () {

            //验证邮箱是否合法
            var email = $("#email_update_input").val();
            var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
            if(!regEmail.test(email)){
                show_validate_msg("#email_update_input", "error", "邮箱格式不正确!");
                return false;
            }else{
                show_validate_msg("#email_update_input", "success", "");
            }

            //发送ajax请求保存更新的员工数据
            $.ajax({
                //加上之前在修改按钮上保存的edit-id的值
                url:"${APP_PATH}/emp/" + $(this).attr("edit-id"),
                type:"PUT",
                data:$("#empUpdateModal form").serialize(),// + "&_method=PUT",
                success:function (res) {
                    // alert(res.msg);
                    //关闭对话框
                    $('#empUpdateModal').modal('hide');

                    //回到本页面
                    to_page(currentPage);

                }
            })
        })

删除

/**
     * 按照员工id删除
     * 单个删除和批量删除二合一
     * 如果是批量删除,每个id之间用-分隔开
     */
    @ResponseBody
    @RequestMapping(value = "/emp/{ids}", method = RequestMethod.DELETE)
    public Msg deleteEmpById(@PathVariable("ids") String ids){
//        如果包含-就是批量删除
        if(ids.contains("-")){
//            批量删除

            List<Integer> del_ids = new ArrayList<>();
//            按照-分隔开,转化为String数组
            String[] str_ids = ids.split("-");

//            组装id的集合
            for(String s : str_ids){
                del_ids.add(Integer.parseInt(s));
            }
            employeeService.deleteBatch(del_ids);
        }else{
//            单个删除
            Integer id = Integer.parseInt(ids);
            employeeService.deleteEmp(id);
        }
        return Msg.success();
    }

service层中包含两个方法

 /**
     * 员工删除
     * @param id
     */
    public void deleteEmp(Integer id) {
        employeeMapper.deleteByPrimaryKey(id);
    }

    /**
     * 批量删除
     * @param ids
     */
    public void deleteBatch(List<Integer> ids) {

        EmployeeExample example = new EmployeeExample();
        EmployeeExample.Criteria criteria = example.createCriteria();
//        delete from tbl_employee where emp_id in (1,2,...)
        criteria.andEmpIdIn(ids);
        employeeMapper.deleteByExample(example);
    }
}

前端

//单个删除
        $(document).on("click", ".delete_btn", function () {
        //    弹出是否删除确认框,并显示员工姓名
        //    取出员工姓名:找tr标签下的第三个td标签,对应的就是员工名字
            var empName = $(this).parents("tr").find("td:eq(2)").text();

            //拿到当前员工的id
            var empId = $(this).attr("del-id");

            //弹出确认框,点击确认就删除
            if(confirm("确认删除 [" + empName + "] 吗?")){
            //    确认,发送ajax请求删除
                $.ajax({
                    url:"${APP_PATH}/emp/" + empId,
                    type:"DELETE",
                    success:function (res) {
                        alert(res.msg);

                        //回到本页
                        to_page(currentPage);
                    }
                })
            }
        });


    //    完成全选/全不选功能
        $("#check_all").click(function () {
        //   attr获取checked是undefined,因为我们没有定义checked属性,attr获取的是自定义属性值
        //    而我们这些dom原生的属性,可以用prop来获取这些值
        //     alert($(this).prop("checked"));
        //    让所有复选框状态同步
            $(".check_item").prop("checked", $(this).prop("checked"));
        });

    //    当本页面所有复选框都选上时,自动将全选复选框选上
        $(document).on("click", ".check_item", function () {
            //判断当前选择中的元素是否是当前页面所有check_item的个数
            var flag = $(".check_item:checked").length == $(".check_item").length;

            $("#check_all").prop("checked", flag);
        })


    //    为批量删除绑定单击事件
        $("#emp_delete_batch_btn").click(function () {

            var empNames = "";
            var del_idstr = "";

            //遍历每一个被选中的复选框
            $.each($(".check_item:checked"), function () {
                // 获取要删除的员工姓名
                empNames += $(this).parents("tr").find("td:eq(2)").text() + "\n";

                //获取要删除的员工的id
                del_idstr += $(this).parents("tr").find("td:eq(1)").text() + "-";
            });

            //去除多余的-
            del_idstr = del_idstr.substring(0, del_idstr.length - 1);

            if(confirm("确认删除 \n" + empNames + " 吗?")){
                $.ajax({
                    url:"${APP_PATH}/emp/" + del_idstr,
                    type:"DELETE",
                    success:function (res) {
                        alert(res.msg);
                        to_page(currentPage);
                    }
                })
            }

        });
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值