尚硅谷ssm整合实战项目笔记

文章目录

  • 前言
  • 一、SSM整合
    • 1、项目介绍
    • 2、功能点
    • 3、技术点
  • 二、基础环境搭建
    • 1、创建maven工程
    • 2、引入依赖jar包
    • 3、引入BootStrap
    • 4、SSM整合配置
      • 4.1、配置web.xml
      • 4.2、springMVC配置
      • 4.3、配置spring
    • 5、编写mybatis核心文件
    • 6、创建数据库
    • 7、mybatis逆向工程
    • 8、修改mapper映射文件
    • 9、测试dao接口方法
  • 三、查询功能实现
    • 1、编写 index.jsp 页面:
    • 2、编写list.jsp页面
    • 3、编写EmployeeService类
    • 4、引入PageHelper分页插件
    • 5、编写EmployeeController类
    • 6、虚拟MVC测试
    • 7、完善list.jsp页面
  • 四、改写查询功能
    • 1、创建Msg类
    • 2、改写处理器方法
    • 3、修改 index.jsp
  • 五、编写添加功能
    • 1、编写查询所有部门的业务逻辑
      • 1.1、编写DepartmentService
      • 1.2、编写DepartmentController
    • 2、编写保存员工代码
      • 2.1、编写Service层方法
      • 2.2、编写controller层方法
    • 3、设置分页助手
    • 4、前端校验
      • 4.1、检查邮箱是否已存在
    • 5、后端校验
      • 5.1、导入相关jar包
      • 5.2、修改Employee类
      • 5.3、修改添加员工控制**器**
      • 5.4、修改保存按钮事件函数
      • 5.5、完整jsp页面
  • 六、修改员工信息功能
    • 1、编写修改模态框
    • 2、添加按钮样式
    • 3、修改重置表单函数
    • 4、编辑按钮事件
    • 5、回显用户数据
      • 5.1、编写控制器方法
      • 5.2、编写Service层方法
      • 5.3、网页查询员工信息函数
      • 5.4、为修改员工按钮添加属性
      • 5.5、回显员工信息函数
      • 5.6、完善修改按钮事件
    • 6、更新按钮事件
      • 6.1、控制器方法
      • 6.2、Service层方法
      • 6.3、修改编辑按钮事件
      • 6.4、使用PUT发送请求
  • 七、删除员工
    • 1、控制器方法
    • 2、Srevice方法
    • 3. 添加选择按钮
    • 4、绑定选择按钮事件
    • 4、删除单个员工按钮事件
    • 5、删除全部员工按钮事件
  • 九、最终index页面

前言

该笔记为尚硅谷SSM实战演练丨ssm整合快速开发CRUD学习笔记

github项目地址:https://github.com/xjhqre/sgg-ssm-demo

一、SSM整合

1、项目介绍

使用SSM框架搭建出一套简单的CRUD项目示例,包括分页查询、Ajax请求、数据校验等。

尚硅谷ssm整合实战项目笔记_第1张图片

尚硅谷ssm整合实战项目笔记_第2张图片

2、功能点

  1. 分页查询
  2. 数据校验:JQuery前端校验+JSR-303后端校验
  3. Ajax请求
  4. REST风格的URI:GET查询、POST新增、DELETE删除、PUT修改

3、技术点

  • 基础框架-SSM(Spring+SpringMVC+Mybatis)
  • 数据库-MySQL
  • 前端框架-Bootstrap
  • 依赖管理-Maven
  • 分页查询-PageHelper
  • 逆向工程-Mybatis Generator

二、基础环境搭建

相关配置文件的创建请见SSM整合配置模板,这里主要写下不同的地方。

1、创建maven工程

步骤:

  1. 创建maven工程快速开始
  2. 修改pom.xml文件,打包方式为war
  3. 创建resources目录
  4. 删除不必要的类和目录
  5. 创建web.xml文件

尚硅谷ssm整合实战项目笔记_第3张图片

2、引入依赖jar包

SpringMVC、Spring:

  • spring-webmvc

Spring-Jdbc:

  • spring-jdbc

Spring面向切面编程:

  • spring-aspects

Mybatis:

  • mybatis

mybatis整合Spring:

  • mybatis-spring

数据库连接池:

  • c3p0(不要用druid)

MySQL驱动:

  • mysql-connector-java

其他(jstl,servlet-api,junit):

  • jstl
  • servlet-api 加上 provided
  • junit

注意spring包的版本都要相同

pom.xml文件:



<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>org.examplegroupId>
    <artifactId>ssm-demoartifactId>
    <version>1.0-SNAPSHOTversion>
    <packaging>warpackaging>

    <dependencies>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-webmvcartifactId>
            <version>5.3.14version>
        dependency>

        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>5.3.14version>
        dependency>

        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-aspectsartifactId>
            <version>5.3.14version>
        dependency>

        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.5.7version>
        dependency>

        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatis-springartifactId>
            <version>2.0.6version>
        dependency>

        <dependency>
            <groupId>com.mchangegroupId>
            <artifactId>c3p0artifactId>
            <version>0.9.5.2version>
        dependency>

        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>8.0.17version>
        dependency>

        
        <dependency>
            <groupId>jstlgroupId>
            <artifactId>jstlartifactId>
            <version>1.2version>
        dependency>

        
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
            <version>3.1.0version>
            <scope>providedscope>
        dependency>

        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.11version>
            <scope>testscope>
        dependency>
    
    dependencies>

project>

3、引入BootStrap

步骤:

  1. 在webapp文件夹下创建static目录存放bootstrap文件和jQuery文件
  2. 创建index.jsp页面,引入jquery和bootstrap

index.jsp代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title

    <%--引入jQuery--%>
    
    <%--引入样式--%>
    
    





4、SSM整合配置

4.1、配置web.xml

