來來來,讓一下,客官,您要的REST清蒸CRUD來了,火候剛剛好,不油不膩,請慢用~~~
如果說前面是准備調料,洗菜,切菜,擺盤,那么今天就來完整的上道菜,主要說的是基於REST風格實現數據的增刪改查(CRUD)操作。
用料
entity:Employee + Department
對於這樣的實體類大家肯定很熟悉,一個Employee就是一個員工,一個Department就是一個部門,一個員工只屬於一個部門,一個部門可以對應多個員工。
Employee.java
package com.jackie.springmvc.crud.entities;
import java.util.Date;
import javax.validation.constraints.Past;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;
public class Employee {
private Integer id;
@NotEmpty
private String lastName;
@Email
private String email;
//1 male, 0 female
private Integer gender;
private Department department;
@Past
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;
@NumberFormat(pattern="#,###,###.#")
private Float salary;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Float getSalary() {
return salary;
}
public void setSalary(Float salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email="
+ email + ", gender=" + gender + ", department=" + department
+ ", birth=" + birth + ", salary=" + salary + "]";
}
public Employee(Integer id, String lastName, String email, Integer gender,
Department department) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.department = department;
}
public Employee() {
// TODO Auto-generated constructor stub
}
}
Department.java
package com.jackie.springmvc.crud.entities;
public class Department {
private Integer id;
private String departmentName;
public Department() {
// TODO Auto-generated constructor stub
}
public Department(int i, String string) {
this.id = i;
this.departmentName = string;
}
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;
}
@Override
public String toString() {
return "Department [id=" + id + ", departmentName=" + departmentName
+ "]";
}
}
dao層:除了entity層,我們還需要有dao層,用於對於entity的增刪改查的操作,這里對應的有EmployeeDao和DepartmentDao
EmployeeDao.java
package com.jackie.springmvc.crud.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 com.jackie.springmvc.crud.entities.Department;
import com.jackie.springmvc.crud.entities.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);
}
}
該dao提供了:1. 添加保存一個employee——save方法
2. 獲取所有員工信息——getAll方法
3. 根據指定員工id查找員工——get方法
4. 根據指定員工id刪除員工——delete方法
DepartmentDao.java
package com.jackie.springmvc.crud.dao;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Repository;
import com.jackie.springmvc.crud.entities.Department;
@Repository
public class DepartmentDao {
private static Map<Integer, Department> departments = null;
static{
departments = new HashMap<Integer, Department>();
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<Department> getDepartments(){
return departments.values();
}
public Department getDepartment(Integer id){
return departments.get(id);
}
}
該dao提供了:1. 查找所有部門信息——getDepartments
2. 根據指定id查找相應的部門信息——getDepartment
另外這里需要用到的所有jar包都在這里
http://pan.baidu.com/s/1qXT180c 提取碼:z7q2
用料齊活了, 就開始做菜了,要做的分別是REST清蒸C(添加記錄)、REST油炸R(查詢記錄)、REST紅燒U(更新記錄)和REST水煮D(刪除記錄)。
1. 查詢記錄
這個很簡單,跟前幾篇介紹的套路差不多,新建一個index.jsp,放入一個用於查詢的超鏈接
<a href="emps">list all employees</a><br/>
相應的在Handler中需要添加映射支持,這里新建一個EmployeeHandler類
package com.jackie.springmvc.crud.handlers;
import java.util.Map;
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.RequestMethod;
import com.jackie.springmvc.crud.dao.EmployeeDao;
@Controller
public class EmployeeHandler {
@Autowired
private EmployeeDao employeeDao;
@RequestMapping("/emps")
public String list(Map<String, Object> map){
map.put("employees", employeeDao.getAll());
return "list";
}
}
注意:
這里RequestMapping中沒有指明RequestMethod的請求類型,默認是GET方式。
最終我們需要將查詢的數據解析出來放到頁面上,這個頁面就是list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:if test="${empty requestScope.employees}">
沒有員工信息
</c:if>
<c:if test="${!empty requestScope.employees }">
<table border="1" cellpadding="10" cellspacing="0">
<tr>
<th>ID</th>
<th>LastName</th>
<th>Email</th>
<th>Gender</th>
<th>Department</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<c:forEach items="${requestScope.employees }" var="emp">
<tr>
<td>${emp.id }</td>
<td>${emp.lastName }</td>
<td>${emp.email }</td>
<td>${emp.gender==0?'Female':'Male' }</td>
<td>${emp.department.departmentName }</td>
<td><a href="emp/${emp.id}">Edit</a></td>
<td><a class="delete" href="emp/${emp.id}">Delete</a></td>
</tr>
</c:forEach>
</table>
</c:if>
<br><br>
</body>
</html>
這里通過表格的方式顯示,表格的每一行顯示一個員工記錄。
如果Handler層沒有傳入employee,則顯示“沒有員工信息”。
如果從Handler層傳入查詢到的employee的信息,則通過遍歷的方式查詢每條記錄並顯示在對應的表格中。
結果如下:

這里查詢了所有的員工信息,為簡便起見,這里的員工信息並不是從數據庫中讀取的,而是在EmployeeDao中通過靜態模塊聲明構造的,將每個員工信息放入一個map集合中。
2. 添加記錄
添加記錄即在原有的數據集合基礎上,再新建一個員工信息,我們需要為員工的每個屬性填充值,所以我們需要一個頁面來為這些字段賦值,這個頁面就叫input.jsp。
添加員工信息的入口鏈接就放在list.jsp中
<a href = "emp">add new employee</a><br/>
同時在EmployeeHandler中添加映射
@RequestMapping(value="/emp", method=RequestMethod.GET)
public String input(Map<String, Object> map){
map.put("departments", departmentDao.getDepartments());
map.put("employee", new Employee());
return "input";
}
input.jsp
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form:form action="emp" method="POST" modelAttribute="employee">
<!-- path 屬性對應html表單標簽的name屬性 -->
LastName: <form:input path="lastName"></form:input><br>
Email:<form:input path="email"></form:input><br>
<%
Map<String, String> genders = new HashMap<String, String>();
genders.put("1", "male");
genders.put("0", "female");
request.setAttribute("genders", genders);
%>
Gender:<form:radiobuttons path="gender" items="${genders }"/><br>
Department:<form:select path="department.id" items="${departments }" itemLabel="departmentName" itemValue="id"></form:select><br>
<input type="submit" value="Submit"/>
</form:form>
</body>
</html>
先不看代碼,至此你就能看到這樣的效果:

到這里還沒完,我們還需要寫一個保存的handler接口,在EmployeeHandler.java中
@RequestMapping(value="/emp", method=RequestMethod.POST)
public String save(Employee employee){
employeeDao.save(employee);
return "redirect:/emps";
}
主要實現將新建的員工記錄保存到employee集合中。
這樣我們就能夠成功的添加一條記錄了

注意:
這里有幾個問題需要聲明
(1). 為什么使用form標簽:可以更快速開發表單頁面,而且可以方便的進行表單值的回顯
(2) 為什么要在EmployeeHandler類中添加map.put("employee", employee),並且在input.jsp頁面的form:form標簽中添加modelAttribute="employee"
如果沒有這樣的聲明代碼,在運行中會出現報錯信息如下:
HTTP Status 500 - An exception occurred processing JSP page /WEB-INF/views/input.jsp at line 23 type Exception report message An exception occurred processing JSP page /WEB-INF/views/input.jsp at line 23 description The server encountered an internal error that prevented it from fulfilling this request. exception org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/views/input.jsp at line 23 20: --> 21: <form:form action="emp" method="POST"> 22: <!-- path 灞炴�у搴攈tml琛ㄥ崟鏍囩鐨刵ame灞炴�� --> 23: LastName: <form:input path="lastName"></form:input><br> 24: Email:<form:input path="email"></form:input><br> 25: <% 26: Map<String, String> genders = new HashMap<String, String>(); Stacktrace: org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:574) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:471) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:209) org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:267) org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1221) org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1005) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:952) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) javax.servlet.http.HttpServlet.service(HttpServlet.java:622) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) root cause java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:168) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:188) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:154) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.autogenerateId(AbstractDataBoundFormElementTag.java:141) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.resolveId(AbstractDataBoundFormElementTag.java:132) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.java:116) org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.java:422) org.springframework.web.servlet.tags.form.InputTag.writeTagContent(InputTag.java:142) org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:84) org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:80) org.apache.jsp.WEB_002dINF.views.input_jsp._jspx_meth_form_005finput_005f0(input_jsp.java:244) org.apache.jsp.WEB_002dINF.views.input_jsp._jspService(input_jsp.java:168) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:438) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:209) org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:267) org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1221) org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1005) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:952) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) javax.servlet.http.HttpServlet.service(HttpServlet.java:622) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) note The full stack trace of the root cause is available in the Apache Tomcat/8.0.36 logs.
於是在handler中將employee放入map集合中,此時運行,仍然報錯
HTTP Status 500 - java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute type Exception report message java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute description The server encountered an internal error that prevented it from fulfilling this request. exception org.apache.jasper.JasperException: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:555) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:471) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:209) org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:267) org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1221) org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1005) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:952) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) javax.servlet.http.HttpServlet.service(HttpServlet.java:622) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) root cause java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:168) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:188) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:154) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.autogenerateId(AbstractDataBoundFormElementTag.java:141) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.resolveId(AbstractDataBoundFormElementTag.java:132) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.java:116) org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.java:422) org.springframework.web.servlet.tags.form.InputTag.writeTagContent(InputTag.java:142) org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:84) org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:80) org.apache.jsp.WEB_002dINF.views.input_jsp._jspx_meth_form_005finput_005f0(input_jsp.java:244) org.apache.jsp.WEB_002dINF.views.input_jsp._jspService(input_jsp.java:168) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:438) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:209) org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:267) org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1221) org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1005) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:952) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) javax.servlet.http.HttpServlet.service(HttpServlet.java:622) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) note The full stack trace of the root cause is available in the Apache Tomcat/8.0.36 logs.
這時候在form:form中加入modelAttribute="employee",再次運行,就能夠成功添加記錄了。
這是為什么呢,因為表單在顯示的時候會做一個檢查,如果表單的字段在request的bean中不能一一對應,就會無法顯示並報錯,說白了就是這里加上了employee這個bean后,這個對象中的各個屬性如email、gender和表單上的字段都能夠對應起來了,校驗通過,就能正常添加保存了。
注意input.jsp中modelAttribute的值要和handler中放進map集合的key值一致,默認在頁面上這個modelAttribute的值為command,所以你會看到報錯信息中頻繁的出現command。
(3). <form:radiobuttons>這個標簽中有一下屬性:
items:存放具體的數據集合,可以是String、Map或List類型
itemValue:指定radio的value值,可以使集合中bean的一個屬性值
itemLabel:radio的label值
3. 刪除記錄
其實從前面的list.jsp的表格中已經看出來了,在每條記錄后面都有一個DELETE選項,用於刪除該項記錄,那么具體怎么實現
這里首先要該Delete項對應的href,在list.jsp中
<td><a href="emp/${emp.id}">Delete</a></td>
我們將href的值賦值為一個請求路徑,顯然我們需要在handler中添加映射處理:
@RequestMapping(value="/emp/{id}", method=RequestMethod.DELETE)
public String delete(@PathVariable("id") Integer id){
employeeDao.delete(id);
return "redirect:/emps";
}
刪除完記錄后重定向到emps即list.jsp頁面。
效果如下

