【SpringMVC從入門到精通】05-RESTful 案例
目錄
RESTful 案例
1、準備工作
Step1、建立工程
File
-New
-Project
,預設Next
填寫專案工程基本資訊,點選FINISH
Step2、完善 POM
修改打包方式為war
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.vectorx</groupId> <artifactId>SpringMVC_RESTful</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.16</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.11</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> <version>3.0.15.RELEASE</version> </dependency> </dependencies> </project>
Step3、web.xml
File
-Project Structure
-Modules
,在Deployment Descriptors
中點選+
號新增Deployment Descriptor Location
,預設路徑中不帶src\main\webapp\
,需要手動新增
在web.xml
中新增兩個過濾器和一個前端控制器:
- 編碼過濾器:
CharacterEncodingFilter
(注意順序) - 處理
PUT
和DELETE
的請求過濾器:HiddenHttpMethodFilter
- 前端控制器:
DispatcherServlet
<?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"> <!--配置編碼過濾器--> <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>forceResponseEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置處理 PUT 和 DELETE 的請求過濾器--> <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> <!--配置 SpringMVC 前端控制器--> <servlet> <servlet-name>DispatcherServlet</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> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
Step4、SpringMVC 配置檔案
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--自動掃描包-->
<context:component-scan base-package="com.vectorx.restful"></context:component-scan>
<!--配置Thymeleaf檢視解析器-->
<bean id="ThymeleafViewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"></property>
<property name="characterEncoding" value="UTF-8"></property>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/"></property>
<property name="suffix" value=".html"></property>
<property name="templateMode" value="HTML5"></property>
<property name="characterEncoding" value="UTF-8"></property>
</bean>
</property>
</bean>
</property>
</bean>
<!--配置檢視控制器-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<!--配置MVC註解驅動-->
<mvc:annotation-driven/>
</beans>
Step5、建立 Controller、Dao、Bean
EmployeeController
@Controller
@RequestMapping("/employeeController")
public class EmployeeController {
@Autowired
private EmployeeDao employeeDao;
}
EmployeeDao
public interface EmployeeDao {
/**
* 增改員工資訊
*
* @param employee
*/
void save(Employee employee);
/**
* 刪除員工資訊
*
* @param id
*/
void deleteById(Integer id);
/**
* 獲取所有員工資訊
*
* @return
*/
List<Employee> getAll();
/**
* 根據員工id獲取員工資訊
*
* @param id
* @return
*/
Employee getById(Integer id);
}
EmployeeDaoImpl
@Repository
public class EmployeeDaoImpl implements EmployeeDao {
private static Map<Integer, Employee> employeeMap;
private static Integer initId = 1000;
static {
employeeMap = new HashMap<>();
employeeMap.put(++initId, new Employee(initId, "張三", "[email protected]", 1));
employeeMap.put(++initId, new Employee(initId, "李四", "[email protected]", 0));
employeeMap.put(++initId, new Employee(initId, "王五", "[email protected]", 0));
employeeMap.put(++initId, new Employee(initId, "趙六", "[email protected]", 1));
}
@Override
public void save(Employee employee) {
if (employee.getId() == null) {
employee.setId(++initId);
}
employeeMap.put(employee.getId(), employee);
}
@Override
public void deleteById(Integer id) {
employeeMap.remove(id);
}
@Override
public List<Employee> getAll() {
return new ArrayList<>(employeeMap.values());
}
@Override
public Employee getById(Integer id) {
return employeeMap.get(id);
}
}
Employee
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender;
public Employee() {
}
public Employee(Integer id, String lastName, String email, Integer gender) {
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
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;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", gender='" + gender + '\'' +
'}';
}
}
2、功能清單
功能 | URL路徑 | 請求方式 |
---|---|---|
訪問首頁 | / |
GET |
查詢所有員工 | /employee |
GET |
刪除員工 | /employee/1 |
DELETE |
跳轉到新增員工頁面 | /toAdd |
GET |
新增員工 | /employee |
POST |
跳轉到修改員工頁面 | /employee/2 |
GET |
修改員工 | /employee |
PUT |
3、訪問首頁
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁</title>
</head>
<body>
<h1>首頁</h1>
<a th:href="@{/employeeController/employee}">檢視員工資訊</a>
</body>
</html>
測試
4、列表功能
EmployeeController.java
@GetMapping("/employee")
public String getAllEmployee(Model model) {
List<Employee> employeeList = employeeDao.getAll();
model.addAttribute("employeeList", employeeList);
return "employeelist";
}
employeelist.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>員工資訊</title>
<style type="text/css">
table {
width: 50%;
border: 1px black solid;
border-collapse: collapse;
vertical-align: middle;
text-align: center;
}
tbody tr:nth-child(odd) {
background-color: rgb(211, 216, 188);
}
th, td {
border: 1px black solid;
}
</style>
</head>
<body>
<table>
<tr>
<th colspan="5">員工資訊</th>
</tr>
<tr>
<th>ID</th>
<th>姓名</th>
<th>郵箱</th>
<th>性別</th>
<th>操作</th>
</tr>
<tr th:each="employee : ${employeeList}">
<td th:text="${employee.id}"></td>
<td th:text="${employee.lastName}"></td>
<td th:text="${employee.email}"></td>
<td th:text="${employee.gender == 1 ? '男' : '女'}"></td>
<td>
<a href="">修改</a>
<a href="">刪除</a>
</td>
</tr>
</table>
</body>
</html>
效果
5、刪除功能
在webapp
下新建static/css
和static/js
,用來放置css
檔案和js
檔案
- 引入
static/js/vue.js
-
static/css/employeelist.css
作為外部樣式檔案 -
static/js/employeelist.js
作為外部js
檔案
employeelist.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>員工資訊</title>
<link th:href="@{/static/css/employeelist.css}" rel="stylesheet" type="text/css"/>
</head>
<body>
<table id="employeeTable">
<tr>
<th colspan="5">員工資訊</th>
</tr>
<tr>
<th>ID</th>
<th>姓名</th>
<th>郵箱</th>
<th>性別</th>
<th>操作</th>
</tr>
<tr th:each="employee : ${employeeList}">
<td th:text="${employee.id}"></td>
<td th:text="${employee.lastName}"></td>
<td th:text="${employee.email}"></td>
<td th:text="${employee.gender == 1 ? '男' : '女'}"></td>
<td>
<a href="">修改</a>
<!--<a th:href="@{/employeeController/employee/}+${employee.id}">刪除</a>-->
<a @click="deleteEmployee" th:href="@{'/employeeController/employee/'+${employee.id}}">刪除</a>
</td>
</tr>
</table>
<form method="post" id="deleteForm">
<input type="hidden" name="_method" value="delete"/>
</form>
<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
<script type="text/javascript" th:src="@{/static/js/employeelist.js}"></script>
</body>
</html>
employeelist.css
table {
width: 50%;
border: 1px black solid;
border-collapse: collapse;
/* 垂直水平居中 */
vertical-align: middle;
text-align: center;
}
/* 間隔變色 */
tbody tr:nth-child(odd) {
background-color: rgb(211, 216, 188);
}
th, td {
border: 1px black solid;
}
employeelist.js
var vue = new Vue({
el: "#employeeTable",
methods: {
deleteEmployee: function (event) {
if (confirm('確認刪除嗎?')) {
var deleteForm = document.getElementById("deleteForm");
deleteForm.action = event.target.href;
deleteForm.submit();
}
event.preventDefault();
}
}
});
SpringMVC 配置檔案
<!--開放靜態資源訪問-->
<mvc:default-servlet-handler/>
效果
6、新增功能
employeelist.html
<!-- 略 -->
<tr>
<th>ID</th>
<th>姓名</th>
<th>郵箱</th>
<th>性別</th>
<th>操作 <a th:href="@{/employeeController/toAdd}">新增</a><br/></th>
</tr>
<!-- 略 -->
employeeadd.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>新增員工</title>
</head>
<body>
<h1>新增員工</h1>
<form th:action="@{/employeeController/employee}" method="post">
姓名:<input type="text" name="lastName"/><br/>
郵箱:<input type="text" name="email"/><br/>
性別:<input type="radio" name="gender" value="1">男
<input type="radio" name="gender" value="0">女<br/>
<input type="submit" value="新增">
</form>
</body>
</html>
EmployeeController.java
@GetMapping("/toAdd")
public String toAdd() {
return "employeeadd";
}
@PostMapping("/employee")
public String addEmployee(Employee employee) {
employeeDao.save(employee);
return "redirect:/employeeController/employee";
}
效果
7、修改功能
employeelist.html
<!-- 略 -->
<a th:href="@{/employeeController/employee/}+${employee.id}">修改</a>
<!-- 略 -->
employeeedit.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>修改員工</title>
</head>
<body>
<h1>修改員工</h1>
<form th:action="@{/employeeController/employee}" method="post">
<input type="hidden" name="_method" th:value="put">
<input type="hidden" name="id" th:value="${employee.id}">
姓名:<input type="text" name="lastName" th:value="${employee.lastName}"/><br/>
郵箱:<input type="text" name="email" th:value="${employee.email}"/><br/>
性別:<input type="radio" name="gender" value="1" th:field="${employee.gender}">男
<input type="radio" name="gender" value="0" th:field="${employee.gender}">女<br/>
<input type="submit" value="修改">
</form>
</body>
</html>
EmployeeController.java
@GetMapping("/employee/{id}")
public String getEmployeeById(@PathVariable("id") Integer id, Model model) {
Employee employee = employeeDao.getById(id);
model.addAttribute("employee", employee);
return "employeeedit";
}
@PutMapping("/employee")
public String editEmployee(Employee employee) {
employeeDao.save(employee);
return "redirect:/employeeController/employee";
}
效果
注意點
當前 SpringMVC 配置檔案中存在這樣幾個配置
<!--配置檢視控制器-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<!--開放靜態資源訪問-->
<mvc:default-servlet-handler/>
<!--配置MVC註解驅動-->
<mvc:annotation-driven/>
各個配置的作用
-
view-controller
:簡化頁面跳轉實現 -
default-servlet-handler
:開放靜態資源訪問 -
annotation-driven
:這裡主要有 2 個作用- 1)解決因配置檢視控制器導致其他請求失效(404)的問題
- 2)解決因配置靜態資源訪問導致其他請求失效(404)的問題
回憶:在 04-SpringMVC 檢視 - 5、檢視控制器 view-controller 中有介紹過“MVC 註解驅動”功能作用
annotation-driven
需要與view-controller
、default-servlet-handler
配合使用
annotation-driven
與view-controller
的關係
- 當配置了
view-controller
而不配置annotation-driven
,那麼除了檢視控制器中配置的請求,其他控制器方法將無法訪問,即其他請求失效(404) - 當配置了
view-controller
也配置了annotation-driven
,那麼檢視控制器中配置的請求和其他控制器方法都能夠正常訪問
annotation-driven
與default-servlet-handler
的關係
- 當配置了
default-servlet-handler
而不配置annotation-driven
,那麼所有請求都將交給DefaultServlet
處理,DispatcherServlet
將失效 - 當配置了
default-servlet-handler
也配置了annotation-driven
,那麼所有請求將先交給DispatcherServlet
處理,處理不了再交給DefaultServlet
處理