步骤:

  1. 启动Spring容器,设置 contextConfigLocationContextLoaderListenercontextConfigLocation设置spring配置文件的位置,在resources目录下创建applicationContext.xml文件
  2. 配置springMVC前端控制器dispatchServlet,拦截所有请求,需要指定springMVC配置文件的位置,若不指定,则需要在同级目录下(webapp目录下)创建一个 servlet-name + -servlet的一个xml文件。让dispatchServlet拦截所有请求:/
  3. 配置字符编码过滤器 CharacterEncodingFilter,初始化参数 encoding、forceRequestEncoding、forceResponseEncoding,设置过滤所有请求 /*,一定要放在所有过滤器之前
  4. 使用Rest风格的URI,配置 HiddenHttpMethodFilter,将指定的 post 转化为 delete 或者是 put 请求。过滤所有请求/*

尚硅谷ssm整合实战项目笔记_第4张图片

wen.xml代码:


<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    
    
    <context-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath:applicationContext.xmlparam-value>
    context-param>

    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
    listener>

    
    
    <servlet>
        <servlet-name>dispatcherServletservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <load-on-startup>1load-on-startup>
    servlet>

    
    <servlet-mapping>
        <servlet-name>dispatcherServletservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>

    
    <filter>
        <filter-name>CharacterEncodingFilterfilter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
        <init-param>
            <param-name>encodingparam-name>
            <param-value>utf-8param-value>
        init-param>
        <init-param>
            <param-name>forceRequestEncodingparam-name>
            <param-value>trueparam-value>
        init-param>
        <init-param>
            <param-name>forceResponseEncodingparam-name>
            <param-value>trueparam-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

    
    <filter>
        <filter-name>HiddenHttpMethodFilterfilter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>
web-app>

4.2、springMVC配置

步骤:

  1. 配置扫描控制器
  2. 配置视图解析器
  3. 启动Servlet默认处理器,处理springMVC不能处理的请求
  4. 开启MVC注解驱动

尚硅谷ssm整合实战项目笔记_第5张图片

dispatcherServlet-servlet.xml:


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    
    <context:component-scan base-package="com.xjhqre.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 name="suffix" value=".jsp"/>
    bean>

    
    
    <mvc:default-servlet-handler/>
    
    <mvc:annotation-driven/>

beans>

4.3、配置spring

步骤:

  1. 配置数据源,创建db.properties文件
  2. 配置和mybatis的整合
    1. 指定mybatis的核心配置文件
    2. 指定mybatis的mapper文件
    3. 配置扫描器,将mybatis接口的实现加入到ioc容器中,扫描所有dao接口的实现,加入到ioc容器中
    4. 配置一个可以执行批量的sqlSession,加入到IOC容器里
  3. 事务控制的配置,导入配置好的数据源id
    1. 配置切入点表达式
    2. 配置事务增强
    3. 配置事务如何切入

尚硅谷ssm整合实战项目笔记_第6张图片

applicationContext.xml:


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    
    <context:component-scan base-package="com.xjhqre.crud">
        <context:exclude-filter type="annotation"
                                expression="org.springframework.stereotype.Controller" />
    context:component-scan>

    
    
    <context:property-placeholder location="classpath:db.properties"/>
    <bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="driverClass" value="${jdbc.driverClassName}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    bean>

    
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        
        <property name="dataSource" ref="pooledDataSource"/>
        
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    bean>

    
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        
        <property name="basePackage" value="com.xjhqre.crud.dao"/>
    bean>

    
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
        
        <constructor-arg name="executorType" value="BATCH"/>
    bean>

    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        
        <property name="dataSource" ref="pooledDataSource"/>
    bean>

    
    
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            
            <tx:method name="*"/>
            
            <tx:method name="get*" read-only="true"/>
        tx:attributes>
    tx:advice>
    <aop:config>
        
        <aop:pointcut id="txPoint" expression="execution(* com.xjhqre.crud.service..*(..))"/>
        
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
    aop:config>

beans>

5、编写mybatis核心文件


DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        
        <setting name="logImpl" value="STDOUT_LOGGING" />
    settings>
configuration>

6、创建数据库

DROP DATABASE IF EXISTS ssm;
CREATE DATABASE ssm;
USE ssm;

CREATE TABLE t_emp(
	`emp_id` INT(11) PRIMARY KEY AUTO_INCREMENT,
	`emp_name` VARCHAR(255) NOT NULL,
	`emp_gender` CHAR(1) NOT NULL,
	`emp_email` VARCHAR(255),
	`dept_id` INT(11)
);

CREATE TABLE t_dept(
	`dept_id` INT(11) PRIMARY KEY AUTO_INCREMENT,
	`dept_name` VARCHAR(255) NOT NULL
);

7、mybatis逆向工程

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

步骤:

  1. 导入mybatis generator core包

<dependency>
    <groupId>org.mybatis.generatorgroupId>
    <artifactId>mybatis-generator-coreartifactId>
    <version>1.3.7version>
dependency>
  1. 在当前工程目录下创建 mbg.xml 文件(与pom.xml同级目录)

  2. 配置mgb.xml文件


DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>

    <context id="DB2Tables" targetRuntime="MyBatis3">
        
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        commentGenerator>
        
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/ssm?useSSL=false&serverTimezone=UTC"
                        userId="root"
                        password="123456">
        jdbcConnection>

        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        javaTypeResolver>

        
        <javaModelGenerator targetPackage="com.xjhqre.crud.pojo"
                            targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        javaModelGenerator>

        
        <sqlMapGenerator targetPackage="mapper" targetProject=".\src\main\resources">
            <property name="enableSubPackages" value="true" />
        sqlMapGenerator>

        
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.xjhqre.crud.dao" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
        javaClientGenerator>

        
        <table tableName="t_emp" domainObjectName="Employee"/>
        <table tableName="t_dept" domainObjectName="Department"/>
    context>
generatorConfiguration>
  1. 编写一个测试类运行逆向工程生成mapper和类
@Test
public void mbgTest() throws Exception {
    List<String> warnings = new ArrayList<String>();
    boolean overwrite = true;
    File configFile = new File("mbg.xml");
    ConfigurationParser cp = new ConfigurationParser(warnings);
    Configuration config = cp.parseConfiguration(configFile);
    DefaultShellCallback callback = new DefaultShellCallback(overwrite);
    MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
            callback, warnings);
    myBatisGenerator.generate(null);
}

8、修改mapper映射文件

逆向工程不能生成联合查询。我们需要在mybatis逆向工程生成的mapper映射文件基础上添加新功能,查询员工时带上他的部门信息

步骤:

  1. EmployeeMapper接口上新添加两个方法:
List<Employee> selectByExampleWithDept(EmployeeExample example);

Employee selectByPrimaryKeyWithDept(Integer empId);
  1. Employee员工类上新增属性private Department department;,并添加 get和set方法

  2. EmployeeMapper.xml中编写编写 With_Dept_Column_List:

<sql id="With_Dept_Column_List">
  e.emp_id, e.emp_name, e.emp_gender, e.emp_email, e.dept_id, d.dept_id, d.dept_name
sql>
  1. 编写 WithDeptResultMap 返回结果封装:
<resultMap id="WithDeptResultMap" type="com.xjhqre.crud.pojo.Employee">
  <id column="emp_id" jdbcType="INTEGER" property="empId" />
  <result column="emp_name" jdbcType="VARCHAR" property="empName" />
  <result column="emp_gender" jdbcType="CHAR" property="empGender" />
  <result column="emp_email" jdbcType="VARCHAR" property="empEmail" />
  <result column="dept_id" jdbcType="INTEGER" property="deptId" />
  <association property="department" javaType="com.xjhqre.crud.pojo.Department">
    <id column="dept_id" property="deptId"/>
    <result column="dept_name" property="deptName"/>
  association>
resultMap>
  1. 编写 selectByExampleWithDept
<select id="selectByExampleWithDept" parameterType="com.xjhqre.crud.pojo.EmployeeExample"
        resultMap="WithDeptResultMap">
    select
    <if test="distinct">
        distinct
    if>
    <include refid="With_Dept_Column_List"/>
    from t_emp e left join t_dept d on e.`dept_id`=d.`dept_id`
    <if test="_parameter != null">
        <include refid="Example_Where_Clause"/>
    if>
    <if test="orderByClause != null">
        order by ${orderByClause}
    if>
select>
  1. 编写 selectByPrimaryKeyWithDept
<select id="selectByPrimaryKeyWithDept" parameterType="java.lang.Integer" resultMap="WithDeptResultMap">
    select
    <include refid="With_Dept_Column_List"/>
    from t_emp e left join t_dept d on e.`dept_id`=d.`dept_id`
    where emp_id = #{empId,jdbcType=INTEGER}
select>

9、测试dao接口方法

spring项目推荐使用spring的单元测试,可以自动注入我们需要的组件

需要导入spring-test包


<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-testartifactId>
    <version>5.3.14version>
    <scope>testscope>
dependency>

测试代码:

Department类和Employee类中添加构造函数

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class MapperTest {
    @Autowired
    DepartmentMapper departmentMapper;

    @Autowired
    EmployeeMapper employeeMapper;

    @Autowired
    SqlSession sqlSession;

    @Test
    public void test1() {
        System.out.println(departmentMapper);

        // 1. 测试插入部门
        departmentMapper.insertSelective(new Department(null, "技术部"));
        departmentMapper.insertSelective(new Department(null, "开发部"));

        // 2、生成员工数据,测试员工插入
        employeeMapper.insertSelective(new Employee(null, "xjhqre", "M", "[email protected]", 1));

        // 3、批量插入多个员工;批量,使用可以执行批量操作的sqlSession。
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
        for (int i = 0; i < 100; i++) {
            String uid = UUID.randomUUID().toString().substring(0, 5) + i;
            mapper.insertSelective(new Employee(null, uid, "M", uid + "@126.com", 1));
        }
    }
}

三、查询功能实现

步骤:

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

1、编写 index.jsp 页面:

发送请求为 /emps

<%@ page contentType="text/html;charset=UTF-8" language="java" %>



    Title




2、编写list.jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>



    
    员工列表





3、编写EmployeeService类

@Service
public class EmployeeService {

    @Autowired
    EmployeeMapper employeeMapper;

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

4、引入PageHelper分页插件

  1. 在pom.xml文件里引入PageHelper依赖
<dependency>
    <groupId>com.github.pagehelpergroupId>
    <artifactId>pagehelperartifactId>
    <version>5.1.2version>
dependency>
  1. 在 mybatis 核心文件中注册插件,写在 标签后面
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
plugins>

5、编写EmployeeController类

@Controller
public class EmployeeController {

    @Autowired
    EmployeeService employeeService;

    /**
     * 查询员工数据
     * @return 员工信息
     */
    @RequestMapping("/emps")
    public String queryAllEmployees(@RequestParam(value = "pn", defaultValue = "1")Integer pn, Model model) {
        // 在查询之前调用分页插件,传入页码以及每页分页的大小
        PageHelper.startPage(pn, 5);
        // startPage后面紧跟的这个查询就是一个分页查询
        List<Employee> employees = employeeService.queryAllEmployees();
        // 使用pageInfo包装查询后的结果,只需要将pageInfo交给页面展示
        PageInfo pageInfo = new PageInfo(employees, 5); // 传入页码显示数量
        model.addAttribute("pageInfo", pageInfo);
        return "list"; // 返回到 list.jsp 页面
    }
}

6、虚拟MVC测试

/**
 * 使用Spring测试模块提供的测试请求功能,测试curd请求的正确性
 * Spring4测试的时候,需要servlet3.0的支持
 *
 * @author lfy
 */
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration // 表示测试的 ApplicationContext 应该是WebApplicationContext
@ContextConfiguration(locations = {"classpath:applicationContext.xml",
        "/WEB-INF/dispatcherServlet-servlet.xml"})
public class MvcTest {
    // 传入SpringMVC的ioc
    @Autowired
    WebApplicationContext context;
    // 虚拟MVC请求,获取到处理结果
    MockMvc mockMvc;

    @Before
    public void initMokcMvc() {
        // 初始化mockMvc
        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
    }

    @Test
    public void testPage() throws Exception {
        // 模拟发送get请求, 传入参数名和参数的值,拿到返回值
        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/emps").param("pn", "5")).andReturn();
        // 请求成功以后,请求域中会有pageInfo;我们可以取出pageInfo进行验证
        MockHttpServletRequest request = result.getRequest();
        PageInfo pageInfo = (PageInfo) request.getAttribute("pageInfo");
        System.out.println("当前页码:" + pageInfo.getPageNum());
        System.out.println("总页码:" + pageInfo.getPages());
        System.out.println("总记录数:" + pageInfo.getTotal());
        System.out.println("在页面需要连续显示的页码");
        int[] nums = pageInfo.getNavigatepageNums();
        for (int i : nums) {
            System.out.print(" "+i);
        }
        System.out.println();
        //获取员工数据
        List<Employee> list = pageInfo.getList();
        for (Employee employee : list) {
            System.out.println("ID:"+employee.getEmpId()+"==>Name:"+employee.getEmpName());
        }
    }
}

7、完善list.jsp页面

引入 jsp 依赖包,不引入无法使用pageContextsetAttribute方法


