转自:https://blog.csdn.net/zhengtornado/article/details/79968211
运行结果
功能点
- 分页
- 数据校验:jquery前端校验+JSR303后端校验
- ajax
- Rest风格的URI;使用HTTP方式的请求动词,来表示对资源的操作
GET(查询)、POST(新增)、PUT(修改)、DELETE(删除)
技术点:
- 基础框架--SSM(SpingMVC+Spring+Mybatis)
- 数据库-MySQL
- 前端框架-bootstrop快速搭建简洁美观的界面
- 项目依赖管理-Maven
- 分页-pagehelper
- 逆向工程-Mybatis Generator
AJAX查询
- index.jsp页面直接发送ajax请求进行员工分页数据的查询
- 服务器将查询出的数据,以json字符串的形式返回给浏览器
- 浏览器收到js字符串。可以使用js对json进行解析,使用js通过dom增删改 改变页面
- 返回json。实现客户端的无关性
新增逻辑
修改逻辑
删除逻辑
附1表结构
部门表
员工表
附2项目工程目录
附3:Mapping层代码
1.部门dao文件
package com.atwolf.crud.dao;
import java.util.List;
import com.atwolf.crud.bean.Department;
public interface DepartmentMapper {
//按主键ID删除一条数据
public int deleteByPrimaryKey(Integer deptId);
//保存全部数据
public int insert(Department record);
//有选择的保存部分数据
public int insertSelective(Department record);
//根据主键查询一条记录
public Department selectByPrimaryKey(Integer deptId);
//有选择的更新部分数据
public int updateByPrimaryKeySelective(Department record);
//更新全部数据
public int updateByPrimaryKey(Department record);
//查询所有
List<Department> Depts();
}
2.部门xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atwolf.crud.dao.DepartmentMapper">
<resultMap id="BaseResultMap" type="com.atwolf.crud.bean.Department">
<id column="dept_id" jdbcType="INTEGER" property="deptId" />
<result column="dept_name" jdbcType="VARCHAR" property="deptName" />
</resultMap>
<sql id="Base_Column_List">
dept_id, dept_name
</sql>
<!--查询所有 -->
<select id="Depts" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from tbl_dept
</select>
<!--根据主键查询一条记录 -->
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from tbl_dept
where dept_id = #{deptId,jdbcType=INTEGER}
</select>
<!--按主键ID删除一条数据 -->
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from tbl_dept
where dept_id = #{deptId,jdbcType=INTEGER}
</delete>
<!--保存全部数据 -->
<insert id="insert" parameterType="com.atwolf.crud.bean.Department">
insert into tbl_dept (dept_id, dept_name)
values (#{deptId,jdbcType=INTEGER}, #{deptName,jdbcType=VARCHAR})
</insert>
<!--有选择的保存部分数据 -->
<insert id="insertSelective" parameterType="com.atwolf.crud.bean.Department">
insert into tbl_dept
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="deptId != null">
dept_id,
</if>
<if test="deptName != null">
dept_name,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="deptId != null">
#{deptId,jdbcType=INTEGER},
</if>
<if test="deptName != null">
#{deptName,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<!--有选择的更新部分数据 -->
<update id="updateByPrimaryKeySelective" parameterType="com.atwolf.crud.bean.Department">
update tbl_dept
<set>
<if test="deptName != null">
dept_name = #{deptName,jdbcType=VARCHAR},
</if>
</set>
where dept_id = #{deptId,jdbcType=INTEGER}
</update>
<!--更新全部数据 -->
<update id="updateByPrimaryKey" parameterType="com.atwolf.crud.bean.Department">
update tbl_dept
set dept_name = #{deptName,jdbcType=VARCHAR}
where dept_id = #{deptId,jdbcType=INTEGER}
</update>
</mapper>
3.员工dao文件
package com.atwolf.crud.dao;
import java.util.List;
import com.atwolf.crud.bean.Employee;
public interface EmployeeMapper {
//ͨ通过主键删除一条记录
public int deleteByPrimaryKey(Integer empId);
//批量删除
public int deleteSelectiveEmp(List<Integer> ids);
//保存全部数据
public int insert(Employee record);
//有选择的保存部分数据
public int insertSelective(Employee record);
//查询所有
public List<Employee> selectByEmployee();
//ͨ通过主键ID查询数据
public Employee selectByPrimaryKey(Integer empId);
//有选择的更新字段
public int updateByPrimaryKeySelective(Employee record);
//更新全部字段
public int updateByPrimaryKey(Employee record);
//多表查询使用:查询员工表的同时,也把部门信息查询出来
public Employee selectByPrimaryKeywithDept(Integer empId);
//多表查询使用:查询员工表的同时,也把部门信息查询出来
public List<Employee> selectByEmpWithDept();
//统计员工表的总记录数
public List<Employee> selectByCountEmployee(Employee employee);
}
4.员工xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atwolf.crud.dao.EmployeeMapper">
<!--封装Employee组件中的所有字段 -->
<resultMap id="BaseResultMap" type="com.atwolf.crud.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" />
</resultMap>
<!--多表查询使用:查询员工表的同时,也把部门信息查询出来 -->
<!--封装多表查询中Employee组件中的字段 -->
<resultMap id="WithDept" type="com.atwolf.crud.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" />
<!--在Employee组件中封装一个部门信息,如何封装 -->
<association property="department" javaType="com.atwolf.crud.bean.Department">
<id column="dept_id" jdbcType="INTEGER" property="deptId" />
<result column="dept_name" jdbcType="VARCHAR" property="deptName" />
</association>
</resultMap>
<sql id="Base_Column_List">
emp_id, emp_name, gender, email, d_id
</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>
<!--查询用户名,用于限制用户名的唯一性 -->
<select id="selectByCountEmployee" resultMap="WithDept" parameterType="com.atwolf.crud.bean.Employee">
select
<include refid="WithDept_Column_List"/>
from tbl_emp e left join tbl_dept d on d.dept_id=e.d_id
where e.emp_name=#{empName,jdbcType=VARCHAR}
</select>
<!--多表查询使用:查询员工表的同时,也把部门信息查询出来 -->
<!-- (单个查询) public Employee selectByPrimaryKeywithDept(Integer empId);-->
<select id="selectByPrimaryKeywithDept" parameterType="java.lang.Integer" resultMap="WithDept">
select <include refid="WithDept_Column_List" />
from tbl_emp e left join tbl_dept d
on d.dept_id=e.d_id
where emp_id=#{empId,jdbcType=INTEGER}
</select>
<!--多表查询使用:查询员工表的同时,也把部门信息查询出来 -->
<!-- (查询所有) public List<Employee> selectByEmpWithDept(); -->
<select id="selectByEmpWithDept" resultMap="WithDept">
select
<include refid="WithDept_Column_List"/>
from tbl_emp e left join tbl_dept d on d.dept_id=e.d_id
</select>
<!-- 查询所有:public List<Employee> selectByEmployee(); -->
<select id="selectByEmployee" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from tbl_emp
</select>
<!--通过主键ID查询数据 -->
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from tbl_emp
where emp_id = #{empId,jdbcType=INTEGER}
</select>
<!--通过主键删除一条记录 -->
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from tbl_emp
where emp_id = #{empId,jdbcType=INTEGER}
</delete>
<!--批量删除 -->
<delete id="deleteSelectiveEmp" >
delete from tbl_emp
where emp_id in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</delete>
<!--保存全部数据 -->
<insert id="insert" parameterType="com.atwolf.crud.bean.Employee">
insert into tbl_emp (emp_id, emp_name, gender,
email, d_id)
values (#{empId,jdbcType=INTEGER}, #{empName,jdbcType=VARCHAR}, #{gender,jdbcType=CHAR},
#{email,jdbcType=VARCHAR}, #{dId,jdbcType=INTEGER})
</insert>
<!-- 有选择的保存部分数据 -->
<insert id="insertSelective" parameterType="com.atwolf.crud.bean.Employee">
insert into tbl_emp
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="empId != null">
emp_id,
</if>
<if test="empName != null">
emp_name,
</if>
<if test="gender != null">
gender,
</if>
<if test="email != null">
email,
</if>
<if test="dId != null">
d_id,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="empId != null">
#{empId,jdbcType=INTEGER},
</if>
<if test="empName != null">
#{empName,jdbcType=VARCHAR},
</if>
<if test="gender != null">
#{gender,jdbcType=CHAR},
</if>
<if test="email != null">
#{email,jdbcType=VARCHAR},
</if>
<if test="dId != null">
#{dId,jdbcType=INTEGER},
</if>
</trim>
</insert>
<!--有选择的更新字段 -->
<update id="updateByPrimaryKeySelective" parameterType="com.atwolf.crud.bean.Employee">
update tbl_emp
<set>
<if test="empName != null">
emp_name = #{empName,jdbcType=VARCHAR},
</if>
<if test="gender != null">
gender = #{gender,jdbcType=CHAR},
</if>
<if test="email != null">
email = #{email,jdbcType=VARCHAR},
</if>
<if test="dId != null">
d_id = #{dId,jdbcType=INTEGER},
</if>
</set>
where emp_id = #{empId,jdbcType=INTEGER}
</update>
<!--更新全部字段 -->
<update id="updateByPrimaryKey" parameterType="com.atwolf.crud.bean.Employee">
update tbl_emp
set emp_name = #{empName,jdbcType=VARCHAR},
gender = #{gender,jdbcType=CHAR},
email = #{email,jdbcType=VARCHAR},
d_id = #{dId,jdbcType=INTEGER}
where emp_id = #{empId,jdbcType=INTEGER}
</update>
</mapper>
5.部门service文件
备注:只做了对员工表的查询,新增,修改,删除。因此部门service层内容较少,只做了查询所有,到员工的下拉列表中展示
package com.atwolf.crud.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.atwolf.crud.bean.Department;
import com.atwolf.crud.dao.DepartmentMapper;
@Service
public class DepartmentService {
@Autowired
private DepartmentMapper departmentMapper;
//查询所有
public List<Department> getDepts() {
List<Department> list=departmentMapper.Depts();
return list;
}
}
6.员工service文件
package com.atwolf.crud.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Service;
import com.atwolf.crud.bean.Employee;
import com.atwolf.crud.dao.EmployeeMapper;
@Service
public class EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
//单表查询所有
public List<Employee> getAll() {
return employeeMapper.selectByEmployee();
}
//一对多查询:查询员工表对应的部门信息
public List<Employee> getAllEmpWithDept(){
List<Employee> emplist=employeeMapper.selectByEmpWithDept();
return emplist;
}
/**
* 保存员工
* @param employee
*/
public void saveEmp(Employee employee) {
employeeMapper.insertSelective(employee);
}
/**
* 服务端校验,用户名是否可用
* @param empName
* @return true:代表当前用户名可用,false:不可用
*/
public boolean checkUser(String empName) {
Employee emp=new Employee();
emp.setEmpName(empName);
List<Employee> list=employeeMapper.selectByCountEmployee(emp);
int size=list.size();
System.out.println("size===="+list.size());
if(size==0){
return true; //用户名可用
}else{
return false;
}
}
/**
* 按照员工id查询员工
* @param id
* @return
*/
public Employee getEmp(Integer id) {
Employee employee=employeeMapper.selectByPrimaryKey(id);
return employee;
}
/**
* 修改:更新按钮的单击事件,保存修改后的信息
* @param employee
*/
public void updateEmp(Employee employee) {
employeeMapper.updateByPrimaryKeySelective(employee);
}
/**
* 删除:根据主键id删除一条记录
* @param id
*/
public void deleteEmp(Integer id) {
employeeMapper.deleteByPrimaryKey(id);
}
/**
* 批量删除
* @param ids
*/
public void deleteBatch(List<Integer> ids) {
employeeMapper.deleteSelectiveEmp(ids);
}
}
7.部门Controller层
package com.atwolf.crud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.atwolf.crud.bean.Department;
import com.atwolf.crud.service.DepartmentService;
import com.atwolf.crud.utils.Msg;
/**
* 处理和部门有关的请求
* @author Administrator
*
*/
@Controller
public class DepartmentController {
@Autowired
private DepartmentService departmentService;
/**
* 返回所有部门信息
*/
@RequestMapping(value="/depts")
@ResponseBody
public Msg getDepts(){
List<Department> list=departmentService.getDepts();
return Msg.success().add("depts", list);
}
}
8.员工的Controller层
package com.atwolf.crud.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.atwolf.crud.bean.Employee;
import com.atwolf.crud.service.EmployeeService;
import com.atwolf.crud.utils.Msg;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
@Controller
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
/**
* 批量删除:也可以单个删(二合一)
* 批量删除:id的值 1-2-3
* 单个删除:id的值 1
*/
@ResponseBody
@RequestMapping(value="/emp/{ids}",method=RequestMethod.DELETE)
public Msg deleteEmp(@PathVariable("ids") String ids){
if(ids.contains("-")){
List<Integer> del_ids=new ArrayList<Integer>();
//如果参数ids中包含“-”,就是批量删除
String[] str_ids = ids.split("-");
//组装id的集合
for (String str : str_ids) {
Integer strids=Integer.parseInt(str);
del_ids.add(strids);
}
employeeService.deleteBatch(del_ids);
}else{
Integer id= Integer.parseInt(ids);
employeeService.deleteEmp(id);
}
return Msg.success();
}
/**
* 删除:根据主键id删除一条记录
* @param id
* @return
*/
/* @ResponseBody
@RequestMapping(value="/emp/{id}",method=RequestMethod.DELETE)
public Msg deleteEmpById(@PathVariable("id") Integer id){
employeeService.deleteEmp(id);
return Msg.success();
}*/
/**
* 修改:更新按钮的单击事件,保存修改后的数据
*/
@ResponseBody
@RequestMapping(value="/emp/{empId}",method=RequestMethod.PUT)
public Msg saveEmp(Employee employee){
employeeService.updateEmp(employee);
return Msg.success();
}
/**
* 修改:根据id查询所有员工数据
* @PathVariable("id")Integer id :@PathVariable("id")是指定参数 Integer id来源于上面路径中的id
*/
@RequestMapping(value="/emp/{id}",method=RequestMethod.GET)
@ResponseBody
public Msg getEmp(@PathVariable("id")Integer id){
Employee employee=employeeService.getEmp(id);
return Msg.success().add("emp", employee);
}
/**
* 后端校验:检查用户名是否可用,用户名的唯一性
* @param empName
* @return
*/
@RequestMapping("/checkuser")
@ResponseBody
public Msg checkuse(@RequestParam("empName")String empName){
//前后端保持校验信息一致
String regx="(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})";
boolean ide=empName.matches(regx);
if(!ide){
return Msg.fail().add("va_msg", "用户名必须是6-16位英文和数字的组合或者2-5位中文");
}
//数据库用户名重复校验
boolean iden=employeeService.checkUser(empName);
if(iden==true){
return Msg.success();//用户名可用
}else{
return Msg.fail().add("va_msg", "该用户名不可以使用");
}
}
/**
* 员工保存
* 1.支持JSR303校验
* 2.导入Hibernate-Validator包
* @Valid Employee employee 对封装的数据进行校验
* BindingResult result 封装校验结果
* @return
*/
@RequestMapping(value="/emp",method=RequestMethod.POST)
@ResponseBody
public Msg saveEmp(@Valid Employee employee,BindingResult result){
if(result.hasErrors()){
Map<String,Object> map =new HashMap<String, Object>();
//校验失败,应该返回失败,并在模态框中显示校验失败信息
List<FieldError> errors=result.getFieldErrors();
for (FieldError fieidError:errors) {
System.out.println("错误的字段名:"+fieidError.getField());
System.out.println("错误信息"+fieidError.getDefaultMessage());
map.put(fieidError.getField(), fieidError.getDefaultMessage());
}
return Msg.fail().add("errorFields", map);//传到浏览器显示
}else{
employeeService.saveEmp(employee);
return Msg.success();
}
}
/**
* 单表分页查询所有
* @param pn
* @param model
* @return
*/
@RequestMapping("/emps")
public String getEmps(@RequestParam(value="pn",defaultValue="1")Integer pn,Model model){
//引入PageHelper分页插件
//在查询之前只需要调用,参数1:页码,参数2:每页有多少条数据
PageHelper.startPage(pn, 10);
//startPage后面紧跟的查询就是一个分页查询
List<Employee> emps= employeeService.getAll();
//使用pageInfo包装查询后的结果,只需要将PageInfo交给页面就可以了
//PageInfo封装了分页的信息,包括查询出来的数据,传入连续显示的页数
PageInfo page=new PageInfo(emps,5);
model.addAttribute("pageInfo", page);
return "list";
}
/**
* 一对多分页查询所有
*/
@RequestMapping("/empwithdept")
public String getAllEmpWithDept(@RequestParam(value="pn",defaultValue="1") Integer pn,Model model){
PageHelper.startPage(pn, 10);
List<Employee> emps=employeeService.getAllEmpWithDept();
PageInfo page=new PageInfo(emps,5);
model.addAttribute("pageInfo", page);
return "list";
}
/**
*一对多分页查询所有 ,使用AJAX请求
*@ResponseBody自动将返回的对象转换成json字符串,@ResponseBody要能正常使用,需要导入jackson包
*/
@RequestMapping("/empwithdeptjson")
@ResponseBody
public Msg getEmpsWithJsion(@RequestParam(value="pn",defaultValue="1") Integer pn){
PageHelper.startPage(pn, 10);
List<Employee> emps=employeeService.getAllEmpWithDept();
//5表示连续显示5个页码
PageInfo page=new PageInfo(emps,5);
//直接返回一个对象,该对象会自动转换成json串
//return page;//写一个通用的处理返回的方法
return Msg.success().add("pageInfo", page);
}
}
9.通用的处理后端AJAX返回json信息的类
package com.atwolf.crud.utils;
import java.util.HashMap;
import java.util.Map;
/**
* 返回json数据的通用返回类
* @author Administrator
*
*/
public class Msg {
//状态码 100-成功 200-失败
private int code;
//提示信息
private String msg;
//用户要返回给浏览器的数据
private Map<String,Object> extend =new HashMap<String,Object>();
public static Msg success(){
Msg 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){
Map<String, Object> map=this.getExtend();
map.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;
}
}
10.部门的bean层
package com.atwolf.crud.bean;
public class Department {
private Integer deptId;
private String deptName;
public Department(Integer deptId, String deptName) {
super();
this.deptId = deptId;
this.deptName = deptName;
}
public Department() {
super();
// TODO Auto-generated constructor stub
}
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName == null ? null : deptName.trim();
}
}
11.员工的bean层–包含了后端JSR303校验
package com.atwolf.crud.bean;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Email;
public class Employee {
private Integer empId;
@Pattern(regexp="(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})",
message="用户名必须是2-5位中文或者6-16位英文和数字的组合")
private String empName;
private String gender;
//@Email 主要要使用转义字符/
@Pattern(regexp="^[a-z\\d]+(\\.[a-z\\d]+)*@([\\da-z](-[\\da-z])?)+(\\.{1,2}[a-z]+)+$",
message="邮箱格式不正确")
private String email;
private Integer dId;
//一对多查询中,员工表中添加部门信息
private Department department;
public Employee(Integer empId, String empName, String gender, String email, Integer dId) {
super();
this.empId = empId;
this.empName = empName;
this.gender = gender;
this.email = email;
this.dId = dId;
}
public Employee() {
super();
// TODO Auto-generated constructor stub
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName == null ? null : empName.trim();
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender == null ? null : gender.trim();
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email == null ? null : email.trim();
}
public Integer getdId() {
return dId;
}
public void setdId(Integer dId) {
this.dId = dId;
}
}
前端的jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- web路径:
不以/开始的相对路径,找资源,以当前资源的路径为基准,经常容易出问题。
以/开始的相对路径,找资源,以服务器的路径为标准(http://localhost:3306);需要加上项目名
http://localhost:3306/wolf-crud
-->
<%
pageContext.setAttribute("APP_PATH", request.getContextPath());
%>
<script type="text/javascript" src="${APP_PATH }/static/js/jquery-1.12.4.js"></script>
<link href="${APP_PATH }/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
<script src="${APP_PATH }/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
<title>员工列表(AjAX请求后台数据)</title>
</head>
<body>
<!--员工修改模态框 -->
<!-- Modal -->
<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 for="empName_update_input" class="col-sm-2 control-label">员工姓名</label>
<div class="col-sm-10">
<p class="form-control-static" id="empName_update_static"></p>
<!-- <input type="text" class="form-control" name="empName" id="empName_update_input" placeholder="empName"> -->
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<label for="email_update_input" class="col-sm-2 control-label">电子邮箱</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="email" 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">员工性别</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">所属部门</label>
<div class="col-sm-4">
<select class="form-control" name="dId" id="dept_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="emp_update_btn">更新</button>
</div>
</div>
</div>
</div>
<!--员工添加模态框 -->
<!-- Modal -->
<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">员工姓名</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="empName" id="empName_add_input" placeholder="empName">
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<label for="email_add_input" class="col-sm-2 control-label">电子邮箱</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="email" 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">员工性别</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">所属部门</label>
<div class="col-sm-4">
<select class="form-control" name="dId" id="dept_add_select">
</select>
</div>
</div>
</form>
</div>
<!--表单内容结束 -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" id="emp_save_btn">保存</button>
</div>
</div>
</div>
</div>
<div class="container">
<!--标题 -->
<div class="row">
<div class="col-md-12">
<h1>SSM增删改查实例</h1>
</div>
</div>
<!--按钮 -->
<div class="row">
<div class="col-md-4 col-md-offset-8">
<button class="btn btn-primary" id="emp_add_model_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>员工ID</th>
<th>员工姓名</th>
<th>员工性别</th>
<th>邮箱地址</th>
<th>部门名称</th>
<th>操作</th>
</tr>
</thead>
<!--表格体 -->
<tbody></tbody>
</table>
</div>
</div>
<!--显示分页信息 -->
<div class="row">
<!--分页文字信息 -->
<div class="col-md-6" id="page_info_area">
<!-- 当前页,总页,总条记录 -->
</div>
<!--分页条信息 -->
<div class="col-md-6" id="page_nav_area">
</div>
</div>
</div>
<script type="text/javascript">
//定义全局变量,总记录数
var totalRecord,currentPage;
//页面加载完成以后,直接去发送ajax请求,要到分页数据
$(function(){
//页面加载完默认进首页
to_page(1);
});
//点击页面时,实现页码跳转
function to_page(pn){
$.ajax({
url:"${APP_PATH}/empwithdeptjson",
data:"pn="+pn,//pn是用户指定跳转的页码数
type:"post",
//请求成功的回调函数,result是服务器响应给浏览器的数据
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();
//获取json串中返回的结果集(库表中的数据)
var emps=result.extend.pageInfo.list;
//循环遍历结果集==>循环遍历所有员工数据
//参数1:要遍历的emps集合,参数2:每次遍历的回调函数
//回调函数:参数1:索引,参数2:当前对象
$.each(emps,function(index,item){
//alert(item.empName);
//把解析的数据放到表格中展示,以下的DOM解析表格
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 gender=item.gender=='M'?"男":"女";
var genderTd=$("<td></td>").append(item.gender=='M'?"男":"女");
var emailTd=$("<td></td>").append(item.email);
var deptNameTd=$("<td></td>").append(item.department.deptName);
/*
<button class="btn btn-primary btn-sm">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> 编辑
</button>
<button class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> 删除
</button>
*/
var editBtn=$("<button></button>").addClass("btn btn-primary btn-sm edit_btn")
.append($("<span></span>").addClass("glyphicon glyphicon-pencil")).append(" ").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(" ").append("删除");
//为删除按钮添加一个自定义的属性,来表示当前删除的员工id
delBtn.attr("del-id",item.empId);
var btnTd=$("<td></td>").append(editBtn).append(" ").append(delBtn);
//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;
}
/*
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
*/
//解析显示分页条
function build_page_nav(result){
//清空分页导航
$("#page_nav_area").empty();
//page_nav_area
//创建ul
var ul=$("<ul></ul>").addClass("pagination");
//首页
var firstPageLi=$("<li></li>").append($("<a></a>").append("首页").attr("href","#"));
//前一页
var prePageLi=$("<li></li>").append($("<a></a>").append($("<span></span>").append("«")));
//如果没有了前一页,首页和前一页按钮不可用
if(result.extend.pageInfo.hasPreviousPage==false){
firstPageLi.addClass("disabled");
prePageLi.addClass("disabled");
}
//为元素添加点击翻页事件
//首页单击事件
firstPageLi.click(function(){
to_page(1);
});
//上一页单击事件:当前页-1
prePageLi.click(function(){
to_page(result.extend.pageInfo.pageNum-1);
});
//后一页
var nextPageLi=$("<li></li>").append($("<a></a>").append($("<span></span>").append("»")));
//末页
var lastPageLi=$("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
//如果没有了下一页,末页和下一页按钮不可用
if(result.extend.pageInfo.hasNextPage==false){
nextPageLi.addClass("disabled");
lastPageLi.addClass("disabled");
}
//下一页的单击事件:当前页+1
nextPageLi.click(function(){
to_page(result.extend.pageInfo.pageNum+1);
});
lastPageLi.click(function(){
to_page(result.extend.pageInfo.pages);
});
//添加首页和前一页的提示
ul.append(firstPageLi).append(prePageLi);
//循环遍历给ul中添加页码提示,取出页码号 1,2,3,4,5,
$.each(result.extend.pageInfo.navigatepageNums,function(index,item){
var numLi=$("<li></li>").append($("<a></a>").append(item));
//如果当前页码等于正在循环遍历的页码,则页码变色
if(result.extend.pageInfo.pageNum==item){
numLi.addClass("active");
}
//给页码添加单击事件
numLi.click(function(){
to_page(item);
});
ul.append(numLi);
});
//添加下一页和末页的提示
ul.append(nextPageLi).append(lastPageLi);
//创建nav,将ul标签添加到nav标签中
var nav=$("<nav></nav>").append(ul);
//将分页条添加到上面id中
nav.appendTo("#page_nav_area");
}
// 清除表单数据(表单重置--表单的数据,表单的样式)
function reset_form(ele){
$(ele)[0].reset();//清空表单数据,防止再次打开模态框时,带有之前添加的的数据
//清空模态框表单中上次残留的样式
$(ele).find("*").removeClass("has-error has-success");
$(ele).find(".help-block").text("");
}
//点击新增按钮弹出模态框
$("#emp_add_model_btn").click(function(){
//1.清除表单数据(表单重置--表单的数据,表单的样式),获取表单,jquery没有reset()方法,需要转成原生对象
// $("#empAddModal form")[0].reset(); -->统一写一个函数,见上面
reset_form("#empAddModal form");
//2.发送ajax请求,查出部门信息,显示在下拉列表中
getDepts("#dept_add_select");
//3.弹出模态框
$("#empAddModal").modal({
backdrop:"static"
});
});
//查出所有部门信息,显示在下拉列表中
function getDepts(ele){
$(ele).empty(); //$("#dept_add_select").empty();
$.ajax({
//向后台发送请求
url:"${APP_PATH}/depts",
type:"GET",
//拿到请求查询的结果result
success:function(result){
//console.log(result)
//{"code":100,"msg":"处理成功","extend":{"depts":[{"deptId":1,"deptName":"开发部"},{"deptId":2,"deptName":"测试部"}]}}
//显示部门信息到下拉列表中,有2种获取下拉列表的方式
//$("#empAddModal select")
//$("#dept_add_select")
//循环遍历部门信息
$.each(result.extend.depts,function(){
var optionEle=$("<option></option>").append(this.deptName).attr("value",this.deptId);
optionEle.appendTo(ele);
})
}
});
}
//前端校验:校验表单数据
function validate_add_form(){
//1.拿到要校验的数据(通过id获取),使用正则表达式
var empName=$("#empName_add_input").val();//获取文本框的值
var regName=/(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/;
// alert(regName.test(empName));
if(!regName.test(empName)){//如果校验失败
//alert("用户名可以是2-5位中文或者6-16位英文和数字的组合");
// 给input文本框的父元素添加提示样式,文本框变色
show_validate_msg("#empName_add_input","error","用户名可以是2-5位中文或者6-16位英文和数字的组合");
return false; //校验失败,返回false不在向下执行
}else{
show_validate_msg("#empName_add_input","success","");
//$("#empName_add_input").parent().addClass("has-success");
//$("#empName_add_input").next("span").text("");
}
//2.校验邮箱
var email=$("#email_add_input").val();//获取邮箱的文本框的值
var regEmail=/^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/;
if(!regEmail.test(email)){
//alert("邮箱格式不正确");
//应该清空这个元素之前的样式
show_validate_msg("#email_add_input","error","邮箱格式不正确");
//$("#email_add_input").parent().addClass("has-error");
//$("#email_add_input").next("span").text("邮箱格式不正确");
return false;
}else{
show_validate_msg("#email_add_input","success","");
//$("#email_add_input").parent().addClass("has-success");
//$("#email_add_input").next("span").text("");
}
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");
//获取当前输入框元素的下一个元素span,将span元素的文本值设置成提示信息
$(ele).next("span").text(msg);
}
}
//绑定文本框改变事件:当文本框里面的内容发生改变以后,检验用户名是否可用
$("#empName_add_input").change(function(){
var empName=this.value;
//alert("*****"+empName);
//var empName=$("#empName_add_input").val();
//发送ajax请求校验用户名是否可用
$.ajax({
url:"${APP_PATH}/checkuser",
type:"POST",
data:"empName="+empName,
dataType:"json",
success:function(result){
if(result.code==100){
$("#emp_save_btn").attr("ajax-va","success");
show_validate_msg("#empName_add_input","success","用户名可用");
}else{
show_validate_msg("#empName_add_input","error",result.extend.va_msg);//result.extend.va_msg:获取后台数据 --该用户名不可以使用
$("#emp_save_btn").attr("ajax-va","error");
}
}
});
});
//保存按钮的单击事件,实现点击按钮保存员工数据
$("#emp_save_btn").click(function(){
//模态框中填写的表单数据提交给服务器进行保存
//1.先要对提交给服务器的数据进行校验,前端校验,注释掉可以测试后端JSR303校验
if(!validate_add_form()){
return false;
};
//判断之前的ajax用户名校验是否成功,如果用户名已存在,则保存按钮不可用
//获取当前按钮的属性值
if($("#emp_save_btn").attr("ajax-va")=="error"){
return false;
}
//2.发送ajax请求保存员工,serialize()序列表表格内容为字符串,用于Ajax请求
//获取表单,并将表单序列化empName=%E5%AD%9D%E6%B8%85&email=xiaoqing%40163.com&gender=F&dId=2
//alert($("#empAddModal form").serialize());
$.ajax({
url:"${APP_PATH}/emp",
type:"POST",
data:$("#empAddModal form").serialize(),
success:function(result){
//{"code":100,"msg":"处理成功","extend":{"depts":[{"deptId":1,"deptName":"开发部"},{"deptId":2,"deptName":"测试部"}]}}
// alert(result.msg);
if(result.code==100){
// 员工保存成功后:
// 1.关闭模态框
$('#empAddModal').modal('hide');
// 2、来到最后一页,显示刚才保存的数据
//发送ajax请求,显示最后一页数据即可
to_page(totalRecord);
}else{
//JSR303后端校验失败,显示失败信息
console.log(result);//Objectcode: 200 extend: Objectmsg: "处理失败"__proto__: Object
//有那个字段的错误信息就显示那个字段的信息
alert(result.extend.errorFields.email);
alert(result.extend.errorFields.empName);
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);
}
}
}
})
});
// 给jquery动态创建的编辑按钮绑定事件,没有id属性的按钮,给class属性的一个值绑定单击事件
$(document).on("click",".edit_btn",function(){
//alert("绑定单击事件");
//1.查出部门信息,并显示部门列表
getDepts("#dept_update_select") //getDepts("#empUpdateModal select")
//2.查出员工信息,显示员工信息
//getEmp(id);//?如何获取每一个编辑按钮的员工id-->editBtn.attr("edit-id",item.empId);
getEmp($(this).attr("edit-id")); //this代表当前被点击的按钮
//3.把员工id传递给模态框的更新按钮
$("#emp_update_btn").attr("edit-id",$(this).attr("edit-id"));
//4.弹出模态框
$("#empUpdateModal").modal({
backdrop:"static"
});
})
//查出员工信息,显示员工信息
function getEmp(id){
$.ajax({
url:"${APP_PATH}/emp/"+id, //@RequestMapping(value="/emp/{id}",method=RequestMethod.GET)
type:"GET",
success:function(result){
//console.log(result);
//获取到服务端返回的所有员工数据
var empData=result.extend.emp;
$("#empName_update_static").text(empData.empName);//给p标签之类的赋值用text()属性
$("#email_update_input").val(empData.email);//给文本框赋值用val()属性
// 获取 单选按钮的方法 有多种 $("#empUpdateModa input[name=gender]")
$("#empUpdateModal input[type=radio]").val([empData.gender]);
//给下拉列表赋值
$("#empUpdateModal select").val([empData.dId]);
}
})
}
//修改:给更新按钮绑定单击事件
$("#emp_update_btn").click(function(){
//1.验证邮箱是否合法
var email=$("#email_update_input").val();//获取邮箱的文本框的值
var regEmail=/^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/;
if(!regEmail.test(email)){
//alert("邮箱格式不正确");
//应该清空这个元素之前的样式
show_validate_msg("email_update_input","error","邮箱格式不正确");
//$("#email_add_input").parent().addClass("has-error");
//$("#email_add_input").next("span").text("邮箱格式不正确");
return false;
}else{
show_validate_msg("#email_update_input","success","");
//$("#email_add_input").parent().addClass("has-success");
//$("#email_add_input").next("span").text("");
}
//2.发送ajax数据,保存修改的数据
$.ajax({
//如何获取页面的员工id-->把员工id的值绑定到更新按钮上
url:"${APP_PATH}/emp/"+$(this).attr("edit-id"),
type:"PUT", //<filter-name>HttpPutFormContentFilter</filter-name>
data:$("#empUpdateModal form").serialize(),
//type:"POST",
//data:$("#empUpdateModal form").serialize()+"&_method=PUT",
success:function(result){
//console.log(result);
//alert(result.msg);
//关闭模态框
$("#empUpdateModal").modal("hide");
//回到本页面,如何做到-->全局变量:currentPage
to_page(currentPage);
}
});
});
//单个删除:给jquery动态创建的删除按钮绑定事件,没有id属性的按钮,给class属性的一个值绑定单击事件
$(document).on("click",".delete_btn",function(){
//1.弹出是否确认删除对话框
//(1)如何获取员工姓名:获取当前按钮的所有祖先节点,在找第二个<td>
//alert($(this).parents("tr").find("td:eq(1)").text());
var empName=$(this).parents("tr").find("td:eq(2)").text();
var empId=$(this).attr("del-id");
if(confirm("确认删除【"+empName+"】吗?")){
//确认,发送ajax请求删除即可
$.ajax({
//给删除按钮绑定id
url:"${APP_PATH}/emp/"+empId,
type:"DELETE",
success:function(result){
//alert(result.msg);
//回到本页
to_page(currentPage);
}
});
}
});
//完成全选/全不选的事件功能
$("#check_all").click(function(){
//attr获取checked是undefined;
//我们这些dom原生的属性比如checked,我们用prop()获取原生的属性值,而attr获取自定义属性的值
//prop修改和读取dom原生属性值
//alert($(this).prop("checked"));
//选中标题行的复选框,下面的复选框跟着一起选中
$(".check_item").prop("checked",$(this).prop("checked"));
});
//全部选中表格体中的复选框时,上面标题中的复选框也跟着选中
$(document).on("click",".check_item",function(){
//alert($(".check_item:checked").length);
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代表当前被循环到的复选框,打印所有选中的员工姓名
//alert($(this).parents("tr").find("td:eq(2)").text());
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);
//去除del_idstr对于的“-”
del_idstr=del_idstr.substring(0,empNames.length-1);
if(confirm("确认删除【"+empNames+"】吗?")){
//为true时,确认删除name的值,发送ajax请求
$.ajax({
url:"${APP_PATH}/emp/"+del_idstr,
type:"DELETE",
success:function(result){
alert(result.msg);
//回到当前页面
to_page(currentPage);
}
})
}
});
</script>
</body>
</html>