RESTRUL_CRUD_需求
显示所有员工信息
- URI: emps
- 请求方式:GET
- 显示效果

添加员工信息
显示添加页面:
URI:emp
请求方式:GET
显示效果

添加员工信息:
URI:emp
请求方式:POST
显示效果:完成添加,重定向到 list 页面。

删除操作
- URL:emp/{id}
- 请求方式:DELETE
- 删除后效果:对应记录从数据表中删除
修改操作:lastName 不可修改!
- 显示修改页面
- URI:emp/{id}
- 请求方式:GET
- 显示效果:回显表单。
- 修改员工信息
- URI:emp
- 请求方式:PUT
- 显示效果:完成修改,重定向到 list 页面。

相关的类
- 省略了Service层
- 实体类:Employee、Department
- Controller:EmployeeController
- Dao:EmployeeDao、DepartmentDao

相关页面
- list.jsp
- input.jsp
- edit.jsp
RESTRUL_CRUD_显示所有员工信息
搭建开发环境
导包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
commons-logging-1.1.3.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar创建配置文件:springmvc.xml 增加context,mvc,beans名称空间。
配置核心控制器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>将 POST 请求转换为 PUT 或 DELETE 请求以及字符过滤器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<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>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>创建相关页面
1
2/WEB-INF/views/list.jsp
index.jsp增加实体类