<dependency>
    <groupId>javax.servletgroupId>
    <artifactId>jsp-apiartifactId>
    <version>2.0version>
    <scope>providedscope>
dependency>

list.jsp页面:

  1. pageInfo 中取出取出员工信息显示
  2. 完善分页条
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>



    
    员工列表
    <%
        pageContext.setAttribute("APP_PATH", request.getContextPath());
    %>
    
    
    
    


<%-- 搭建显示页面 --%>
<%-- 标题 --%>

SSM_CRUD

<%-- 按钮 --%>
<%-- 显示表格数据 --%>
# empName gender email deptName 操作
${emp.empId} ${emp.empName} ${emp.empGender} ${emp.empEmail} ${emp.department.deptName}
<%-- 显示分页信息 --%>
<%--分页条信息--%>
<%--分页文字信息 --%>
当前第${pageInfo.pageNum}页,总页数:${pageInfo.pages}, 总记录数:${pageInfo.total}

四、改写查询功能

步骤:

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

1、创建Msg类

类中定义状态码、提示信息、返回给用户的数据、以及相关的 get、set方法,还要定义一个 add 方法,返回 Msg 类对象,用于链式调用

public class Msg {
    // 状态码 100:成功   200:失败
    private int code;
    // 提示信息
    private String msg;
    // 返回给用户的数据,用map存储
    private Map<String, Object> extend = new HashMap<>();

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

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

    // 用于链式添加信息
    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;
    }
}

2、改写处理器方法

返回 json 数据,需要导入jackson包


<dependency>
    <groupId>com.fasterxml.jackson.coregroupId>
    <artifactId>jackson-databindartifactId>
    <version>2.12.3version>
dependency>

EmployeeController:

@Controller
public class EmployeeController {

    @Autowired
    EmployeeService employeeService;

    /**
     * 查询员工数据
     * @return 员工信息
     */
    @RequestMapping("/emps")
    @ResponseBody
    public Msg queryAllEmployees(@RequestParam(value = "pn", defaultValue = "1")Integer pn) {
        PageHelper.startPage(pn, 5);
        List<Employee> employees = employeeService.queryAllEmployees();
        PageInfo pageInfo = new PageInfo(employees, 5);
        return Msg.success().add("pageInfo", pageInfo);
    }
}

3、修改 index.jsp

在 index.jsp 页面加载完后 发送 Ajax 请求,将返回的 JSON 数据解析。删除原来的 标签

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>员工列表title>
    <%
        pageContext.setAttribute("APP_PATH", request.getContextPath());
    %>
    
    <script type="text/javascript" src="${APP_PATH}/static/js/jquery-1.12.4.min.js">script>
    <link href="${APP_PATH}/static/bootstrap-3.4.1-dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="${APP_PATH}/static/bootstrap-3.4.1-dist/css/bootstrap.min.css">script>
head>
<body>
<%-- 搭建显示页面 --%>
<div class="container">
    <%-- 标题 --%>
    <div class="row">
        <div class="col-md-12">
            <h1>SSM_CRUDh1>
        div>
    div>
    <%-- 按钮 --%>
    <div class="row">
        <div class="col-md-2 col-md-offset-10">
            <button class="btn btn-primary">
                <span class="glyphicon glyphicon-pencil" aria-hidden="true">span>添加
            button>
            <button class="btn btn-danger">
                <span class="glyphicon glyphicon-trash" aria-hidden="true">span>删除
            button>
        div>
    div>
    <%-- 显示表格数据 --%>
    <div class="row">
        <div class="col-md-12">
            <table class="table table-striped" id="emps_table">
                <thead>
                <tr>
                    <th>#th>
                    <th>empNameth>
                    <th>genderth>
                    <th>emailth>
                    <th>deptNameth>
                    <th>操作th>
                tr>
                thead>
                <tbody>
                <%-- 通过函数加载数据 --%>
                tbody>
            table>
        div>
    div>
    <%-- 显示分页信息 --%>
    <div class="row">
        <%--分页条信息--%>
        <div class="col-md-6 col-md-offset-3 text-center" id="page_info_area">div>
    div>
    <div class="row">
        <%--分页文字信息 --%>
        <div class="col-md-6 col-md-offset-3 text-center" id="page_nav_area">div>
    div>