注意:
(1). 這里要明白,實際上我們在頁面上發送的是一個rest的delete請求,但是通過<a href>的超鏈接方式我們只能發送get請求,而且前面我們說過,對於form來說只能發get和post請求,如果要發delete和put,則需要偽裝成post請求,再在handler處理類中進行解析處理。
對於這個問題,我們想到了jquery,於是引入jquery庫到WebContent/scripts目錄下,版本是1.9.1
首先需要一個form表單,因為無可厚非,只有表單才能提交post請求
<form action="" method="POST"> <input type="hidden" name="_method" value="DELETE"/> </form>
在list.jsp中引入jquery庫
<script type="text/javascript" src="scripts/jquery-1.9.1.min.js"></script>
在delete對應的<a>中加入class=“delete”,方便后面使用jquery進行元素定位
寫入功能實現代碼:
<script type="text/javascript">
$(function(){
$(".delete").click(function(){
var href = $(this).attr("href");
$("form").attr("action", href).submit();
return false;
});
})
</script>
這段代碼的意思無非就是:找到delete刪除元素,提取器href屬性值,並將其賦給新添加的form表單中,當點擊超鏈接后相當於提交form,並移交給定義好的hanlder接口。
(2). 又要啰嗦下,對於靜態資源來說,因為我們在web.xml中聲明spring是攔截了所有請求,所以對於靜態資源我們也統統招收,攔截不誤,但是顯然我們沒有與這個靜態資源對應的映射,也就是說spring攔截下來了,卻沒有能力處理,這里介紹在springmvc.xml中添加兩個標簽就能解決問題
<mvc:default-servlet-handler/> <mvc:annotation-driven></mvc:annotation-driven>
在前面的章節中有介紹過其他的方法,就是在web.xml中聲明各種靜態資源的支持,比較繁瑣傻瓜點^^
(3). 為什么添加了這個<mvc:default-servlet-handler/>就能解決問題:
Default-servlet-handler將在SpringMVC上下文中定義一個DefaultServletHttpRequestHandler,它會對進入DispatcherServlet的請求進行篩查,如果發現是沒有經過映射的請求,就將該請求交由WEB應用服務器默認的Servlet處理。如果不是靜態資源的請求,才由DispatcherServlet繼續處理。
一般WEB應用服務器默認的Servlet的名稱都是default,若所使用的WEB服務器的默認Serlvet名稱不是default,則需要通過default-servlet-name屬性顯示指定。
這里的小問題比較多,不知道你暈了沒,但是到目前為止,好像一個簡易的框架就有了,有了后台的java,還有模板jsp技術,以及對於dom操作的Jquery,當然我們還少了一個真正的數據庫。
4. 更新記錄
更新操作實際上是分為兩步:查找要修改的記錄 + 修改記錄並保存
(1). 查找記錄
通過get方式映射到emp/${id}
與delete選項類似,在list.jsp改為
<td><a href="emp/${emp.id}">Edit</a></td>
同時在Handler添加相應映射
@RequestMapping(value="/emp/{id}", method=RequestMethod.GET)
public String input(@PathVariable("id") Integer id, Map<String, Object> map){
map.put("employee", employeeDao.get(id));
map.put("departments", departmentDao.getDepartments());
return "input";
}
這樣就可以定位到選中的employee對象上,並跳轉到input.jsp界面上。
(2). 修改並保存
這里要說清楚,進入input.jsp頁面會有兩種情況,一種是添加一條Employee記錄,二是修改一條Employee記錄,而且我們從前面的界面可以看出我們並不修改LastName這個字段,那我們如果讓input.jsp具有辨識是從添加記錄那還是修改記錄那跳轉過來的呢,於是我們需要在input.jsp中加入判斷
<c:if test="${employee.id == null }">
<!-- path 屬性對應 html 表單標簽的 name 屬性值 -->
LastName: <form:input path="lastName" />
<form:errors path="lastName"></form:errors>
</c:if>
<c:if test="${employee.id != null }">
<form:hidden path="id" />
<input type="hidden" name="_method" value="PUT" />
</c:if>
如果傳過來的employee中id存在,那說明是修改更新,如果為空,說明是新建一條記錄。
同時,老套路,這里還是利用隱藏域hidden來發送一個put請求到handler
在EmployeeHandler中
@ModelAttribute
public void getEmployee(@RequestParam(value="id",required=false) Integer id,
Map<String, Object> map){
if(id != null){
map.put("employee", employeeDao.get(id));
}
}
@RequestMapping(value="/emp", method=RequestMethod.PUT)
public String update(Employee employee){
employeeDao.save(employee);
return "redirect:/emps";
}
之所以這里有ModelAttribute前篇已經說過,如果沒有話,更新完后這個LastName字段就會為空。
最終效果如下:

至此,我們學習了:
1. 基於REST風格查詢記錄
2. 基於REST風格添加記錄
3. 基於REST風格刪除記錄
4. 基於REST風格更新記錄
5. 引入JQuery改變請求方式
6. 明白了Request中bean必須要和請求表單中的屬性對應
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注JackieZheng的微信公眾號,我會將我的文章推送給您,並和您一起分享我日常閱讀過的優質文章。