增加Dao
- EmployeeDao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48package xyz.lyhcc.dao;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import xyz.lyhcc.bean.Department;
import xyz.lyhcc.bean.Employee;
@Repository
public class EmployeeDao {
private static Map<Integer, Employee> employees = null;
@Autowired
private DepartmentDao departmentDao;
static{
employees = new HashMap<Integer, Employee>();
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;
public void save(Employee employee) {
if (employee.getId() == null) {
employee.setId(initId++);
}
employee.setDepartment(departmentDao.getDepartment(employee.getDepartment().getId()));
employees.put(employee.getId(), employee);
}
public Collection<Employee> getAll() {
return employees.values();
}
public Employee get(Integer id) {
return employees.get(id);
}
public void delete(Integer id) {
employees.remove(id);
}
} - DeaprtmentDao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36package xyz.lyhcc.bean;
public class Department {
private Integer id;
private String departmentName;
public Department() {
super();
}
public Department(Integer id, String departmentName) {
super();
this.id = id;
this.departmentName = departmentName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
}
- EmployeeDao
显示所有员工信息
页面链接
1
<a href="empList">To Employee List</a>增加处理器
1
2
3
4
5
6
7
8
9
10
11
12@Controller
public class MyController {
@Autowired
EmployeeDao employeeDao;
@RequestMapping("/retrieveEmps")
public String retrieveEmps(Map<String, Object> map) {
map.put("empList", employeeDao.getAll());
return "list";
}
}SpringMVC中没遍历的标签,需要使用jstl标签进行集合遍历增加jstl标签库jar包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27<table border="1" cellpadding="10" cellspacing="0">
<tr>
<td>EmpId</td>
<td>LastName</td>
<td>Gender</td>
<td>Email</td>
<td>DepartmentName</td>
<td>Edit</td>
<td>Delete</td>
</tr>
<c:forEach items="${requestScope.empList }" var="emp">
<tr>
<td>${emp.id } </td>
<td>${emp.lastName }</td>
<td>${emp.gender==0?"女": "男" }</td>
<td>${emp.email }</td>
<td>${emp.department.departmentName }</td>
<td>
<a href="">Edit</a>
</td>
<td>
<a href="">Delete</a>
</td>
</tr>
</c:forEach>
</table>
<a href="toaddpage">Add Employee</a>
使用 Spring的表单标签
- 通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显
- form 标签
- 一般情况下,通过 GET 请求获取表单页面,而通过 POST 请求提交表单页面,因此获取表单页面和提交表单页面的 URL 是相同的。
- 只要满足该最佳条件的契约,form:form 标签就无需通过 action 属性指定表单提交的 URL
- 可以通过 modelAttribute 属性指定绑定的模型属性,若没有指定该属性,则默认从 request 域对象中读取 command 的表单 bean,如果该属性值也不存在,则会发生错误。
- SpringMVC 提供了多个表单组件标签,如 form:input/、form:select/ 等,用以绑定表单字段的属性值,它们的共有属性如下:
- path:表单字段,对应 html 元素的 name 属性,支持级联属性
- htmlEscape:是否对表单值的 HTML 特殊字符进行转换,默认值为 true
- cssClass:表单组件对应的 CSS 样式类名
- cssErrorClass:表单组件的数据存在错误时,采取的 CSS 样式
- form:input、form:password、form:hidden、form:textarea:对应 HTML 表单的 text、password、hidden、textarea 标签
- form:radiobutton:单选框组件标签,当表单 bean 对应的属性值和 value 值相等时,单选框被选中
- form:radiobuttons:单选框组标签,用于构造多个单选框
- items:可以是一个 List、String[] 或 Map
- itemValue:指定 radio 的 value 值。可以是集合中 bean 的一个属性值
- itemLabel:指定 radio 的 label 值
- delimiter:多个单选框可以通过 delimiter 指定分隔符
- form:checkbox:复选框组件。用于构造单个复选框
- form:checkboxs:用于构造多个复选框。使用方式同 form:radiobuttons 标签
- form:select:用于构造下拉框组件。使用方式同 form:radiobuttons 标签
- form:option:下拉框选项组件标签。使用方式同 form:radiobuttons 标签
- form:errors:显示表单组件或数据校验所对应的错误
- <form:errors path= “*” /> :显示表单所有的错误
- <form:errors path= “user*” /> :显示所有以 user 为前缀的属性对应的错误
- <form:errors path= “username” /> :显示特定表单对象属性的错误
RESTRUL_CRUD_添加操作&表单标签
在list.jsp上增加连接
1
<a href="empInput">Add Employee</a>增加处理器方法
1
2
3
4
5
6
7
8
9
10
11
12
13@RequestMapping(value="toaddpage")
public String addEmpPage(Model model) {
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("depts", departments);
//增加一个属性
return "add";
}
@RequestMapping(value="increaseEmp",method=RequestMethod.POST)
public String increaseEmp(Employee employee, Map<String, Object>map) {
employeeDao.save(employee);
return "redirect:/retrieveEmps";
}显示添加页面
- 非SpringMVC的form标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<% pageContext.setAttribute("ctp", request.getContextPath()); %>
<form action="increaseEmp" method="POST">
lastName: <input type="text" name="lastName" />
email: <input type="text" name="email" />
gender:
男<input type="radio" name="gender" value="1"/>
女<input type="radio" name="gender" value="0"/>
<select name="department.id">
<c:forEach items="${depts }" var="dept">
<option value="${dept.id }">${dept.departmentName }</option>
</c:forEach>
</select>
<input type="submit" value="提交" />
</form>- SpringMVC的form标签
1
2
3
4
5
6
7
8
9
10
11
12<form:form action="increaseEmp" method="POST" modelAttribute="employee">
<!-- java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute -->
LastName: <form:input path="lastName"/></br></br>
Email: <form:input path="email"/></br></br>
Gender: 男<form:radiobutton path="gender" value="1"/>
女<form:radiobutton path="gender" value="0"/>
<br/>
<br/>
Department:<form:select path="department.id" items="${depts }" itemLabel="departmentName" itemValue="id"></form:select>
<br/>
<input type="submit" value="提交" />
</form:form>
- SpringMVC的form标签
- 非SpringMVC的form标签
注意: 注意modelAttribute的使用,这里没有在域中使用添加对应的属性会报错
ava.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name ‘command’ available as request attribute
RESTRUL_CRUD_删除操作&处理静态资源
- 页面链接
RESTRUL_CRUD_修改操作

根据id查询员工对象,表单回显
页面链接
1
<td><a href="empEdit/${emp.id }">Edit</a></td>控制器方法
1
2
3
4
5
6@RequestMapping(value="empEdit/{id}", method=RequestMethod.GET)
public String editEmp(@PathVariable(value="id") Integer id, Map<String, Object>map) {
map.put("employee", employeeDao.get(id));
map.put("depts", departmentDao.getDepartments());
return "edit";
}修改页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>员工信息修改界面</title>
</head>
<body>
<form:form action="${pageContext.request.contextPath }/empUpdate"
method="POST" modelAttribute="employee">
<input type="hidden" name="id" value="${employee.id }" />
<input type="hidden" name="_method" value="PUT">
Email : <form:input path="email" />
<br>
<br>
Gender: 男<form:radiobutton path="gender" value="1"/>
女<form:radiobutton path="gender" value="0"/>
<br/>
<br/>
DeptName :
<form:select path="department.id" items="${depts }" itemLabel="departmentName" itemValue="id"></form:select>
<br>
<br>
<input type="submit" value="Submit"><br><br>
</form:form>
</body>
</html>
提交表单,修改数据
1 | @RequestMapping(value="empUpdate",method=RequestMethod.PUT) |
RESTRUL_CRUD_删除操作&处理静态资源
删除实验代码
页面链接
1
<td><a href="/empDelete/${emp.id }">Delete</a></td>控制器方法
1
2
3
4
5@RequestMapping(value="delEmp/{id}", method=RequestMethod.DELETE)
public String delEmp(@PathVariable(value="id") Integer id) {
employeeDao.delete(id);
return "redirect:/retrieveEmps";
}
HiddenHttpMethodFilter过滤器
- 发起请求,无法执行,因为delete请求必须通过post请求转换为delete请求,借助:HiddenHttpMethodFilter过滤器
需要使用jQuery来转换请求方式
- 加入jQuery库文件
1
/scripts/jquery-1.9.1.min.js
- jQuery库文件不起作用
1
警告: No mapping found for HTTP request with URI [/SpringMVC_03_RESTFul_CRUD/scripts/jquery-1.9.1.min.js] in DispatcherServlet with name 'springDispatcherServlet'
- 解决方法,SpringMVC 处理静态资源
SpringMVC 处理静态资源:
a)为什么会有这样的问题:
优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀 若将 DispatcherServlet 请求映射配置为 /, 则 Spring MVC 将捕获 WEB 容器的所有请求, 包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理, 因找不到对应处理器将导致错误。b)解决: 在 SpringMVC 的配置文件中配置 mvc:default-servlet-handler/
- 配置后,原来的请求又不好使了
1
2<!-- 在前端控制器对应的配置文件,增加 -->
<mvc:annotation-driven />关于mvc:default-servlet-handler/作用
mvc:default-servlet-handler/ 将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler,
它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,
就将该请求交由 WEB 应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由 DispatcherServlet 继续处理
一般 WEB 应用服务器默认的 Servlet 的名称都是 default。
若所使用的 WEB 服务器的默认 Servlet 名称不是 default,则需要通过 default-servlet-name 属性显式指定
参考:CATALINA_HOME/config/web.xml
1 | <servlet> |
该标签属性default-servlet-name默认值是”default”,可以省略。
mvc:default-servlet-handler/
1 | <mvc:default-servlet-handler default-servlet-name="default"/> |
通过jQuery转换为DELETE请求
1 | <td><a class="delete" href="empDelete/${emp.id }">Delete</a></td> |