div>
<script type="text/javascript">
    // 初始化页面时需要调用的函数
    $(function () {
        // 去首页
        to_page(1);
    });

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

    function build_emps_table(result) {
        // 清空表格信息
        $("#emps_table tbody").empty()
        // 获取员工列表
        var emps = result.extend.pageInfo.list;
        // 遍历员工列表,构建表格
        $.each(emps, function (index, item) {
            var empIdTd = $("").append(item.empId);
            var empNameTd = $("").append(item.empName)
            var genderTd = $("").append(item.empGender == "M" ? "男" : "女")
            var emailTd = $("").append(item.empEmail)
            var deptNameTd = $("").append(item.department.deptName)

            // 注入按钮数据
            var editBtn = $("").addClass("btn btn-primary btn-sm")
                .append($("").addClass("glyphicon glyphicon-pencil"))
                .append("编辑");
            var delBtn = $("").addClass("btn btn-danger btn-sm")
                .append($("").addClass("glyphicon glyphicon-trash"))
                .append("删除");

            var btnTd = $("").append(editBtn).append(" ").append(delBtn);
            $("").append(empIdTd)
                .append(empNameTd)
                .append(genderTd)
                .append(emailTd)
                .append(deptNameTd)
                .append(btnTd)
                .appendTo("#emps_table tbody");
        });
    }

    // 解析显示分页信息
    function build_page_info(result) {
        // 清空原来的分页信息
        $("#page_info_area").empty()
        $("#page_info_area").append("当前页:" +
            result.extend.pageInfo.pageNum + ",总页数:" +
            result.extend.pageInfo.pages + ",总记录数:" +
            result.extend.pageInfo.total)
    }

    // 解析显示分页条
    function build_page_nav(result) {
        // 清空原来的分页码
        $("#page_nav_area").empty();
        // 构建元素
        var ul = $("
    "
    ).addClass("pagination") var firstPageLi = $("
  • "
    ).append($("").append("首页").attr("href", "#")); var prePageLi = $("
  • "
    ).append($("").append("«").attr("href", "#")); var nextPageLi = $("
  • "
    ).append($("").append("»").attr("href", "#")); var lastPageLi = $("
  • "
    ).append($("").append("末页").attr("href", "#")); // 添加首页、末页、上一页、下一页禁用 和跳转功能 if (result.extend.pageInfo.hasPreviousPage == false) { firstPageLi.addClass("disabled") prePageLi.addClass("disabled") } else { firstPageLi.click(function () { to_page(1) }) prePageLi.click(function () { to_page(result.extend.pageInfo.pageNum-1) }) } if (result.extend.pageInfo.hasNextPage == false) { nextPageLi.addClass("disabled"); lastPageLi.addClass("disabled"); } else { lastPageLi.click(function () { to_page(result.extend.pageInfo.pages); }); nextPageLi.click(function () { to_page(result.extend.pageInfo.pageNum+1); }); } // 添加首页和前一页 ul.append(firstPageLi).append(prePageLi) // 构建条码 $.each(result.extend.pageInfo.navigatepageNums, function (index, num) { var numLi = $("
  • "
    ).append($("").append(num).attr("href", "#")); // 设置当前页码高亮显示 if (result.extend.pageInfo.pageNum == num) { numLi.addClass("active") } // 添加按钮跳转事件 numLi.click(function () { to_page(num) }) ul.append(numLi) }); // 添加末页和后一页 ul.append(nextPageLi).append(lastPageLi) var navEle = $("").append(ul) navEle.appendTo("#page_nav_area"); }
    script> body> html>

    五、编写添加功能

    步骤:

    1. 在index.jsp页面点击“新增”按钮
    2. 弹出添加模态框
    3. 从数据库中查询出所有部门名称显示在下拉列表中
    4. 用户输入数据
    5. 校验用户名、邮箱格式是否正确、用户名是否重复
    6. 点击“保存”按钮添加数据

    1、编写查询所有部门的业务逻辑

    1.1、编写DepartmentService

    @Service
    public class DepartmentService {
        @Autowired
        DepartmentMapper departmentMapper;
    
        public List<Department> quireAllDepartments() {
            return departmentMapper.selectByExample(null);
        }
    }
    

    1.2、编写DepartmentController

    @Controller
    public class DepartmentController {
    
        @Autowired
        DepartmentService departmentService;
    
        @RequestMapping("/depts")
        @ResponseBody
        public Msg quireAllDepartments() {
            List<Department> departments = departmentService.quireAllDepartments();
            return Msg.success().add("depts", departments);
        }
    }
    

    2、编写保存员工代码

    规定URI:

    • /emp/{id} GET查询员工
    • /emp POST保存员工
    • /emp/{id} PUT修改员工
    • /emp/{id} DELETE删除员工

    2.1、编写Service层方法

    public void saveEmp(Employee employee) {
        employeeMapper.insertSelective(employee);
    }
    

    2.2、编写controller层方法

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

    3、设置分页助手

    在添加用户后跳转到最后一页,传入跳转的页数为总记录数,需要设置分页助手参数合理化。否则会跳转到其他非法地址

    在 mybatis 核心配置文件中配置

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            
            <property name="reasonable" value="true"/>
        plugin>
    plugins>
    

    reasonable:分页合理化参数,默认值为 false,当该参数为 true 时,pageNum<=0 时会查询第一页,pageNum(超过总数时),会查询最后一页,默认 false 时,直接根据参数进行查询

    4、前端校验

    • 用户名格式校验
    • 邮箱格式校验
    • 邮箱是否重复校验

    4.1、检查邮箱是否已存在

    因为员工姓名可能存在重复的情况,所以检查邮箱是否已存在

    当输入完邮箱后失去焦点,页面发送Ajax请求查询邮箱是否重复,重复则在页面显示“邮箱地址重复”

    发送表单中含有中文,使用POST请求,因为GET请求不校验中文

    编写Service层方法

    /**
     * 检查邮箱是否重复
     * @param empEmail 页面传来的邮箱
     * @return 返回该邮箱是否可用
     */
    public boolean checkForDuplicateEmails(String empEmail) {
        EmployeeExample example = new EmployeeExample();
        EmployeeExample.Criteria criteria = example.createCriteria();
        criteria.andEmpEmailEqualTo(empEmail);
        long count = employeeMapper.countByExample(example);
        return count == 0;
    }
    

    编写Controller层方法

    /**
     * 检查邮箱是否可用
     * @param empEmail 网页传来的邮箱
     * @return json数据
     */
    @RequestMapping("/checkEmail")
    @ResponseBody
    public Msg checkForDuplicateEmails(@RequestParam("empEmail")String empEmail) {
        boolean b = employeeService.checkForDuplicateEmails(empEmail);
        if(b){
            return Msg.success();
        }else {
            return Msg.fail();
        }
    }
    

    5、后端校验

    重要数据使用 JSR303 进行校验

    5.1、导入相关jar包

    需要导入 Hibernate-Validator

    JSR303数据校验支持:tomcat7及以上的服务器,tomcat7以下的服务器:el表达式。额外给服务器的lib包中替换新的标准的el

    
    <dependency>
        <groupId>org.hibernategroupId>
        <artifactId>hibernate-validatorartifactId>
        <version>6.1.0.Finalversion>
    dependency>
    

    5.2、修改Employee类

    给empName和empEmail属性添加校验注解

    @Pattern(regexp = "(^[a-zA-Z0-9_-]{3,16}$)|(^[\\u2E80-\\u9FFF]{2,5})",
            message = "用户名格式错误")
    private String empName;
    
    @Pattern(regexp = "^[a-z\\d]+(\\.[a-z\\d]+)*@([\\da-z](-[\\da-z])?)+(\\.{1,2}[a-z]+)+$",
                message = "邮箱格式错误")
        private String empEmail;
    

    5.3、修改添加员工控制

    @Valid:指定要校验的数据

    BindingResult:封装校验的结果

    打印中文乱码则在tomcat中的虚拟机选项配置:-Dfile.encoding=UTF-8

    @RequestMapping(value = "/emp", method = RequestMethod.POST)
    @ResponseBody
    public Msg saveEmp(@Valid Employee employee, BindingResult result) {
        if (result.hasErrors()) {
            Map<String, Object> map = new HashMap<>();
            List<FieldError> errors = result.getFieldErrors();
            for (FieldError error : errors) {
                System.out.println("错误的字段名:" + error.getField());
                System.out.println("错误信息:" + error.getDefaultMessage());
                map.put(error.getField(), error.getDefaultMessage());
            }
            return Msg.fail().add("errorFields", map);
        } else {
            employeeService.saveEmp(employee);
            return Msg.success();
        }
    }
    

    5.4、修改保存按钮事件函数

    // 模态框保存按钮点击事件
    $("#saveEmpBtn").click(function () {
        // 校验表单数据
        if (!isTheUsernameCorrect || !isTheEmailAddressCorrect) {
            return false
        }
    
        // 发送保存请求
        $.ajax({
            url: "${APP_PATH}/emp",
            type: "POST",
            data: $("#empAddModal form").serialize(),
            success: function (result) {
                if(result.code == 100) {
                    // 员工保存成功
                    // 1. 关闭模态框
                    $("#empAddModal").modal('hide')
                    // 2. 跳转到最后一页显示
                    to_page(totalRecord)
                } else {
                    // 显示失败信息
                    if(undefined != result.extend.errorFields.empEmail){
                        validate_add_from_information_show("#empEmail_add_input", "error", "邮箱格式不正确")
                    }
                    if(undefined != result.extend.errorFields.empName){
                        validate_add_from_information_show("#empName_add_input", "error", "员工名称格式不正确")
                    }
                }
    
            }
        })
    })
    

    5.5、完整jsp页面

    <%@ page language="java" contentType="text/html; charset=UTF-8"
             pageEncoding="UTF-8" %>
    DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>员工列表title>
        <%
            pageContext.setAttribute("APP_PATH", request.getContextPath());
        %>
        
        <script type="text/javascript" src="${APP_PATH}/static/js/jquery-1.12.4.min.js">script>
        <script src="${APP_PATH }/static/bootstrap-3.4.1-dist/js/bootstrap.min.js">script>
        <link href="${APP_PATH}/static/bootstrap-3.4.1-dist/css/bootstrap.min.css" rel="stylesheet">
    head>
    <body>
    <%-- 添加员工模态框 --%>
    <div class="modal fade" id="empAddModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×span>
                    button>
                    <h4 class="modal-title" id="myModalLabel">添加员工h4>
                div>
                <div class="modal-body">
                    <%-- 表单 --%>
                    <form class="form-horizontal">
                        <div class="form-group">
                            <label for="empName_add_input" class="col-sm-2 control-label">empNamelabel>
                            <div class="col-sm-10">
                                <input name="empName" type="text" class="form-control" id="empName_add_input"
                                       placeholder="empName">
                                <span class="help-block">span>
                            div>
                        div>
                        <div class="form-group">
                            <label for="empEmail_add_input" class="col-sm-2 control-label">Emaillabel>
                            <div class="col-sm-10">
                                <input name="empEmail" type="text" class="form-control" id="empEmail_add_input"
                                       placeholder="empEmail">
                                <span class="help-block">span>
                            div>
                        div>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">empGenderlabel>
                            <div class="col-sm-10">
                                <label class="radio-inline">
                                    <input type="radio" name="empGender" id="empGender_add_input" value="M" checked="checked">label>
                                <label class="radio-inline">
                                    <input type="radio" name="empGender" id="empGender_add_input2" value="F">label>
                            div>
                        div>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">deptIdlabel>
                            <div class="col-sm-4">
                                <select class="form-control" name="deptId" id="deptId_add_select">
                                select>
                            div>
                        div>
                    form>
                div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">关闭button>
                    <button type="button" class="btn btn-primary" id="saveEmpBtn">保存button>
                div>
            div>
        div>
    div>
    
    <%-- 搭建显示页面 --%>
    <div class="container">
        <%-- 标题 --%>
        <div class="row">
            <div class="col-md-12">
                <h1>SSM_CRUDh1>
            div>
        div>
        <%-- 按钮 --%>
        <div class="row">
            <div class="col-md-2 col-md-offset-10">
                <button class="btn btn-primary" id="emp_add_modal_btn">
                    <span class="glyphicon glyphicon-pencil" aria-hidden="true">span>添加
                button>
                <button class="btn btn-danger">
                    <span class="glyphicon glyphicon-trash" aria-hidden="true">span>删除
                button>
            div>
        div>
        <%-- 显示表格数据 --%>
        <div class="row">
            <div class="col-md-12">
                <table class="table table-striped" id="emps_table">
                    <thead>
                    <tr>
                        <th>#th>
                        <th>empNameth>
                        <th>genderth>
                        <th>emailth>
                        <th>deptNameth>
                        <th>操作th>
                    tr>
                    thead>
                    <tbody>
                    <%-- 通过函数加载数据 --%>
                    tbody>
                table>
            div>
        div>
        <%-- 显示分页信息 --%>
        <div class="row">
            <%--分页条信息--%>
            <div class="col-md-6 col-md-offset-3 text-center" id="page_info_area">div>
        div>
        <div class="row">
            <%--分页文字信息 --%>
            <div class="col-md-6 col-md-offset-3 text-center" id="page_nav_area">div>
        div>
    
    div>
    <script type="text/javascript">
        /* ================================================ 全局变量 ================================================ */
    
        var totalRecord; // 用于跳转到末页
        var isTheUsernameCorrect = false // 用户名是否正确
        var isTheEmailAddressCorrect = false // 邮箱是否正确
    
        /* ================================================ 函数 ================================================ */
        // 初始化页面时需要调用的函数
        $(function () {
            // 去首页
            to_page(1);
        });
    
        // 页面跳转函数
        function to_page(pn) {
            $.ajax({
                url: "${APP_PATH}/emps",
                data: "pn=" + pn,
                type: "GET",
                success: function (result) {
                    // 1.解析员工数据
                    build_emps_table(result);
                    // 2. 解析并显示分页信息
                    build_page_info(result);
                    // 3. 解析显示分页条码
                    build_page_nav(result);
                }
            });
        }
    
        // 解析表格数据函数
        function build_emps_table(result) {
            // 清空表格信息
            $("#emps_table tbody").empty()
            // 获取员工列表
            var emps = result.extend.pageInfo.list;
            // 遍历员工列表,构建表格
            $.each(emps, function (index, item) {
                var empIdTd = $("").append(item.empId);
                var empNameTd = $("").append(item.empName)
                var genderTd = $("").append(item.empGender == "M" ? "男" : "女")
                var emailTd = $("").append(item.empEmail)
                var deptNameTd = $("").append(item.department.deptName)
    
                // 注入按钮数据
                var editBtn = $("").addClass("btn btn-primary btn-sm")
                    .append($("").addClass("glyphicon glyphicon-pencil"))
                    .append("编辑");
                var delBtn = $("").addClass("btn btn-danger btn-sm")
                    .append($("").addClass("glyphicon glyphicon-trash"))
                    .append("删除");
    
                var btnTd = $("").append(editBtn).append(" ").append(delBtn);
                $("").append(empIdTd)
                    .append(empNameTd)
                    .append(genderTd)
                    .append(emailTd)
                    .append(deptNameTd)
                    .append(btnTd)
                    .appendTo("#emps_table tbody");
            });
        }
    
        // 解析显示分页信息函数
        function build_page_info(result) {
            // 清空原来的分页信息
            $("#page_info_area").empty()
            $("#page_info_area").append("当前页:" +
                result.extend.pageInfo.pageNum + ",总页数:" +
                result.extend.pageInfo.pages + ",总记录数:" +
                result.extend.pageInfo.total)
            totalRecord = result.extend.pageInfo.total
        }
    
        // 解析显示分页条函数
        function build_page_nav(result) {
            // 清空原来的分页码
            $("#page_nav_area").empty();
            // 构建元素
            var ul = $("
      "
      ).addClass("pagination") var firstPageLi = $("
    • "
      ).append($("").append("首页").attr("href", "#")); var prePageLi = $("
    • "
      ).append($("").append("«").attr("href", "#")); var nextPageLi = $("
    • "
      ).append($("").append("»").attr("href", "#")); var lastPageLi = $("
    • "
      ).append($("").append("末页").attr("href", "#")); // 添加首页、末页、上一页、下一页禁用 和跳转功能 if (result.extend.pageInfo.hasPreviousPage == false) { firstPageLi.addClass("disabled") prePageLi.addClass("disabled") } else { firstPageLi.click(function () { to_page(1) }) prePageLi.click(function () { to_page(result.extend.pageInfo.pageNum - 1) }) } if (result.extend.pageInfo.hasNextPage == false) { nextPageLi.addClass("disabled"); lastPageLi.addClass("disabled"); } else { lastPageLi.click(function () { to_page(result.extend.pageInfo.pages); }); nextPageLi.click(function () { to_page(result.extend.pageInfo.pageNum + 1); }); } // 添加首页和前一页 ul.append(firstPageLi).append(prePageLi) // 构建条码 $.each(result.extend.pageInfo.navigatepageNums, function (index, num) { var numLi = $("
    • "
      ).append($("").append(num).attr("href", "#")); // 设置当前页码高亮显示 if (result.extend.pageInfo.pageNum == num) { numLi.addClass("active") } // 添加按钮跳转事件 numLi.click(function () { to_page(num) }) ul.append(numLi) }); // 添加末页和后一页 ul.append(nextPageLi).append(lastPageLi) var navEle = $("").append(ul) navEle.appendTo("#page_nav_area"); } // 查询所有部门信息请求函数 function getDepts() { $.ajax({ url: "${APP_PATH}/depts", type: "GET", success: function (result) { console.log(result) $.each(result.extend.depts, function () { var optionElement = $("").append(this.deptName).attr("value", this.deptId) optionElement.appendTo("#deptId_add_select") }) } }) } // 添加员工表单数据校验信息显示函数 function validate_add_from_information_show(ele, status, msg) { // 清楚当前元素的校验状态 $(ele).parent().removeClass("has-success has-error") $(ele).next("span").text("") if("success" == status){ $(ele).parent().addClass("has-success") $(ele).next("span").text(msg) } else if ("error" == status) { $(ele).parent().addClass("has-error") $(ele).next("span").text(msg) } } // 重置添加员工表单数据和样式 function reset_form(ele) { // 清空表单数据 $(ele + " form")[0].reset() // 清空表单样式 $(ele + " form").find("*").removeClass("has-success has-error") $(ele + " form").find(".help-block").text("") // 清空下拉列表 $(ele + " select").empty() } /* ============================================== 按钮绑定事件区 ============================================== */ // 添加员工按钮事件 $("#emp_add_modal_btn").click(function () { // 表单重置数据 reset_form("#empAddModal") // 发送Ajax请求, 查出部门信息,显示在下拉列表中 getDepts() $("#empAddModal").modal({ backdrop: "static" }) }) // 模态框保存按钮点击事件 $("#saveEmpBtn").click(function () { // 校验表单数据 if (!isTheUsernameCorrect || !isTheEmailAddressCorrect) { return false } // 发送保存请求 $.ajax({ url: "${APP_PATH}/emp", type: "POST", data: $("#empAddModal form").serialize(), success: function (result) { if(result.code == 100) { // 员工保存成功 // 1. 关闭模态框 $("#empAddModal").modal('hide') // 2. 跳转到最后一页显示 to_page(totalRecord) } else { // 显示失败信息 if(undefined != result.extend.errorFields.empEmail){ validate_add_from_information_show("#empEmail_add_input", "error", "邮箱格式不正确") } if(undefined != result.extend.errorFields.empName){ validate_add_from_information_show("#empName_add_input", "error", "员工名称格式不正确") } } } }) }) // 用户名栏失去焦点时进行格式检查 $("#empName_add_input").blur(function () { var empName = $("#empName_add_input").val(); var regName = /(^[a-zA-Z0-9_-]{3,16}$)|(^[\u2E80-\u9FFF]{2,5})/ // 允许英文和中文 if(!regName.test(empName)){ validate_add_from_information_show("#empName_add_input", "error", "员工名称格式不正确") } else { validate_add_from_information_show("#empName_add_input", "success", "") isTheUsernameCorrect = true } }) // 邮箱栏失去焦点时进行格式检查和重复检查 $("#empEmail_add_input").blur(function () { var empEmail = $("#empEmail_add_input").val() var regEmail = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/ if(!regEmail.test(empEmail)){ validate_add_from_information_show("#empEmail_add_input", "error", "邮箱格式不正确") } // 发送Ajax请求判断邮箱是否重复 $.ajax({ url:"${APP_PATH}/checkEmail", data:"empEmail=" + empEmail, type:"GET", // get请求不检验中文,如果发送对象中含中文则用POST success:function (result) { console.log(result) if(result.code == 100 && regEmail.test(empEmail)) { validate_add_from_information_show("#empEmail_add_input", "success", "") isTheEmailAddressCorrect = true } else if (result.code == 200) { validate_add_from_information_show("#empEmail_add_input", "error", "邮箱已存在") } } }) })
      script> body> html>

      六、修改员工信息功能

      步骤:

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

      1、编写修改模态框

      <%-- 修改员工模态框 --%>
      <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">×span>
                      button>
                      <h4 class="modal-title" id="updateModalLabel">修改员工h4>
                  div>
                  <div class="modal-body">
                      <%-- 表单 --%>
                      <form class="form-horizontal">
                          <div class="form-group">
                              <label for="empName_add_input" class="col-sm-2 control-label">empNamelabel>
                              <div class="col-sm-10">
                                  <input name="empName" type="text" class="form-control" id="empName_update_input"
                                         placeholder="empName">
                                  <span class="help-block">span>
                              div>
                          div>
                          <div class="form-group">
                              <label for="empEmail_add_input" class="col-sm-2 control-label">Emaillabel>
                              <div class="col-sm-10">
                                  <input name="empEmail" type="text" class="form-control" id="empEmail_update_input"
                                         placeholder="empEmail">
                                  <span class="help-block">span>
                              div>
                          div>
                          <div class="form-group">
                              <label class="col-sm-2 control-label">empGenderlabel>
                              <div class="col-sm-10">
                                  <label class="radio-inline">
                                      <input type="radio" name="empGender" id="empGender_update_input" value="M" checked="checked">label>
                                  <label class="radio-inline">
                                      <input type="radio" name="empGender" id="empGender_update_input2" value="F">label>
                              div>
                          div>
                          <div class="form-group">
                              <label class="col-sm-2 control-label">deptIdlabel>
                              <div class="col-sm-4">
                                  <select class="form-control" name="deptId" id="deptId_update_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="updateEmpBtn">更新button>
                  div>
              div>
          div>
      div>
      

      2、添加按钮样式

      给员工列表的修改和删除按钮添加样式:edit_btn、del_btn

      // 注入按钮数据
      var editBtn = $("").addClass("btn btn-primary btn-sm edit_btn")
          .append($("").addClass("glyphicon glyphicon-pencil"))
          .append("编辑");
      var delBtn = $("").addClass("btn btn-danger btn-sm del_btn")
          .append($("").addClass("glyphicon glyphicon-trash"))
          .append("删除");
      

      3、修改重置表单函数

      新增下拉列表的重置

      // 重置添加员工表单数据和样式
      function reset_form(ele) {
          // 清空表单数据
          $(ele + " form")[0].reset()
          // 清空表单样式
          $(ele + " form").find("*").removeClass("has-success has-error")
          $(ele + " form").find(".help-block").text("")
          // 清空下拉列表
          $(ele + " select").empty()
      }
      

      4、编辑按钮事件

      // 为修改员工按钮添加事件
      // 因为是先绑定事件后在生成的按钮,所以不能用click
      // 早先版本的jQuery可以使用live方法
      // 这里使用 on 方法绑定
      $(document).on("click", ".edit_btn", function () {
          // 1. 查询部门信息显示
          getDepts("#deptId_update_select")
          
          // 2. 回显员工信息
      
          // 3. 跳出模态框
          $("#empUpdateModal").modal({
              backdrop: "static"
          })
      })
      

      5、回显用户数据

      5.1、编写控制器方法

      /**
       * 根据id查询员工信息
       * @param id 页面传入的id
       * @return 员工对象的JSON数据
       */
      @RequestMapping(value = "/emp/{id}", method = RequestMethod.GET)
      @ResponseBody
      public Msg getEmpById(@PathVariable("id")Integer id) {
          Employee emp = employeeService.getEmpById(id);
          return Msg.success().add("emp", emp);
      }
      

      5.2、编写Service层方法

      public Employee getEmpById(Integer id) {
          return employeeMapper.selectByPrimaryKey(id);
      }
      

      5.3、网页查询员工信息函数

      // 根据id查询员工信息函数
      function getEmpById(id) {
          $.ajax({
              url:"${APP_PATH}/emp/" + id,
              type:"GET",
              success:function (result) {
                  console.log(result)
              }
          })
      }
      

      5.4、为修改员工按钮添加属性

      在定义editBtn按钮之后添加empId属性,用于修改员工时传递id值

      // 添加自定义属性,用于修改员工时传递id值
      editBtn.attr("empId_for_edit", item.empId)
      

      5.5、回显员工信息函数

      这里传入的是部门id,而回显的是部门名称的原因:

      1. val() 方法返回或设置被选元素的值。元素的值是通过 value 属性设置的。该方法大多用于 input 元素。
      2. 查询部门信息时,value属性定义的是id,显示的是部门名,页面根据传入的id值选择了相应的部门名
      // 根据id查询员工信息函数
      function getEmpById(id) {
          $.ajax({
              url:"${APP_PATH}/emp/" + id,
              type:"GET",
              success:function (result) {
                  var empData = result.extend.empty;
                  $("#empName_update_input").val(empData.empName);
                  $("#empEmail_update_input").val(empData.empEmail);
                  $("#empUpdateModal input[name=empGender]").val(empData.empGender);
                  $("#empUpdateModal select").val(empData.deptId);
              }
          })
      }
      

      5.6、完善修改按钮事件

      // 为修改员工按钮添加事件
      // 因为是先绑定事件后在生成的按钮,所以不能用click
      // 早先版本的jQuery可以使用live方法
      // 这里使用 on 方法绑定
      $(document).on("click", ".edit_btn", function () {
          // 1. 查询部门信息显示
          getDepts("#deptId_update_select")
          // 2. 回显员工信息
          getEmpById($(this).attr("empId_for_edit"))
          // 3. 跳出模态框
          $("#empUpdateModal").modal({
              backdrop: "static"
          })
      })
      

      6、更新按钮事件

      步骤:

      1. 绑定更新按钮事件
      2. 前端校验用户名和邮箱格式
      3. 将编辑按钮的id属性传递给更新按钮
      4. 前端发送Ajax请求更新员工数据
      5. 编写更新员工控制器
      6. 编写更新员工Service方法

      6.1、控制器方法

      注意事项

      @RequestMapping(value = "/emp/{empId}", method = RequestMethod.PUT)

      上述代码里的 {empId} ,大括号中的名称必须和对象类的属性名相同

      如果直接使用ajax=PUT的请求

      存在问题:

      • 请求体中有数据,但是Employee对象封装属性失败

      原因:

      • Tomcat将请求体中的数据封装为一个map,SpringMVC封装POJO对象的时候,底层使用request.getParameter(“empName”) 从map中取值
      • Tomcat不会封装请求体中的数据为map,只有POST请求才会封装成map

      request和connector原码:

      org.apache.catalina.connector.Request--parseParameters() 
      (3111);
      
      protected String parseBodyMethods = "POST";
      
      if( !getConnector().isParseBodyMethod(getMethod()) ) {
          success = true;
          return;
      }
      
      /**
       * 根据id更新员工信息
       * @param employee 页面传来的员工数据
       * @param result 校验结果
       * @return 校验信息
       */
      @RequestMapping(value = "/emp/{empId}", method = RequestMethod.PUT)
      @ResponseBody
      public Msg updateEmpById(@Valid Employee employee, BindingResult result) {
          if (result.hasErrors()) {
              Map<String, Object> map = new HashMap<>();
              List<FieldError> errors = result.getFieldErrors();
              for (FieldError error : errors) {
                  System.out.println("错误的字段名:" + error.getField());
                  System.out.println("错误信息:" + error.getDefaultMessage());
                  map.put(error.getField(), error.getDefaultMessage());
              }
              return Msg.fail().add("errorFields", map);
          } else {
              employeeService.updateEmpById(employee);
              return Msg.success();
          }
      }
      

      6.2、Service层方法

      /**
       * 根据id更新员工数据
       * @param employee 页面传来的员工数据
       */
      public void updateEmpById(Employee employee) {
          employeeMapper.updateByPrimaryKey(employee);
      }
      

      6.3、修改编辑按钮事件

      将编辑按钮的id属性传递给更新按钮

      // 为修改员工按钮添加事件
      // 因为是先绑定事件后在生成的按钮,所以不能用click
      // 早先版本的jQuery可以使用live方法
      // 这里使用 on 方法绑定
      $(document).on("click", ".edit_btn", function () {
          // 1. 查询部门信息显示
          getDepts("#deptId_update_select")
          // 2. 回显员工信息
          getEmpById($(this).attr("empId_for_edit"))
          // 3. 传递id給更新按钮
          $("#updateEmpBtn").attr("empId_for_edit", $(this).attr("empId_for_edit"))
          // 4. 跳出模态框
          $("#empUpdateModal").modal({
              backdrop: "static"
          })
      })
      

      6.4、使用PUT发送请求

      在web.xml设置 HttpPutFormContentFilter

      作用:

      1. 将请求体中的数据解析包装成一个map
      2. request重新被包装,request.getParameter()被重写,就会从自己封装的map中获取数据
      <filter>
          <filter-name>HttpPutFormContentFilterfilter-name>
          <filter-class>org.springframework.web.filter.HttpPutFormContentFilterfilter-class>
      filter>
      <filter-mapping>
          <filter-name>HttpPutFormContentFilterfilter-name>
          <url-pattern>/*url-pattern>
      filter-mapping>
      

      七、删除员工

      1、控制器方法

      /**
       * 根据id删除对应的员工数据
       * @return 删除是否成功
       */
      @RequestMapping(value = "/emp/{id}", method = RequestMethod.DELETE)
      @ResponseBody
      public Msg deleteEmp(@PathVariable("id")String id) {
          String[] ids = id.split("-");
          List<Integer> idList = new ArrayList<>();
          for (String s : ids) {
              idList.add(Integer.valueOf(s));
          }
          if (idList.size() == 1) {
              employeeService.deleteEmpById(idList.get(0));
          } else {
              employeeService.deleteBatch(idList);
          }
          return Msg.success();
      }
      

      2、Srevice方法

      删除单个员工

      /**
       * 根据id删除员工
       * @param id 页面传入的id
       */
      public void deleteEmpById(Integer id) {
          employeeMapper.deleteByPrimaryKey(id);
      }
      

      删除多个员工

      /**
       * 删除对应列表里id的员工
       * @param idList id列表
       */
      public void deleteBatch(List<Integer> idList) {
          EmployeeExample employeeExample = new EmployeeExample();
          EmployeeExample.Criteria criteria = employeeExample.createCriteria();
          criteria.andEmpIdIn(idList);
          employeeMapper.deleteByExample(employeeExample);
      }
      

      3. 添加选择按钮

      全选按钮:

      <tr>
          <th>
              <input type="checkbox" id="check_all"/>
          th>
          <th>#th>
          <th>empNameth>
          <th>genderth>
          <th>emailth>
          <th>deptNameth>
          <th>操作th>
      tr>
      

      选项按钮:

      $.each(emps, function (index, item) {
          var checkBoxTd = $("")
          var empIdTd = $("").append(item.empId);
          var empNameTd = $("").append(item.empName)
          var genderTd = $("").append(item.empGender == "M" ? "男" : "女")
          var emailTd = $("").append(item.empEmail)
          var deptNameTd = $("").append(item.department.deptName)
      
          // 注入按钮数据
          var editBtn = $("").addClass("btn btn-primary btn-sm edit_btn")
              .append($("").addClass("glyphicon glyphicon-pencil"))
              .append("编辑");
          // 添加自定义属性,用于修改员工时传递id值
          editBtn.attr("empId_for_edit", item.empId)
          var delBtn = $("").addClass("btn btn-danger btn-sm del_btn")
              .append($("").addClass("glyphicon glyphicon-trash"))
              .append("删除");
      
          var btnTd = $("").append(editBtn).append(" ").append(delBtn);
          $("").append(checkBoxTd)
              .append(empIdTd)
              .append(empNameTd)
              .append(genderTd)
              .append(emailTd)
              .append(deptNameTd)
              .append(btnTd)
              .appendTo("#emps_table tbody");
      });
      

      4、绑定选择按钮事件

      全选按钮绑定事件

      // 全选按钮绑定事件
      $("#check_all").click(function () {
          // attr获取checked属性时undefined
          // dom原生的属性需要用prop获取,attr获取自定义的属性
          $(".check_item").prop("checked", $(this).prop("checked"))
      })
      

      选项按钮绑定事件

      // 选项按钮绑定事件,当所有按钮被选中时,同时选中全选按钮
      $(document).on("click", ".check_item", function () {
          var flag = $(".check_item:checked").length === $(".check_item").length
          $("#check_all").prop("checked", flag)
      })
      

      4、删除单个员工按钮事件

      // 单个删除按钮事件
      $(document).on("click", ".del_btn", function (){
          var empName = $(this).parents("tr").find("td:eq(2)").text()
          var empId = $(this).parents("tr").find("td:eq(1)").text()
          if(confirm("确认删除【" + empName + "】吗?")) {
              // 确认则发送Ajax请求
              $.ajax({
                  url:"${APP_PATH}/emp/" + empId,
                  type:"DELETE",
                  success:function (result) {
                      console.log(result)
                      // 刷新页面
                      to_page(currentPage)
                  }
              })
          }
      })
      

      5、删除全部员工按钮事件

      添加删除所有员工按钮id

      <button class="btn btn-danger" id="delete_all_emp_btn">
          <span class="glyphicon glyphicon-trash" aria-hidden="true">span>删除
      button>
      

      绑定按钮事件

      // 删除全部选中员工按钮事件
      $("#delete_all_emp_btn").click(function () {
          var empIds = ""
          alert("dqwdfa")
          $.each($(".check_item:checked"), function () {
              empIds += $(this).parents("tr").find("td:eq(1)").text() + "-"
          })
          // 删除最后一个 "-"
          empIds.substring(0, empIds.length-1)
          if(confirm("确认删除所有员工吗?")) {
              $.ajax({
                  url:"${APP_PATH}/emp/" + empIds,
                  type:"DELETE",
                  success:function (result) {
                      console.log(result)
                      to_page(currentPage)
                      // 重置全选按钮为未选中状态
                      $("#check_all").prop("checked", false)
                  }
              })
          }
      })
      

      九、最终index页面

      <%@ page language="java" contentType="text/html; charset=UTF-8"
               pageEncoding="UTF-8" %>
      <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
      <html>
      <head>
          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
          <title>员工列表</title>
          <%
              pageContext.setAttribute("APP_PATH", request.getContextPath());
          %>
          <!-- web路径:
          不以/开始的相对路径,找资源,以当前资源的路径为基准,经常容易出问题。
          以/开始的相对路径,找资源,以服务器的路径为标准(http://localhost:3306);需要加上项目名
                  http://localhost:3306/crud
           -->
          <script type="text/javascript" src="${APP_PATH}/static/js/jquery-1.12.4.min.js"></script>
          <script src="${APP_PATH }/static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
          <link href="${APP_PATH}/static/bootstrap-3.4.1-dist/css/bootstrap.min.css" rel="stylesheet">
      </head>
      <body>
      <%-- 添加员工模态框 --%>
      <div class="modal fade" id="empAddModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
          <div class="modal-dialog" role="document">
              <div class="modal-content">
                  <div class="modal-header">
                      <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
                      </button>
                      <h4 class="modal-title" id="myModalLabel">添加员工</h4>
                  </div>
                  <div class="modal-body">
                      <%-- 表单 --%>
                      <form class="form-horizontal">
                          <div class="form-group">
                              <label for="empName_add_input" class="col-sm-2 control-label">empName</label>
                              <div class="col-sm-10">
                                  <input name="empName" type="text" class="form-control" id="empName_add_input"
                                         placeholder="empName">
                                  <span class="help-block"></span>
                              </div>
                          </div>
                          <div class="form-group">
                              <label for="empEmail_add_input" class="col-sm-2 control-label">Email</label>
                              <div class="col-sm-10">
                                  <input name="empEmail" type="text" class="form-control" id="empEmail_add_input"
                                         placeholder="empEmail">
                                  <span class="help-block"></span>
                              </div>
                          </div>
                          <div class="form-group">
                              <label class="col-sm-2 control-label">empGender</label>
                              <div class="col-sm-10">
                                  <label class="radio-inline">
                                      <input type="radio" name="empGender" id="empGender_add_input" value="M" checked="checked"></label>
                                  <label class="radio-inline">
                                      <input type="radio" name="empGender" id="empGender_add_input2" value="F"></label>
                              </div>
                          </div>
                          <div class="form-group">
                              <label class="col-sm-2 control-label">deptId</label>
                              <div class="col-sm-4">
                                  <select class="form-control" name="deptId" id="deptId_add_select">
                                  </select>
                              </div>
                          </div>
                      </form>
                  </div>
                  <div class="modal-footer">
                      <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                      <button type="button" class="btn btn-primary" id="saveEmpBtn">保存</button>
                  </div>
              </div>
          </div>
      </div>
      
      <%-- 修改员工模态框 --%>
      <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" id="updateModalLabel">修改员工</h4>
                  </div>
                  <div class="modal-body">
                      <%-- 表单 --%>
                      <form class="form-horizontal">
                          <div class="form-group">
                              <label for="empName_add_input" class="col-sm-2 control-label">empName</label>
                              <div class="col-sm-10">
                                  <input name="empName" type="text" class="form-control" id="empName_update_input"
                                         placeholder="empName">
                                  <span class="help-block"></span>
                              </div>
                          </div>
                          <div class="form-group">
                              <label for="empEmail_add_input" class="col-sm-2 control-label">Email</label>
                              <div class="col-sm-10">
                                  <input name="empEmail" type="text" class="form-control" id="empEmail_update_input"
                                         placeholder="empEmail">
                                  <span class="help-block"></span>
                              </div>
                          </div>
                          <div class="form-group">
                              <label class="col-sm-2 control-label">empGender</label>
                              <div class="col-sm-10">
                                  <label class="radio-inline">
                                      <input type="radio" name="empGender" id="empGender_update_input" value="M" checked="checked"></label>
                                  <label class="radio-inline">
                                      <input type="radio" name="empGender" id="empGender_update_input2" value="F"></label>
                              </div>
                          </div>
                          <div class="form-group">
                              <label class="col-sm-2 control-label">deptId</label>
                              <div class="col-sm-4">
                                  <select class="form-control" name="deptId" id="deptId_update_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="updateEmpBtn">更新</button>
                  </div>
              </div>
          </div>
      </div>
      
      <%-- 搭建显示页面 --%>
      <div class="container">
          <%-- 标题 --%>
          <div class="row">
              <div class="col-md-12">
                  <h1>SSM_CRUD</h1>
              </div>
          </div>
          <%-- 按钮 --%>
          <div class="row">
              <div class="col-md-2 col-md-offset-10">
                  <button class="btn btn-primary" id="emp_add_modal_btn">
                      <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>添加
                  </button>
                  <button class="btn btn-danger" id="delete_all_emp_btn">
                      <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>删除
                  </button>
              </div>
          </div>
          <%-- 显示表格数据 --%>
          <div class="row">
              <div class="col-md-12">
                  <table class="table table-striped" id="emps_table">
                      <thead>
                      <tr>
                          <th>
                              <input type="checkbox" id="check_all"/>
                          </th>
                          <th>#</th>
                          <th>empName</th>
                          <th>gender</th>
                          <th>email</th>
                          <th>deptName</th>
                          <th>操作</th>
                      </tr>
                      </thead>
                      <tbody>
                      <%-- 通过函数加载数据 --%>
                      </tbody>
                  </table>
              </div>
          </div>
          <%-- 显示分页信息 --%>
          <div class="row">
              <%--分页条信息--%>
              <div class="col-md-6 col-md-offset-3 text-center" id="page_info_area"></div>
          </div>
          <div class="row">
              <%--分页文字信息 --%>
              <div class="col-md-6 col-md-offset-3 text-center" id="page_nav_area"></div>
          </div>
      
      </div>
      <script type="text/javascript">
          /* ================================================ 全局变量 ================================================ */
      
          var totalRecord; // 用于跳转到末页
          var currentPage // 用于完成请求后刷新页面
      
          /* ================================================ 函数 ================================================ */
          // 初始化页面时需要调用的函数
          $(function () {
              // 去首页
              to_page(1);
          });
      
          // 页面跳转函数
          function to_page(pn) {
              $.ajax({
                  url: "${APP_PATH}/emps",
                  data: "pn=" + pn,
                  type: "GET",
                  success: function (result) {
                      // 1.解析员工数据
                      build_emps_table(result);
                      // 2. 解析并显示分页信息
                      build_page_info(result);
                      // 3. 解析显示分页条码
                      build_page_nav(result);
                  }
              });
          }
      
          // 解析表格数据函数
          function build_emps_table(result) {
              // 清空表格信息
              $("#emps_table tbody").empty()
              // 获取员工列表
              var emps = result.extend.pageInfo.list;
              // 遍历员工列表,构建表格
              $.each(emps, function (index, item) {
                  var checkBoxTd = $("")
                  var empIdTd = $("").append(item.empId);
                  var empNameTd = $("").append(item.empName)
                  var genderTd = $("").append(item.empGender == "M" ? "男" : "女")
                  var emailTd = $("").append(item.empEmail)
                  var deptNameTd = $("").append(item.department.deptName)
      
                  // 注入按钮数据
                  var editBtn = $("").addClass("btn btn-primary btn-sm edit_btn")
                      .append($("").addClass("glyphicon glyphicon-pencil"))
                      .append("编辑");
                  // 添加自定义属性,用于修改员工时传递id值
                  editBtn.attr("empId_for_edit", item.empId)
                  var delBtn = $("").addClass("btn btn-danger btn-sm del_btn")
                      .append($("").addClass("glyphicon glyphicon-trash"))
                      .append("删除");
      
                  var btnTd = $("").append(editBtn).append(" ").append(delBtn);
                  $("").append(checkBoxTd)
                      .append(empIdTd)
                      .append(empNameTd)
                      .append(genderTd)
                      .append(emailTd)
                      .append(deptNameTd)
                      .append(btnTd)
                      .appendTo("#emps_table tbody");
              });
          }
      
          // 解析显示分页信息函数
          function build_page_info(result) {
              // 清空原来的分页信息
              $("#page_info_area").empty()
              $("#page_info_area").append("当前页:" +
                  result.extend.pageInfo.pageNum + ",总页数:" +
                  result.extend.pageInfo.pages + ",总记录数:" +
                  result.extend.pageInfo.total)
              totalRecord = result.extend.pageInfo.total
              currentPage = result.extend.pageInfo.pageNum
          }
      
          // 解析显示分页条函数
          function build_page_nav(result) {
              // 清空原来的分页码
              $("#page_nav_area").empty();
              // 构建元素
              var ul = $("
        "
        ).addClass("pagination") var firstPageLi = $("
      • "
        ).append($("").append("首页").attr("href", "#")); var prePageLi = $("
      • "
        ).append($("").append("«").attr("href", "#")); var nextPageLi = $("
      • "
        ).append($("").append("»").attr("href", "#")); var lastPageLi = $("
      • "
        ).append($("").append("末页").attr("href", "#")); // 添加首页、末页、上一页、下一页禁用 和跳转功能 if (result.extend.pageInfo.hasPreviousPage == false) { firstPageLi.addClass("disabled") prePageLi.addClass("disabled") } else { firstPageLi.click(function () { to_page(1) }) prePageLi.click(function () { to_page(result.extend.pageInfo.pageNum - 1) }) } if (result.extend.pageInfo.hasNextPage == false) { nextPageLi.addClass("disabled"); lastPageLi.addClass("disabled"); } else { lastPageLi.click(function () { to_page(result.extend.pageInfo.pages); }); nextPageLi.click(function () { to_page(result.extend.pageInfo.pageNum + 1); }); } // 添加首页和前一页 ul.append(firstPageLi).append(prePageLi) // 构建条码 $.each(result.extend.pageInfo.navigatepageNums, function (index, num) { var numLi = $("
      • "
        ).append($("").append(num).attr("href", "#")); // 设置当前页码高亮显示 if (result.extend.pageInfo.pageNum == num) { numLi.addClass("active") } // 添加按钮跳转事件 numLi.click(function () { to_page(num) }) ul.append(numLi) }); // 添加末页和后一页 ul.append(nextPageLi).append(lastPageLi) var navEle = $("").append(ul) navEle.appendTo("#page_nav_area"); } // 查询所有部门信息请求函数 function getDepts(ele) { $.ajax({ url: "${APP_PATH}/depts", type: "GET", success: function (result) { console.log(result) $.each(result.extend.depts, function () { var optionElement = $("").append(this.deptName).attr("value", this.deptId) optionElement.appendTo(ele) }) } }) } // 添加员工表单数据校验信息显示函数 function validate_add_from_information_show(ele, status, msg) { // 清楚当前元素的校验状态 $(ele).parent().removeClass("has-success has-error") $(ele).next("span").text("") if("success" == status){ $(ele).parent().addClass("has-success") $(ele).next("span").text(msg) } else if ("error" == status) { $(ele).parent().addClass("has-error") $(ele).next("span").text(msg) } } // 重置添加员工表单数据和样式 function reset_form(ele) { // 清空表单数据 $(ele + " form")[0].reset() // 清空表单样式 $(ele + " form").find("*").removeClass("has-success has-error") $(ele + " form").find(".help-block").text("") // 清空下拉列表 $(ele + " select").empty() } // 根据id查询员工信息函数 function getEmpById(id) { $.ajax({ url:"${APP_PATH}/emp/" + id, type:"GET", success:function (result) { var empData = result.extend.emp; console.log(result) $("#empName_update_input").val(empData.empName); $("#empEmail_update_input").val(empData.empEmail); $("#empUpdateModal input[name=empGender]").val(empData.empGender); $("#empUpdateModal select").val(empData.deptId); } }) } // 校验用户名函数 function verifyUsername(ele) { var empName = $(ele).val(); var regName = /(^[a-zA-Z0-9_-]{3,16}$)|(^[\u2E80-\u9FFF]{2,5})/ // 允许英文和中文 if(!regName.test(empName)){ validate_add_from_information_show(ele, "error", "员工名称格式不正确") return false } else { validate_add_from_information_show(ele, "success", "") return true } } // 校验邮箱格式函数 function checkMailbox(ele) { var empEmail = $(ele).val() var regEmail = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/ if(!regEmail.test(empEmail)){ validate_add_from_information_show(ele, "error", "邮箱格式不正确") return false } var isTheEmailAddressCorrect = false // 发送Ajax请求判断邮箱是否重复 $.ajax({ url:"${APP_PATH}/checkEmail", data:"empEmail=" + empEmail, type:"GET", // get请求不检验中文,如果发送对象中含中文则用POST async:false, // 设置Ajax为同步 success:function (result) { console.log(result) if(result.code === 100 && regEmail.test(empEmail)) { validate_add_from_information_show(ele, "success", "") isTheEmailAddressCorrect = true } else if (result.code === 200) { validate_add_from_information_show(ele, "error", "邮箱已存在") isTheEmailAddressCorrect = false } } }) return isTheEmailAddressCorrect; } /* ============================================== 按钮绑定事件区 ============================================== */ // 添加员工按钮事件 $("#emp_add_modal_btn").click(function () { // 表单重置数据 reset_form("#empAddModal") // 发送Ajax请求, 查出部门信息,显示在下拉列表中 getDepts("#deptId_add_select") $("#empAddModal").modal({ backdrop: "static" }) }) // 模态框保存按钮点击事件 $("#saveEmpBtn").click(function () { // 校验表单数据 if (!verifyUsername("#empName_add_input") || !checkMailbox("#empEmail_add_input")) { return false } // 发送保存请求 $.ajax({ url: "${APP_PATH}/emp", type: "POST", data: $("#empAddModal form").serialize(), success: function (result) { console.log(result) if(result.code === 100) { // 员工保存成功 // 1. 关闭模态框 $("#empAddModal").modal('hide') // 2. 跳转到最后一页显示 to_page(totalRecord) } else { // 显示失败信息 if(undefined !== result.extend.errorFields.empEmail){ validate_add_from_information_show("#empEmail_add_input", "error", "邮箱格式不正确") } if(undefined !== result.extend.errorFields.empName){ validate_add_from_information_show("#empName_add_input", "error", "员工名称格式不正确") } } } }) }) // 为修改员工按钮添加事件 // 因为是先绑定事件后在生成的按钮,所以不能用click // 早先版本的jQuery可以使用live方法 // 这里使用 on 方法绑定 $(document).on("click", ".edit_btn", function () { // 1. 查询部门信息显示 getDepts("#deptId_update_select") // 2. 回显员工信息 getEmpById($(this).attr("empId_for_edit")) // 3. 传递id給更新按钮 $("#updateEmpBtn").attr("empId_for_edit", $(this).attr("empId_for_edit")) // 4. 跳出模态框 $("#empUpdateModal").modal({ backdrop: "static" }) }) // 绑定更新按钮单击事件 $("#updateEmpBtn").click(function () { // 1. 校验表单数据 if (!verifyUsername("#empName_update_input") || !checkMailbox("#empEmail_update_input")) { return false } // 2. 发送更新的Ajax请求 $.ajax({ url:"${APP_PATH}/emp/" + $(this).attr("empId_for_edit"), type:"PUT", data:$("#empUpdateModal form").serialize(), success:function (result) { console.log(result) if(result.code === 100) { // 员工更新成功 // 1. 关闭模态框 $("#empUpdateModal").modal('hide') // 2. 刷新页面 to_page(currentPage) } else { // 显示失败信息 if(undefined !== result.extend.errorFields.empEmail){ validate_add_from_information_show("#empEmail_update_input", "error", "邮箱格式不正确") } if(undefined !== result.extend.errorFields.empName){ validate_add_from_information_show("#empName_update_input", "error", "员工名称格式不正确") } } } }) }) // 单个删除按钮事件 $(document).on("click", ".del_btn", function (){ var empName = $(this).parents("tr").find("td:eq(2)").text() var empId = $(this).parents("tr").find("td:eq(1)").text() if(confirm("确认删除【" + empName + "】吗?")) { // 确认则发送Ajax请求 $.ajax({ url:"${APP_PATH}/emp/" + empId, type:"DELETE", success:function (result) { console.log(result) // 刷新页面 to_page(currentPage) } }) } }) // 全选按钮绑定事件 $("#check_all").click(function () { // attr获取checked属性时undefined // dom原生的属性需要用prop获取,attr获取自定义的属性 $(".check_item").prop("checked", $(this).prop("checked")) }) // 选项按钮绑定事件,当所有按钮被选中时,同时选中全选按钮 $(document).on("click", ".check_item", function () { var flag = $(".check_item:checked").length === $(".check_item").length $("#check_all").prop("checked", flag) }) // 删除全部选中员工按钮事件 $("#delete_all_emp_btn").click(function () { var empIds = "" $.each($(".check_item:checked"), function () { empIds += $(this).parents("tr").find("td:eq(1)").text() + "-" }) // 删除最后一个 "-" empIds.substring(0, empIds.length-1) if(confirm("确认删除所有员工吗?")) { $.ajax({ url:"${APP_PATH}/emp/" + empIds, type:"DELETE", success:function (result) { console.log(result) to_page(currentPage) // 重置全选按钮为未选中状态 $("#check_all").prop("checked", false) } }) } }) </script> </body> </html>

        你可能感兴趣的:(spring,java,bootstrap,前端)