target
能够完成restful的增删改查
掌握静态资源不能加载的处理办法
掌握中文乱码的解决方案
掌握下拉框和单选框的回显操作
了解使用Spring表单标签重构页面
1. RESTRUL_CRUD_需求
使用 restful 实现员工的crud功能。
1.1 显示所有员工信息
① URL:emps
② 请求方式:GET
③ 显示效果

1.2 添加操作-跳转至添加页面
① 显示添加⻚面:
② URL:emp
③ 请求方式:GET
④ 显示效果:

1.3 添加操作-添加员工
① 添加员工信息
②URL:emp
③ 请求方式:POST
④ 显示效果:完成添加,重定向到emps请求

1.4 删除操作
① URL:emp/{id}
② 请求方式:DELETE
③ 删除后效果:对应记录从数据表中删除
1.5 修改操作–去往修改⻚面
① URL:emp/{id}
② 请求方式:GET
③ 显示效果:回显表单
1.6 修改操作–修改员工
① URL:emp
② 请求方式:PUT
③ 显示效果:完成修改,重定向到emps请求
1.7 相关的类
① 实体类:Employee、Department
② Controller: EmployeeController
③ Dao:EmployeeDao、DepartmentDao
1.8 相关页面
① list.jsp
② input.jsp
③ edit.jsp
2. 搭建环境
新建动态 Web项目 SpringMVC_restful
:
2.1 导入jar
将以下jar复制到 lib 目录下:
commons-logging-1.2.jar
spring-aop-4.3.9.RELEASE.jar
spring-beans-4.3.9.RELEASE.jar
spring-context-4.3.9.RELEASE.jar
spring-core-4.3.9.RELEASE.jar
spring-expression-4.3.9.RELEASE.jar
spring-web-4.3.9.RELEASE.jar
spring-webmvc-4.3.9.RELEASE.jar
2.2 配置核心控制器:web.xml
Web.xml 中配置 HiddenHttpMethodFilter 过滤器和前端控制器
SpringMVC_Restfulindex.jspHiddenHttpMethodFilterorg.springframework.web.filter.HiddenHttpMethodFilterHiddenHttpMethodFilter/*springDispatcherServletorg.springframework.web.servlet.DispatcherServletcontextConfigLocationclasspath:springmvc.xml1springDispatcherServlet/
2.3 创建配置文件:springmvc.xml
在 src 下新建springmvc 配置文件,开启包扫描和视图解析
2.4 实体类
员工类:
package com.lee.entity;
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender;
private Department department;
//getter、setter 略
}
部门类:
package com.lee.entity;
public class Department {
private Integer id;
private String departmentName;
//getter、setter 略
}
2.5 Dao类
员工:
package com.lee.springmvc.dao;
@Repository
public class EmployeeDao {
//模拟数据库数据
private static Map employees = null;
static {
employees = new HashMap();
employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1, new Department(101, "D-AA")));
employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1, new Department(102, "D-BB")));
employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0, new Department(103, "D-CC")));
employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0, new Department(104, "D-DD")));
employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1, new Department(105, "D-EE")));
}
private static Integer initId = 1006; //下次添加的id默认从1006开始
}
部门:
package com.lee.springmvc.dao;
@Repository
public class DepartmentDao {
//模拟数据库数据
private static Map departments = null;
static {
departments = new LinkedHashMap();
departments.put(101, new Department(101, "D-AA"));
departments.put(102, new Department(102, "D-BB"));
departments.put(103, new Department(103, "D-CC"));
departments.put(104, new Department(104, "D-DD"));
departments.put(105, new Department(105, "D-EE"));
}
//获取所有部门信息
public Collection getDepartments() {
return departments.values();
}
//根据id获取部门信息
public Department getDepartment(Integer id) {
return departments.get(id);
}
}
3. RESTRUL_CRUD_显示所有员工信息
1)增加页面链接:index.jsp
主页
显示员工列表
2)处理器
@Controller
public class EmpController {
@Autowired
EmployeeDao employeeDao;
/**
* 查询所有员工
* @param map
* @return
*/
@RequestMapping("emps")
public String getAll(Map map) {
Collection emps = employeeDao.getAll();
map.put("emps", emps);
return "list";
}
}
3)Dao层:
在EmployeeDao.java 中加入 getAll()方法来获取所有员工信息:
package com.lee.springmvc.dao;
@Repository
public class EmployeeDao {
.......
/**
* 获取所有员工信息
* @return
*/
public Collection getAll() {
return employees.values();
}
}
4)在views下编写list.jsp
需要用到jstl标签库进行遍历员工信息遍历,需要两个jar:
jstl-1.1.2.jar
standard-1.1.2.jar
在 WEB-INF/views 目录下新建list页面:
员工列表
table,table tr th, table tr td {
border:1px solid #a8aeb2;
padding: 5px 10px;
}
table {
min-height: 25px;
line-height: 25px;
text-align: center;
border-collapse: collapse;
}
ID
LASTNAME
EMAIL
GENDER
DEPARTMENT
${emp.id }
${emp.lastName }
${emp.email }
${emp.gender ==1?"男":"女"}
${emp.department.departmentName }
开发经验
如果加载css样式或者js等会出现静态资源无法被访问的情况:
这是由于springmvc的dispatcherServlet把静态资源也当成请求进行处理了,可以使用以下两个标签,把静态资源交给Tomcat的servlet去处理,就能解决这个问题:
4. RESTRUL_CRUD_添加操作
1)在list.jsp上增加连接
ID
LASTNAME
EMAIL
GENDER
DEPARTMENT
ADD
....
2)在EmpController中增加处理方法
此处理器是跳转到增加页面的处理器,并不是具体的增加方法
/**
* 跳转到添加页面,并查出所有部门信息
* @param map
* @return
*/
@RequestMapping(value = "emp",method = RequestMethod.GET)
public String toAdd(Map map) {
//查询所有部门
Collection departments = departmentDao.getDepartments();
map.put("departments", departments);
return "add";
}
这个控制器不仅仅跳转到增加页面,而且获取了部门信息。
3)add.jsp页面
添加页面
lastName
email
gender
男
女
department
SELECT DEPARTMENT
${dept.departmentName }
4)在EmpController处理器中新增员工
/**
* 添加员工
* @param emp
* @return
*/
@RequestMapping(value = "emp" ,method = RequestMethod.POST)
public String addEmp(Employee emp) {
employeeDao.addEmp(emp);
return "redirect:/emps";
}
注意:
这里需要使用重定向,重定向到获取所有员工的控制器。
开发中,增删改后都要进行重定向,请求转发会造成表单重复提交问题。
5)在EmployeeDao中编写员工添加方法:
package com.lee.springmvc.dao;
@Repository
public class EmployeeDao {
...
@Autowired
DepartmentDao departmentDao;
/**
* 添加员工
* @param emp
*/
public void addEmp(Employee emp) {
// System.out.println(emp);
// 由于前台传来的emp中只有部门id,没有部门名称。所以根据部门id查出部门信息
Department department = departmentDao.getDepartment(emp.getDepartment().getId());
emp.setId(initId); //为emp设置id
emp.setDepartment(department); // 为emp设置部门信息
employees.put(initId, emp); // 将emp加入到员工中
initId++;
}
}
开发经验
再添加信息时,添加中文会出现乱码情况。
解决方案:在web.xml中添加字符编码过滤器,这个过滤器一定要添加到其他过滤器之前。
encodingFilterorg.springframework.web.filter.CharacterEncodingFilterencodingUTF-8encodingFilter/*
5. RESTRUL_CRUD_更新操作
1)添加更新链接:
在list.jsp中添加更新按钮:
${emp.id }
${emp.lastName }
${emp.email }
${emp.gender ==1?"男":"女"}
${emp.department.departmentName }
UPDATE
2)在EmpController控制器中编写跳转到更新员工的页面的方法:
/**
* 跳转到更新员工的页面
* @param id
* @param map
* @return
*/
@RequestMapping(value = "emp/{id}",method = RequestMethod.GET)
public String toUpdate(@PathVariable("id") Integer id,Map map) {
Employee emp = employeeDao.getEmpById(id);//根据员工id查员工信息
Collection departments = departmentDao.getDepartments();
map.put("emp", emp);
map.put("departments", departments);
return "update";
}
3)在EmployeeDao 中编写根据员工id查询员工信息:
public Employee getEmpById(Integer id) {
Employee employee = employees.get(id);
return employee;
}
4)在 WEB-INF下新建update.jsp
注意:
如果更新页面报错405,就在表单action写绝对路径
更新信息
lastName
email
gender
男
女
department
${dept.departmentName }
5)在EmpController控制器中编写 更新员工的方法:
/**
* 更新员工信息
* @param emp
* @return
*/
@RequestMapping(value = "emp" ,method = RequestMethod.PUT)
public String updateEmp(Employee emp) {
employeeDao.updateEmp(emp);
return "redirect:/emps";
}
6)在EmployeeDao下编写更新员工的方法:
public void updateEmp(Employee emp) {
// 由于前台传来的emp中只有部门id,没有部门名称。所以根据部门id查出部门信息
Department department = departmentDao.getDepartment(emp.getDepartment().getId());
emp.setDepartment(department); // 为emp设置部门信息
employees.replace(emp.getId(), emp);
}
开发经验
如何设置下拉框回显:
${dept.departmentName }
如何设置单选框回显
男
女
或者:
checked="checked" />男
checked="checked" />女
更新的action需要绝对路径
update.jsp中的form表单的action必须是绝对路径,否则会出现路径请求异常。
el表达式获取绝对路径:
6. RESTURL_CRUD_删除操作
6.1 方法一
1)在list.jsp中添加删除按钮,由于删除需要使用delete方式的请求,所以用form表单传值:
2)在EmpController中编写根据id删除员工的方法:
/**
* 根据id删除员工
* @param id
* @return
*/
@RequestMapping(value = "emp/{id}",method = RequestMethod.DELETE)
public String deleteEmpById(@PathVariable("id") Integer id) {
employeeDao.deleteEmp(id);
return "redirect:/emps";
}
3)在 EmployeeDao中编写删除代码:
/**
* 根据id删除员工
* @param id
*/
public void deleteEmp(Integer id) {
employees.remove(id);
}
6.2 方法二
请求路径:
Delete
控制器:
/**
* 根据id删除员工
* @param id
* @return
*/
@RequestMapping(value = "emp/{id}" ,method = RequestMethod.DELETE)
public String delEmp(@PathVariable("id") Integer id) {
employeeDao.delete(id);
return "redirect:/emps";
}
发起请求,无法执行,因为 delete 请求必须借助HiddenHttpMethodFilter 过滤器把 post 请求转换为 delete 请求,
需要使用 jQuery 来转换请求方式
$(function() {
$(".delete").click(function(){
var href = this.href;
if(confirm("确认删除")){
$("form").attr("action",href).submit();
return false;//使函数终止执行
}
});
});
开发经验:
如果报如下错误:

检查第一步: jQuery的路径应该是绝对路径,否则资源找不到。
检查第二步:springmvc有没有处理静态资源(重要)。
6.3 删除操作执行图解

7. 扩展:作用
首先打开Tomcat的web.xml文件:可以看到如下的servlet
defaultorg.apache.catalina.servlets.DefaultServletdebug0listingsfalse1default/
这是Tomcat配置的servlet,名字是default,拦截所有请求。
他是专门处理静态资源请求的servlet。springmvc中会配置一个dispatcherServlet去处理所有的请求,但是不包含静态资源,所以静态资源会失效。因此需要在springmvc配置文件中加上:,就可以去处理dispatcherServlet处理不了的静态资源了。但是加上
后,又只能访问静态资源,原来的请求又失效了,因此需要配合
一起使用。
8. 扩展:Spring的表单标签
通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显。
使用spring的表单标签需要引入标签库:
8.1 使用spring标签重构添加
- 修改EmpController控制器中的跳转方法:
/**
* 跳转到添加页面
* @return
*/
@RequestMapping(value = "emp",method = RequestMethod.GET )
public String toAdd(Map map) {
Collection departments = departmentDao.getDepartments();
Map genders = new HashMap();
genders.put("0", "男");
genders.put("1", "女");
map.put("departments", departments);
map.put("genders", genders);
/**
* 如果不加下面这行代码,会报错
*/
map.put("command", new Employee());
return "add";
}
- 修改add.jsp:
添加员工信息
LastName:
email:
Gender:
Department:
重新加载项目,一切OK。
注意:
如果EmpController控制器中的 toAdd() 方法没有map.put("command", new Employee());
代码,会如下报错:

报错原因:
由于spring的from表单自带回显功能,form会去控制器中寻找默认为command的属性,command中包含表单的所有信息,command就是”模型属性”,form会解析command中的信息显示在表格中。
此外,也可以在表单中使用modelAttribute指定:
控制器相应的改为:
map.put("employee", new Employee());
8.2 使用Spring标签重构修改
可以把添加和修改写到一个页面,将add.jsp改名为:add_update_form.jsp:
添加/修改员工信息
LastName:
email:
Gender:
Department:
EmpController控制器中修改”跳转到更新”和”跳转到添加页面”的方法:
/*跳转到添加页面 */
@RequestMapping(value = "emp",method = RequestMethod.GET)
public String toAdd(Map map) {
Collection departments = departmentDao.getDepartments();
Map genders = new HashMap();
genders.put("0", "男");
genders.put("1", "女");
map.put("genders", genders);
map.put("departments", departments);
map.put("employee", new Employee());
return "add_update_form";
}
/*跳转到更新页面*/
@RequestMapping(value = "emp/{id}",method = RequestMethod.GET)
public String toUpdate(@PathVariable("id") Integer id,Map map) {
Employee emp = employeeDao.getEmpById(id);//根据员工id查员工信息
Collection departments = departmentDao.getDepartments();
Map genders = new HashMap();
genders.put("0", "男");
genders.put("1", "女");
map.put("genders", genders);
map.put("employee", emp);
map.put("departments", departments);
return "add_update_form";
}