项目简介
使用 SSM 框架搭建出一套简单的 CRUD 项目示例,主要涉及两张表:员工表和部门表,其中每个员工都对应一个部门
主要实现的功能
1、分页查询所有员工信息并展示列表。
2、添加一条员工的信息。
3、新增数据需要校验:
- jQuery 前端校验用户名和邮箱是否合法。
- Ajax 请求校验用户名是否重复。
- JSR 303 后端校验用户名、邮箱是否合法以及用户名是否重复。
4、编辑修改某条员工的信息。
5、删除某条员工的信息,批量删除所选员工的信息。
6、RESTful 风格的URI。
涉及的技术
1、后端框架:SSM(Spring 5 + Spring MVC + MyBatis 3)+ Maven 3.6.3
2、MyBatis 分页插件:PageHelper
3、MyBatis 逆向工程:MyBatis Generator
4、数据库:MySQL 5.7 + Druid 数据库连接池
5、前端框架:BootStrap 5
最终效果图
一、搭建环境
1. 添加依赖,打包方式为 war
<packaging>war</packaging>
<!--引入项目依赖的jar包 -->
<!-- SpringMVC、Spring -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependencies>
<!--引入pageHelper分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.0</version>
</dependency>
<!-- MBG -->
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- 返回json字符串的支持 -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.8</version>
</dependency>
<!--JSR303数据校验支持;tomcat7及以上的服务器,
tomcat7以下的服务器:el表达式。额外给服务器的lib包中替换新的标准的el
-->
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.1.Final</version>
</dependency>
<!-- Spring-Jdbc -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!--Spring-test -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- Spring面向切面编程 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!--MyBatis -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- MyBatis整合Spring的适配包 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!--druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
<!-- (jstl,servlet-api,junit) -->
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<!--引入jsp-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!-- junit -->
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<!--逆向工程的插件-->
<!-- 控制Maven在构建过程中相关配置 -->
<build>
<!-- 构建过程中用到的插件 -->
<plugins>
<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.0</version>
<!-- 插件的依赖 -->
<dependencies>
<!-- 逆向工程的核心依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.7</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
2. 创建webapp目录,添加web.xml
注意路径:\src\main\webapp\web.xml
3. 配置tomcat服务器
4. 引入 BootStrap 前端框架
Bootstrap 官网:https://getbootstrap.com/,图标资源官网:https://icons.getbootstrap.com/
中文第3版Bootstrap的学习资料:https://v3.bootcss.com/getting-started/
5. 引入jquery
二、整合SSM
1. 配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!--指定Spring配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application.xml</param-value>
</context-param>
<!--该监听器将根据contextConfigLocation参数加载Spring配置文件, 初始化Spring应用上下文-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--过滤器-->
<!--配置字符编码过滤器,一定要放在所有过滤器之前,/* 表示拦截所有请求-->
<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>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置HTTP方法过滤器, 实现REST风格的增删改查 -->
<!-- 该过滤器根据指定的请求参数(默认是"_method")来修改请求的类型 -->
<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>
<!--HttpPutFormContentFilter过滤器会自动的封装前台传递过来的PUT请求的参数-->
<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>
<!--2、配置 Spring MVC 的前端控制器,拦截所有请求-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--指定SpringMVC的配置文件-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!--随着tomcat的启动-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2. 配置application.xml
Spring 的配置文件,主要配置业务逻辑相关的内容:数据源、与MyBatis的整合、事务控制等。
(1)先创建一个 dbconfig.properties,用来保存数据库驱动的配置信息
jdbc.url=jdbc:mysql://localhost:3306/ssm_crud
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=123456
(2)在配置文件中进行配置
<?xml version="1.0" encoding="UTF-8"?>
<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 http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--1、配置扫描包,不扫描controller-->
<context:component-scan base-package="com.study.ssm">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--2、引入数据库驱动的properties文件-->
<context:property-placeholder location="classpath:dbconfig.properties"/>
<!--3、配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.url}"></property>
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--4、与 MyBatis 的整合配置-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--指定数据源-->
<property name="dataSource" ref="dataSource"></property>
<!--指定 MyBatis 全局配置文件的位置-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--指定 MyBatis 映射文件的位置-->
<property name="mapperLocations" value="classpath:com/study/ssm/dao/*.xml"></property>
</bean>
<!--配置一个可以执行批量操作的 sqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
<constructor-arg name="executorType" value="BATCH"></constructor-arg>
</bean>
<!--配置扫描器,将 MyBatis 接口的实现加入到 IOC 容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--扫描所有的 DAO 接口的实现,加入到 IOC 容器中-->
<property name="basePackage" value="com.study.ssm.dao"></property>
</bean>
<!--4、事务控制-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--指定数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启基于注解的事务,使用 XML 配置形式的事务(比较主要的事务都用配置式)-->
<aop:config>
<!--切入点表达式-->
<aop:pointcut id="txPoint" expression="execution(* com.study.ssm.service..*(..))"/>
<!--配置事务增强-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"></aop:advisor>
</aop:config>
<!--配置事务增强,事务如何增强-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
* 代表所有方法都是事务方法
get* 代表以get开始的所有方法
-->
<tx:method name="*"/>
<tx:method name="get*" read-only="true"/>
</tx:attributes>
</tx:advice>
</beans>
3. 配置spring-mvc.xml
Spring MVC 的配置文件,主要包含网站跳转逻辑的控制、配置。
<?xml version="1.0" encoding="UTF-8"?>
<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 http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Spring MVC 的配置文件,主要包含网站跳转逻辑的控制、配置-->
<context:component-scan base-package="com.study.ssm" 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/js/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--将 Spring MVC 不能处理的请求交给 tomcat 处理-->
<mvc:default-servlet-handler/>
<!-- 开启mvc注解驱动 -->
<!--能支持 Spring MVC 更高级的一些功能,比如 JSR 303 校验、快捷的 Ajax 映射动态请求等-->
<mvc:annotation-driven/>
</beans>
4. 配置mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!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"/>
</settings>
<typeAliases>
<!--给Java Bean起别名-->
<package name="com.study.ssm.bean"/>
</typeAliases>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--分页查询合理化-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
</configuration>
5. 创建数据库表
CREATE TABLE `tbl_emp` (
`emp_id` int(11) PRIMARY KEY AUTO_INCREMENT NOT NULL ,
`emp_name` varchar(255) DEFAULT NULL,
`gender` char(1) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`d_id` int(11) DEFAULT NULL,
FOREIGN KEY (d_id) REFERENCES tbl_dept(dept_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `tbl_dept` (
`dept_id` int(11) PRIMARY KEY AUTO_INCREMENT NOT NULL,
`dept_name` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6. Mybatis 逆向工程
(1)配置 generatorConfig.xml 逆向工程配置文件(必须叫这名)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--targetRuntime设置生成的模式-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!--阻止注释的生成-->
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!-- 配置数据库连接 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/ssm_crud" userId="root"
password="123456">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 指定javaBean生成的位置 -->
<javaModelGenerator targetPackage="com.study.ssm.bean"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!--指定sql映射文件生成的位置 -->
<!-- <sqlMapGenerator> 的 targetPackage属性 最好与 <javaClientGenerator> 的targetPackage属性一致-->
<sqlMapGenerator targetPackage="com/study/ssm/dao" targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- 指定dao接口生成的位置,mapper接口 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.study.ssm.dao" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- table指定每个表的生成策略 -->
<table tableName="tbl_emp" domainObjectName="Employee"></table>
<table tableName="tbl_dept" domainObjectName="Department"></table>
</context>
</generatorConfiguration>
(2)使用逆向工程插件
7. 项目完整的结构
修改 Employee 类,添加部门属性
...
private Department department;
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 +
'}';
}
...
修改 EmployeeMapper 接口,增加下面内容
...
//带上部门查询的条件查询
List<Employee> selectByExampleWithDept(EmployeeExample example);
//带上部门的主键查询
Employee selectByPrimaryKeyWithDept(Integer empId);
...
修改 EmployeeMapper.xml,增加下面内容
<!--新增的带有部门信息的返回结果集-->
<resultMap id="WithDeptResultMap" type="com.study.ssm.bean.Employee">
<id column="emp_id" jdbcType="INTEGER" property="empId" />
<result column="emp_name" jdbcType="VARCHAR" property="empName" />
<result column="gender" jdbcType="CHAR" property="gender" />
<result column="email" jdbcType="VARCHAR" property="email" />
<result column="d_id" jdbcType="INTEGER" property="dId" />
<association property="department" javaType="com.study.ssm.bean.Department">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
</association>
</resultMap>
<!--带部门列的sql-->
<sql id="WithDept_Column_List">
e.emp_id, e.emp_name, e.gender, e.email, e.d_id, d.dept_id, d.dept_name
</sql>
<!--List<Employee> selectByExampleWithDept(EmployeeExample example);-->
<!--新增的带部门查询-->
<select id="selectByExampleWithDept"
parameterType="com.study.ssm.bean.EmployeeExample"
resultMap="WithDeptResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="WithDept_Column_List" />
from tbl_emp e left join tbl_dept d on e.d_id=d.dept_id
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<!--Employee selectByPrimaryKeyWithDept(Integer empId);-->
<select id="selectByPrimaryKeyWithDept"
parameterType="java.lang.Integer"
resultMap="WithDeptResultMap">
select
<include refid="WithDept_Column_List" />
from tbl_emp e left join tbl_dept d on e.d_id=d.dept_id
where emp_id = #{empId,jdbcType=INTEGER}
</select>
8. Spring 整合 Junit 4测试 Mapper 添加数据
/**
* 推荐Spring的项目就可以使用Spring的单元测试,可以自动注入我们需要的组件
* 1、导入SpringTest模块
* 2、@ContextConfiguration指定Spring配置文件的位置
* 3、直接autowired要使用的组件即可
*/
//指定单元测试类型
@RunWith(SpringJUnit4ClassRunner.class)
//指定配置文件
@ContextConfiguration(locations = {"classpath:application.xml"})
public class MapperTest {
@Autowired
DepartmentMapper departmentMapper;
@Autowired
EmployeeMapper employeeMapper;
@Autowired
SqlSession sqlSession;
@Test
public void testCRUD() {
System.out.println(departmentMapper);
//1.插入几个部门
departmentMapper.insertSelective(new Department(null, "开发部"));
departmentMapper.insertSelective(new Department(null, "测试部"));
//插入一条员工数据
employeeMapper.insertSelective(new Employee(null, "张三", "M", "zhangsan@qq.com", 1));
employeeMapper.insertSelective(new Employee(null, "李四", "M", "lisi@163.com", 1));
employeeMapper.insertSelective(new Employee(null, "王五", "M", "wangwu@sina.com", 1));
//批量插入员工数据
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, "W", uid + "@gmail.com", 2));
}
}
}
三、规定RESTful 风格的URI
URI | 请求方式 | 功能 |
---|---|---|
/emps | GET | 获取所有员工信息 |
/emp | POST | 保存新增用户信息 |
/checkEmp | GET | 检查用户是否重名 |
/emp/{id} | GET | 根据id获取用户信息 |
/emp/{empId} | PUT | 保存修改用户信息 |
/emp/{empId} | DELETE | 删除用户 |
四、创建index.jsp
基本的骨架搭建
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<%--得到工程路径--%>
<% pageContext.setAttribute("APP_PATH", request.getContextPath()); %>
<%--引入js文件--%>
<script src="${APP_PATH}/static/js/jquery-1.12.4.min.js"></script>
<%--引入bootstrap--%>
<script src="${APP_PATH}/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
<link href="${APP_PATH}/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
<title>首页</title>
</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-primary" id="emp_add_modal_btn">新增</button>
<button class="btn btn-danger" id="emp_delete_all_btn">删除</button>
</div>
</div>
<!-- 显示表格数据 -->
<div class="row">
<div class="col-md-12">
<table class="table table-hover" 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" id="page_info_area"></div>
<!-- 分页条信息 -->
<div class="col-md-6" id="page_nav_area">
</div>
</div>
<script type="text/javascript">
// 完善前端代码...
</script>
</div>
</body>
</html>
五、查询
1. 需要实现的功能
(1)第一步,用 JSTL 实现(URI:/emps):
- 访问 index.jsp 页面。
- index.jsp 发送出查询员工列表的请求。
- EmployeeController 接收请求,查出员工的数据。
- 来到 list.jsp 页面进行展示。
- 使用 PageHelper 分页插件完成分页查询的功能。
(2)第二步,用 Ajax 实现:
- index.jsp 页面直接发送 Ajax 请求,进行员工分页数据的查询。
- 服务器将查出来的数据,通过 JSON 字符串的形式返回给浏览器。
- 浏览器收到 JSON 字符串后,用 JS 对JSON 解析,通过 DOM 增删改查页面。
- 返回 JSON,实现客户端的无关性。
2. controller
@Controller
public class EmployeeController {
@Autowired
EmployeeService employeeService;
@RequestMapping("/emps")
public String getEmps(
@RequestParam(value = "pn", defaultValue = "1") Integer pn,
Model model) {
// 这不是一个分页查询;
// 引入PageHelper分页插件
// 在查询之前只需要调用,传入页码,以及每页的大小
PageHelper.startPage(pn, 5);
// startPage后面紧跟的这个查询就是一个分页查询
List<Employee> emps = employeeService.getAll();
// 使用pageInfo包装查询后的结果,只需要将pageInfo交给页面就行了。
// 封装了详细的分页信息,包括有我们查询出来的数据,传入连续显示的页数
PageInfo page = new PageInfo(emps, 5);
model.addAttribute("pageInfo", page);
return "list";
}
}
3. service
@Service
public class EmployeeService {
@Autowired
EmployeeMapper employeeMapper;
public List<Employee> getAllEmps() {
EmployeeExample example = new EmployeeExample();
example.setOrderByClause("emp_id");
return employeeMapper.selectByExampleWithDept(example);
}
}
4. spring 整合 Junit 4测试 MVC
/**
* 使用Spring测试模块提供的测试请求功能,测试curd请求的正确性
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration()
@ContextConfiguration(locations = {"classpath:applicationContext.xml", "classpath:Spring-mvc.xml"})
public class MvcTest {
// 传入Springmvc的ioc
@Autowired
WebApplicationContext context;
// 虚拟mvc请求,获取到处理结果。
MockMvc mockMvc;
@Before
public void initMokcMvc() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void testPage() throws Exception {
//模拟请求拿到返回值
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/emps").param("pn", "1"))
.andReturn();
//请求成功以后,请求域中会有pageInfo;我们可以取出pageInfo进行验证
MockHttpServletRequest request = result.getRequest();
PageInfo pi = (PageInfo) request.getAttribute("pageInfo");
System.out.println("当前页码:" + pi.getPageNum());
System.out.println("总页码:" + pi.getPages());
System.out.println("总记录数:" + pi.getTotal());
System.out.println("在页面需要连续显示的页码");
int[] nums = pi.getNavigatepageNums();
for (int i : nums) {
System.out.print(" " + i);
}
System.out.println();
//获取员工数据
List<Employee> list = pi.getList();
for (Employee employee : list) {
System.out.println("ID:" + employee.getEmpId() + "==>Name:" + employee.getEmpName());
}
}
}
5. 添加 Msg 类引入链式编程
public class Msg {
private String code;
private String msg;
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;
}
...
}
6. 修改 controller
修改为使用 JSON 格式传输数据,需要 Jackson 的依赖。
@ResponseBody
@RequestMapping(value = "/emps", method = RequestMethod.GET)
public Msg getEmpsWithJson(@RequestParam(value = "pn", defaultValue = "1") Integer pn) {
PageHelper.startPage(pn, 5);
List<Employee> emps = employeeService.getAllEmps();
PageInfo pageInfo = new PageInfo(emps, 5);
return Msg.success().add("pageInfo", pageInfo);
}
7. 补充前端代码,采用Ajax发送请求
在<script type="text/javascript">
中补充
//总记录数
var totalRecord;
//1、页面加载完成以后,直接去发送一个ajax请求,要到分页数据
$(function () {
to_page(1);
});
function to_page(pn) {
$.ajax({
url: "${APP_PATH}/emps",
data: "pn=" + pn,
type: "GET",
success: function (result) {
//console.log(result);
//1、解析并显示员工数据
build_emps_table(result);
//2、解析并显示分页信息
build_page_info(result);
//3、解析显示分页条数据
build_page_nav(result);
}
});
}
// 表格
function build_emps_table(result) {
//清空table表格
$("#emps_table tbody").empty();
//获得分页数据
var emps = result.extend.pageInfo.list;
//循环遍历分页数据
$.each(emps, function (index, item) {
//每行数据
var checkBoxTd = $("<td><input type='checkbox' class='check_item'/></td>");
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-primary 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);
//将每行数据以及对应的按钮加入到表格的<tbody>标签中
//append方法执行完成以后还是返回原来的元素
$("<tr></tr>").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 = $("<ul></ul>").addClass("pagination");
//构建元素
//首页,默认进入页面是第一页,不允许点击
var firstPageLi = $("<li></li>").append($("<a></a>").append("首页").attr("href", "#"));
//上一页
var prePageLi = $("<li></li>").append($("<a></a>").append("«"));
//没有上一页,不允许点击
if (result.extend.pageInfo.hasPreviousPage == false) {
//添加不允许点击的样式(css)
firstPageLi.addClass("disabled");
prePageLi.addClass("disabled");
} else {
//为元素添加点击翻页的事件
firstPageLi.click(function () {
to_page(1);
});
prePageLi.click(function () {
to_page(result.extend.pageInfo.pageNum - 1);
});
}
//下一页
var nextPageLi = $("<li></li>").append($("<a></a>").append("»"));
//末页
var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href", "#"));
//如果没有下一页,不允许点击
if (result.extend.pageInfo.hasNextPage == false) {
//添加不允许点击的样式(css)
nextPageLi.addClass("disabled");
lastPageLi.addClass("disabled");
//为元素添加点击翻页的事件
} else {
nextPageLi.click(function () {
to_page(result.extend.pageInfo.pageNum + 1);
});
lastPageLi.click(function () {
to_page(result.extend.pageInfo.pages);
});
}
//添加首页和前一页 的提示
ul.append(firstPageLi).append(prePageLi);
//1,2,3遍历给ul中添加页码提示
//添加页码框
$.each(result.extend.pageInfo.navigatepageNums, function (index, item) {
//为每个页码添加超链接以及显示的内容(即:所在页码)
var numLi = $("<li></li>").append($("<a></a>").append(item));
//页码为当前页码,不允许点击
if (result.extend.pageInfo.pageNum == item) {
//添加不允许点击的样式(css)
numLi.addClass("active");
}
//为元素添加点击翻页的事件
numLi.click(function () {
to_page(item);
});
ul.append(numLi);
});
//添加下一页和末页 的提示
ul.append(nextPageLi).append(lastPageLi);
//把ul加入到nav
var navEle = $("<nav></nav>").append(ul);
//添加到id为page_nav_area的元素中
navEle.appendTo("#page_nav_area");
}
8. 效果
启动服务,直接显示首页:
六、新增数据
1. 需要实现的功能
-
在 index.jsp 页面点击“新增”弹出对话框
-
去数据库中查询部门列表,显示在对话框内
-
对用户输入的数据进行校验
-
- jQuery 前端校验格式
- Ajax 校验用户名是否重复
- 后端校验(JSR 303)
-
保存用户数据
2. 添加模态框
在标签的开头处添加
<!-- 员工添加的模态框 -->
<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 class="col-sm-2 control-label">empName</label>
<div class="col-sm-10">
<input type="text" name="empName" class="form-control" id="empName_add_input" placeholder="empName">
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">email</label>
<div class="col-sm-10">
<input type="text" name="email" class="form-control" id="email_add_input" placeholder="email@atguigu.com">
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">gender</label>
<div class="col-sm-10">
<label class="radio-inline">
<input type="radio" name="gender" id="gender1_add_input" value="M" checked="checked"> 男
</label>
<label class="radio-inline">
<input type="radio" name="gender" id="gender2_add_input" value="F"> 女
</label>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">deptName</label>
<div class="col-sm-4">
<!-- 部门提交部门id即可 -->
<select class="form-control" name="dId">
</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>
3 查询部门列表
Controller
@Controller
public class DepartmentController {
@Autowired
private DepartmentService departmentService;
@ResponseBody
@RequestMapping("/depts")
public Msg getDeptsWithJson() {
List<Department> depts = departmentService.getAllDepts();
return Msg.success().add("depts", depts);
}
}
Service
@Service
public class DepartmentService {
@Autowired
DepartmentMapper departmentMapper;
public List<Department> getAllDepts() {
return departmentMapper.selectByExample(null);
}
}
补充前端代码
//清空表单样式及内容
function reset_form(ele){
$(ele)[0].reset();
//清空表单样式
$(ele).find("*").removeClass("has-error has-success");
$(ele).find(".help-block").text("");
}
//点击新增按钮弹出模态框。
$("#emp_add_modal_btn").click(function(){
//清除表单数据(表单完整重置(表单的数据,表单的样式))
reset_form("#empAddModal form");
//发送ajax请求,查出部门信息,显示在下拉列表中
getDepts("#empAddModal select");
//弹出模态框
$("#empAddModal").modal({
backdrop:"static"
});
});
//查出所有的部门信息并显示在下拉列表中
function getDepts(ele){
//清空之前下拉列表的值
$(ele).empty();
$.ajax({
url:"${APP_PATH}/depts",
type:"GET",
success:function(result){
//{"code":100,"msg":"处理成功!",
//"extend":{"depts":[{"deptId":1,"deptName":"开发部"},{"deptId":2,"deptName":"测试部"}]}}
//console.log(result);
//显示部门信息在下拉列表中
$.each(result.extend.depts,function(){
var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
optionEle.appendTo(ele);
});
}
});
}
4. jQuery 前端校验格式
//校验表单数据
function validate_add_form(){
//1、拿到要校验的数据,使用正则表达式
var empName = $("#empName_add_input").val();
var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/;
if(!regName.test(empName)){
//alert("用户名可以是2-5位中文或者6-16位英文和数字的组合");
show_validate_msg("#empName_add_input", "error", "用户名可以是2-5位中文或者6-16位英文和数字的组合");
return false;
}else{
show_validate_msg("#empName_add_input", "success", "");
};
//2、校验邮箱信息
var email = $("#email_add_input").val();
var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
if(!regEmail.test(email)){
//alert("邮箱格式不正确");
//应该清空这个元素之前的样式
show_validate_msg("#email_add_input", "error", "邮箱格式不正确");
return false;
}else{
show_validate_msg("#email_add_input", "success", "");
}
return true;
}
//显示校验结果的提示信息
function show_validate_msg(ele,status,msg){
//清除当前元素的校验状态
$(ele).parent().removeClass("has-success has-error");
$(ele).next("span").text("");
if("success"==status){
$(ele).parent().addClass("has-success");
$(ele).next("span").text(msg);
}else if("error" == status){
$(ele).parent().addClass("has-error");
$(ele).next("span").text(msg);
}
}
5. Ajax 校验用户名是否重复
Controller
/**
* 检查用户名是否可用
*/
@ResponseBody
@RequestMapping("/checkuser")
public Msg checkuser(@RequestParam("empName") String empName) {
//先判断用户名是否是合法的表达式;
String regx = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})";
if (!empName.matches(regx)) {
return Msg.fail().add("va_msg", "用户名必须是6-16位数字和字母的组合或者2-5位中文");
}
//数据库用户名重复校验
boolean b = employeeService.checkUser(empName);
if (b) {
return Msg.success();
} else {
return Msg.fail().add("va_msg", "用户名不可用");
}
}
Service
public boolean checkEmp(String empName) {
EmployeeExample example = new EmployeeExample();
example.createCriteria().andEmpNameEqualTo(empName);
return employeeMapper.countByExample(example) == 0;
}
补充前端代码
//校验用户名是否可用
$("#empName_add_input").change(function(){
//发送ajax请求校验用户名是否可用
var empName = this.value;
$.ajax({
url:"${APP_PATH}/checkuser",
data:"empName="+empName,
type:"POST",
success:function(result){
if(result.code==100){
show_validate_msg("#empName_add_input","success","用户名可用");
//添加定义属性ajax-va,值为"success"
$("#emp_save_btn").attr("ajax-va","success");
}else{
show_validate_msg("#empName_add_input","error",result.extend.va_msg);
//添加定义属性ajax-va,值为"error"
$("#emp_save_btn").attr("ajax-va","error");
}
}
});
});
6. 后端校验 + 保存
Controller
/**
* 校验用户是否可用
*/
@RequestMapping(value = "/emp", method = RequestMethod.POST)
@ResponseBody
/**
* @Valid: 使用JSR303对employee属性进行校验, 校验规则在属性注解的@Pattern中设置
* BindingResult result: 校验后,返回的结果
*/
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) {
//fieldError.getField(): 错误的字段名
//fieldError.getDefaultMessage(): 错误信息
map.put(fieldError.getField(), fieldError.getDefaultMessage());
}
return Msg.fail().add("errorFields", map);
} else {
employeeService.saveEmp(employee);
return Msg.success();
}
}
Service
public void saveEmp(Employee employee) {
employeeMapper.insert(employee);
}
补充前端代码
//点击保存,保存员工。
$("#emp_save_btn").click(function(){
//1、模态框中填写的表单数据提交给服务器进行保存
//1、先对要提交给服务器的数据进行校验
if(!validate_add_form()){
return false;
};
//1、判断之前的ajax用户名校验是否成功。如果成功。
if($(this).attr("ajax-va")=="error"){
return false;
}
//2、发送ajax请求保存员工
$.ajax({
url:"${APP_PATH}/emp",
type:"POST",
data:$("#empAddModal form").serialize(),
success:function(result){
//alert(result.msg);
if(result.code == 100){
//员工保存成功;
//1、关闭模态框
$("#empAddModal").modal('hide');
//2、来到最后一页,显示刚才保存的数据
//发送ajax请求显示最后一页数据即可
to_page(totalRecord);
}else{
//有哪个字段的错误信息就显示哪个字段的;
if(undefined != result.extend.errorFields.email){
//显示邮箱错误信息
show_validate_msg("#email_add_input", "error", result.extend.errorFields.email);
}
if(undefined != result.extend.errorFields.empName){
//显示员工名字的错误信息
show_validate_msg("#empName_add_input", "error", result.extend.errorFields.empName);
}
}
}
});
});
7. 效果
七、修改数据
1. 需要实现的功能
- 点击编辑按钮,弹出用户修改的模态框。
- 模态框可以回显用户的信息。
- 点击更新,完成修改操作。
2. 添加模态框
<!-- 员工修改的模态框 -->
<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">员工修改</h4>
</div>
<div class="modal-body">
<form class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">empName</label>
<div class="col-sm-10">
<p class="form-control-static" id="empName_update_static"></p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">email</label>
<div class="col-sm-10">
<input type="text" name="email" class="form-control" id="email_update_input" placeholder="email@atguigu.com">
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">gender</label>
<div class="col-sm-10">
<label class="radio-inline">
<input type="radio" name="gender" id="gender1_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>
<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">
</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>
3. 获取要修改的员工信息
Controller
@ResponseBody
@RequestMapping(value = "/emp/{id}", method = RequestMethod.GET)
public Msg getEmp(@PathVariable("id") Integer id) {
Employee employee = employeeService.getEmp(id);
return Msg.success().add("emp", employee);
}
Service
public Employee getEmp(Integer id) {
return employeeMapper.selectByPrimaryKey(id);
}
补充前端代码
//1、我们是按钮创建之前就绑定了click,所以绑定不上。
//1)、可以在创建按钮的时候绑定。 2)、绑定点击.live()
//jquery新版没有live,使用on进行替代
$(document).on("click",".edit_btn",function(){
//alert("edit");
//1、查出部门信息,并显示部门列表
getDepts("#empUpdateModal select");
//2、查出员工信息,显示员工信息
getEmp($(this).attr("edit-id"));
//3、把员工的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(result){
//console.log(result);
var empData = result.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]);
}
});
}
4. 保存员工信息
Controller
@ResponseBody
@RequestMapping(value = "/emp/{empId}", method = RequestMethod.PUT)
public Msg saveEmp(Employee employee) {
employeeService.updateEmp(employee);
System.out.println(employee);
return Msg.success();
}
Service
public void updateEmp(Employee employee) {
employeeMapper.updateByPrimaryKeySelective(employee);
}
补充前端代码
//点击更新,更新员工信息
$("#emp_update_btn").click(function(){
//验证邮箱是否合法
//1、校验邮箱信息
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", "");
}
//2、发送ajax请求保存更新的员工数据
$.ajax({
url:"${APP_PATH}/emp/"+$(this).attr("edit-id"),
type:"PUT",
data:$("#empUpdateModal form").serialize(),
success:function(result){
//alert(result.msg);
//1、关闭对话框
$("#empUpdateModal").modal("hide");
//2、回到本页面
to_page(currentPage);
}
});
});
5. 效果
八、删除数据
1. 需要实现的功能
-
单个删除,点击某条用户的删除按钮,弹出提示框,点击确定即可删除
-
批量删除
2. Controller
@ResponseBody
@RequestMapping(value = "/emp/{empId}", method = RequestMethod.DELETE)
public Msg deleteEmp(@PathVariable("empId") String ids) {
//判断批量删除还是单个删除
if (ids.contains("-")) {
ArrayList<Integer> list = new ArrayList<>();
String[] str_ids = ids.split("-");
for (String str_id : str_ids) {
list.add(Integer.parseInt(str_id));
}
employeeService.deleteBatch(list);
} else {
int id = Integer.parseInt(ids);
employeeService.deleteEmp(id);
}
return Msg.success();
}
3. Service
public void deleteEmp(Integer empId) {
employeeMapper.deleteByPrimaryKey(empId);
}
public void deleteBatch(ArrayList<Integer> list) {
EmployeeExample example = new EmployeeExample();
example.createCriteria().andEmpIdIn(list);
employeeMapper.deleteByExample(example);
}
4. 单个删除
补充前端代码
//单个删除
$(document).on("click",".delete_btn",function(){
//1、弹出是否确认删除对话框
var empName = $(this).parents("tr").find("td:eq(2)").text();
var empId = $(this).attr("del-id");
//alert($(this).parents("tr").find("td:eq(1)").text());
if(confirm("确认删除【"+empName+"】吗?")){
//确认,发送ajax请求删除即可
$.ajax({
url:"${APP_PATH}/emp/"+empId,
type:"DELETE",
success:function(result){
alert(result.msg);
//回到本页
to_page(currentPage);
}
});
}
});
5. 批量删除
补充前端代码
//完成全选/全不选功能
$("#check_all").click(function(){
//attr获取checked是undefined;
//我们这些dom原生的属性;attr获取自定义属性的值;
//prop修改和读取dom原生属性的值
$(".check_item").prop("checked",$(this).prop("checked"));
});
//check_item
$(document).on("click",".check_item",function(){
//判断当前选择中的元素是否5个
var flag = $(".check_item:checked").length==$(".check_item").length;
$("#check_all").prop("checked",flag);
});
//点击全部删除,就批量删除
$("#emp_delete_all_btn").click(function(){
//
var empNames = "";
var del_idstr = "";
$.each($(".check_item:checked"),function(){
//this
empNames += $(this).parents("tr").find("td:eq(2)").text()+",";
//组装员工id字符串
del_idstr += $(this).parents("tr").find("td:eq(1)").text()+"-";
});
//去除empNames多余的,
empNames = empNames.substring(0, empNames.length-1);
//去除删除的id多余的-
del_idstr = del_idstr.substring(0, del_idstr.length-1);
if(confirm("确认删除【"+empNames+"】吗?")){
//发送ajax请求删除
$.ajax({
url:"${APP_PATH}/emp/"+del_idstr,
type:"DELETE",
success:function(result){
alert(result.msg);
//回到当前页面
to_page(currentPage);
//每次删除完后,取消全选
$("#check_all").prop("checked",false);
}
});
}
});
6. 效果
单个删除
批量删除