参考视频:SpringMVC教程,SpringMVC从零到精通,老杜SpringMVC,动力节点SpringMVC
1. RESTFul编程风格
1.1 RESTFul是什么
RESTFul是WEB服务接口
的一种设计风格。
RESTFul定义了一组约束条件和规范,可以让WEB服务接口
更加简洁、易于理解、易于扩展、安全可靠。
RESTFul对一个WEB服务接口
都规定了哪些东西?
- 对请求的URL格式有约束和规范
- 对HTTP的请求方式有约束和规范
- 对请求和响应的数据格式有约束和规范
- 对HTTP状态码有约束和规范
- 等 ……
REST对请求方式的约束是这样的:
- 查询必须发送GET请求
- 新增必须发送POST请求
- 修改必须发送PUT请求
- 删除必须发送DELETE请求
REST对URL的约束是这样的:
传统的URL:get请求,/springmvc/getUserById?id=1
REST风格的URL:get请求,/springmvc/user/1
传统的URL:get请求,/springmvc/deleteUserById?id=1
REST风格的URL:delete请求, /springmvc/user/1
RESTFul对URL的约束和规范的核心是:通过采用 不同的请求方式
+ URL
来确定WEB服务中的资源。
RESTful 的英文全称是 Representational State Transfer(表述性状态转移)。简称REST。
表述性(Representational)是:URI + 请求方式。
状态(State)是:服务器端的数据。
转移(Transfer)是:变化。
表述性状态转移是指:通过 URI + 请求方式 来控制服务器端数据的变化。
1.2 RESTFul风格与传统方式对比
传统的 URL 与 RESTful URL 的区别是传统的 URL 是基于方法名进行资源访问和操作,而 RESTful URL 是基于资源的结构和状态进行操作的。下面是一张表格,展示两者之间的具体区别:
传统的 URL |
RESTful URL |
GET /getUserById?id=1 |
GET /user/1 |
GET /getAllUser |
GET /user |
POST /addUser |
POST /user |
POST /modifyUser |
PUT /user |
GET /deleteUserById?id=1 |
DELETE /user/1 |
从上表中我们可以看出,传统的URL是基于动作的,而 RESTful URL 是基于资源和状态的,因此 RESTful URL 更加清晰和易于理解,这也是 REST 架构风格被广泛使用的主要原因之一。
1.3 RESTFul方式演示查询
RESTFul规范中规定,如果要查询数据,需要发送GET请求。
1.3.1 查询所有(GET /api/user)
1、准备springmvc.xml文件
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
| <?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.muyoukule.controller"/>
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver"> <property name="characterEncoding" value="UTF-8"/> <property name="order" value="1"/> <property name="templateEngine"> <bean class="org.thymeleaf.spring6.SpringTemplateEngine"> <property name="templateResolver"> <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver"> <property name="prefix" value="/WEB-INF/thymeleaf/"/> <property name="suffix" value=".html"/> <property name="templateMode" value="HTML"/> <property name="characterEncoding" value="UTF-8"/> </bean> </property> </bean> </property> </bean>
<mvc:annotation-driven/>
<mvc:view-controller path="/" view-name="index"/> </beans>
|
2、准备首页index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <h1>测试RESTFul编程风格</h1> <hr>
<a th:href="@{/user}">查看用户列表</a><br>
</body> </html>
|
3、控制器Controller:
1 2 3 4 5 6 7 8 9
| @Controller public class UserController {
@RequestMapping(value = "/user", method = RequestMethod.GET) public String getAll() { System.out.println("正在查询所有用户信息...."); return "ok"; } }
|
4、视图页面:
1 2 3 4 5 6 7 8 9 10
| <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>ok</title> </head> <body> <h1>OK!</h1> </body> </html>
|
5、启动服务器,测试:http://localhost:8080/springmvc
6、控制台打印:
1.3.2 根据id查询(GET /api/user/1)
1、index.html添加超链接
1 2
| <a th:href="@{/user/110}">查询id=110的这个用户信息</a><br>
|
2、编写Controller
1 2 3 4 5
| @RequestMapping(value = "/user/{id}", method = RequestMethod.GET) public String getById(@PathVariable("id") String id){ System.out.println("正在根据用户id查询用户信息...,用户id是" + id); return "ok"; }
|
3、启动服务器测试:
4、控制台打印:
1
| 正在根据用户id查询用户信息...,用户id是110
|
1.4 RESTFul方式演示增加(POST /api/user)
RESTFul规范中规定,如果要进行保存操作,需要发送POST请求。
1、准备User实体(采用Lombok简化)
1 2 3 4 5 6 7 8
| @Data @NoArgsConstructor @AllArgsConstructor public class User { private String username; private Integer password; private String age; }
|
PS:如需使用Lombok,需要在pom.xml引入依赖
1 2 3 4 5 6
| <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.28</version> </dependency>
|
2、index.html添加表单
1 2 3 4 5 6 7
| <form th:action="@{/user}" method="post"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> 年龄:<input type="text" name="age"><br> <input type="submit" value="保存"> </form>
|
3、编写Controller
1 2 3 4 5
| @RequestMapping(value = "/user", method = RequestMethod.POST) public String save(User user) { System.out.println("正在保存user用户信息..." + user); return "ok"; }
|
4、启动服务器测试:
5、控制台打印:
1
| 正在保存user用户信息...User(username=木又枯了, password=123, age=18)
|
1.5 RESTFul方式演示修改
RESTFul规范中规定,如果要进行保存操作,需要发送PUT请求。
如何发送PUT请求?
- 首先你必须是一个POST请求。
- 在发送POST请求的时候,提交这样的数据:
_method=PUT
- 在web.xml文件配置SpringMVC提供的过滤器:
HiddenHttpMethodFilter
实践一下:
1、index.html添加表单
1 2 3 4 5 6 7 8 9 10 11
| <form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="put">
用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> 年龄:<input type="text" name="age"><br> <input type="submit" value="修改"> </form>
|
2、配置隐藏的HTTP请求方式过滤器
PS:如果添加了字符编码过滤器,一定要在字符编码过滤器后面配置,否则字符编码过滤器会失效
1 2 3 4 5 6 7 8 9
| <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>
|
3、编写Controller
1 2 3 4 5
| @RequestMapping(value = "/api/user", method = RequestMethod.PUT) public String update(String username){ System.out.println("修改用户信息,用户名:" + username); return "ok"; }
|
4、测试结果:
5、控制台打印:
1
| 正在修改用户信息:User(username=木又枯了z, password=123321, age=20)
|
1.6 RESTFul方式演示删除
1、index.html添加删除按钮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
<a th:href="@{/user/120}" onclick="del(event)">删除用户id=120的用户信息</a>
<form id="delForm" method="post"> <input type="hidden" name="_method" value="delete"> </form>
<script> function del(event){ let delForm = document.getElementById("delForm"); delForm.action = event.target.href; delForm.submit(); event.preventDefault(); } </script>
|
2、配置隐藏的HTTP请求方式过滤器
PS:如果添加了字符编码过滤器,一定要在字符编码过滤器后面配置,否则字符编码过滤器会失效
1 2 3 4 5 6 7 8 9
| <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>
|
3、编写Controller
1 2 3 4 5
| @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE) public String del(@PathVariable("id") String id) { System.out.println("正在删除用户:" + id); return "ok"; }
|
4、测试结果:
5、控制台打印:
1.7 HiddenHttpMethodFilter
HiddenHttpMethodFilter
是Spring MVC框架提供的,专门用于RESTFul编程风格。
实现原理可以通过源码查看:
通过源码可以看到,if语句中,首先判断是否为POST请求,如果是POST请求,调用request.getParameter(this.methodParam)
。可以看到this.methodParam
是_method
,这样就要求我们在提交请求方式的时候必须采用这个格式:_method=put
。获取到请求方式之后,调用了toUpperCase
转换成大写了。因此前端页面中小写的put
或者大写的PUT
都是可以的。if语句中嵌套的if语句说的是,只有请求方式是 PUT
,DELETE
,PATCH
的时候会创建HttpMethodRequestWrapper
对象。而HttpMethodRequestWrapper
对象的构造方法是这样的:
这样method就从POST
变成了:PUT/DELETE/PATCH
。
PS:重点注意CharacterEncodingFilter和HiddenHttpMethodFilter的顺序!!!!
在HiddenHttpMethodFilter
源码中有这样一行代码:
1
| String paramValue = request.getParameter(this.methodParam);
|
大家是否还记得,字符编码过滤器执行之前不能调用request.getParameter()
方法,如果提前调用了,乱码问题就无法解决了。因为request.setCharacterEncoding()
方法的执行必须在所有request.getParameter()
方法之前执行。
因此这两个过滤器就有先后顺序的要求,在web.xml文件中,应该先配置CharacterEncodingFilter,然后再配置HiddenHttpMethodFilter。
2. 使用RESTFul实现用户管理系统
2.1 静态页面准备
文件包括:user.css、user_index.html、user_list.html、user_add.html、user_edit.html。代码如下:
2.1.1 user.css
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| .header { background-color: #f2f2f2; padding: 20px; text-align: center; }
ul { list-style-type: none; margin: 0; padding: 0; overflow: hidden; background-color: #333; }
li { float: left; }
li a { display: block; color: white; text-align: center; padding: 14px 16px; text-decoration: none; }
li a:hover:not(.active) { background-color: #111; }
.active { background-color: #4CAF50; }
form { width: 50%; margin: 0 auto; padding: 20px; border: 1px solid #ddd; border-radius: 4px; }
label { display: block; margin-bottom: 8px; }
input[type="text"], input[type="email"], select { width: 100%; padding: 6px 10px; margin: 8px 0; box-sizing: border-box; border: 1px solid #555; border-radius: 4px; font-size: 16px; }
button[type="submit"] { padding: 10px; background-color: #4CAF50; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
button[type="submit"]:hover { background-color: #3e8e41; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
tr:nth-child(even) { background-color: #f2f2f2; }
.header { background-color: #f2f2f2; padding: 20px; text-align: center; }
a { text-decoration: none; color: #333; }
.add-button { margin-bottom: 20px; padding: 10px; background-color: #4CAF50; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
.add-button:hover { background-color: #3e8e41; }
|
2.1.2 user_index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户管理系统</title> <link rel="stylesheet" href="user.css" type="text/css"></link> </head> <body> <div class="header"> <h1>用户管理系统</h1> </div> <ul> <li><a class="active" href="user_list.html">用户列表</a></li> </ul> </body> </html>
|
2.1.3 user_list.html
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 48 49
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户列表</title> <link rel="stylesheet" href="user.css" type="text/css"></link> </head> <body> <div class="header"> <h1>用户列表</h1> </div> <div class="add-button-wrapper"> <a class="add-button" href="user_add.html">新增用户</a> </div> <table> <thead> <tr> <th>编号</th> <th>用户名</th> <th>性别</th> <th>邮箱</th> <th>操作</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>张三</td> <td>男</td> <td>zhangsan@powernode.com</td> <td> 修改 删除 </td> </tr> <tr> <td>2</td> <td>李四</td> <td>女</td> <td>lisi@powernode.com</td> <td> 修改 删除 </td> </tr> </tbody> </table> </body> </html>
|
2.1.4 user_add.html
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>新增用户</title> <link rel="stylesheet" href="user.css" type="text/css"></link> </head> <body> <h1>新增用户</h1> <form> <label>用户名:</label> <input type="text" name="username" required>
<label>性别:</label> <select name="gender" required> <option value="">-- 请选择 --</option> <option value="1">男</option> <option value="0">女</option> </select>
<label>邮箱:</label> <input type="email" name="email" required>
<button type="submit">保存</button> </form> </body> </html>
|
2.1.5 user_edit.html
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改用户</title> <link rel="stylesheet" href="user.css" type="text/css"></link> </head> <body> <h1>修改用户</h1> <form> <label>用户名:</label> <input type="text" name="username" value="张三" required>
<label>性别:</label> <select name="gender" required> <option value="">-- 请选择 --</option> <option value="1" selected>男</option> <option value="0">女</option> </select>
<label>邮箱:</label> <input type="email" name="email" value="zhangsan@powernode.com" required>
<button type="submit">修改</button> </form> </body> </html>
|
2.2 SpringMVC环境搭建
1、创建module:usermgt
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 48 49 50 51 52 53
| <?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.muyoukule</groupId> <artifactId>usermgt</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging>
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>6.1.4</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring6</artifactId> <version>3.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.28</version> </dependency> </dependencies>
</project>
|
2、添加web支持
3、配置web.xml文件
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 48 49 50 51 52 53 54
| <?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>forceRequestEncoding</param-name> <param-value>true</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>
<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>
<servlet> <servlet-name>springmvc</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>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
</web-app>
|
注意两个过滤器Filter的配置顺序:先配置 CharacterEncodingFilter
,后配置 HiddenHttpMethodFilter
4、配置springmvc.xml文件
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
| <?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.muyoukule"/>
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver"> <property name="characterEncoding" value="UTF-8"/> <property name="order" value="1"/> <property name="templateEngine"> <bean class="org.thymeleaf.spring6.SpringTemplateEngine"> <property name="templateResolver"> <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver"> <property name="prefix" value="/WEB-INF/thymeleaf/"/> <property name="suffix" value=".html"/> <property name="templateMode" value="HTML"/> <property name="characterEncoding" value="UTF-8"/> </bean> </property> </bean> </property> </bean>
<mvc:annotation-driven/>
<mvc:default-servlet-handler/> </beans>
|
5、创建packag
6、在WEB-INF目录下新建:thymeleaf目录
最终创建好的项目结构如下:
2.3 显示首页
1、在应用的根下新建目录:static/css
,将user.css文件拷贝进去。
2、将user_index.html拷贝到WEB-INF/thymeleaf目录下:
代码有两处需要修改:
3、在springmvc.xml文件中配置视图控制器映射:
1 2
| <mvc:view-controller path="/" view-name="user_index"/>
|
4、部署,配置启动服务器,测试:
2.4 实现用户列表
1、修改user_index.html中的超链接:
1
| <li><a class="active" th:href="@{/user}">用户列表</a></li>
|
2、编写pojo:User
1 2 3 4 5 6 7 8 9
| @Data @NoArgsConstructor @AllArgsConstructor public class User { private Long id; private String username; private String email; private Integer gender; }
|
3、编写UserDao,提供selectAll方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Repository public class UserDao { private static List<User> users = new ArrayList<>();
static { User user1 = new User(10001L, "张三", "zhangsan@example.com", 1); User user2 = new User(10002L, "李四", "lisi@example.com", 1); User user3 = new User(10003L, "王五", "wangwu@example.com", 1); User user4 = new User(10004L, "赵六", "zhaoliu@example.com", 0); User user5 = new User(10005L, "钱七", "qianqi@example.com", 0); users.add(user1); users.add(user2); users.add(user3); users.add(user4); users.add(user5); }
public List<User> selectAll() { return users; } }
|
4、编写控制器UserController:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Controller public class UserController {
@Autowired private UserDao userDao;
@GetMapping("/user") public String list(Model model) { List<User> users = userDao.selectAll(); model.addAttribute("users", users); return "user_list"; } }
|
5、将user_list.html拷贝到thymeleaf目录下,并进行代码修改,显示用户列表:
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
| <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>用户列表</title> <link rel="stylesheet" th:href="@{/static/css/user.css}" type="text/css"></link> </head> <body> <div class="header"> <h1>用户列表</h1> </div> <div class="add-button-wrapper"> <a class="add-button" href="user_add.html">新增用户</a> </div> <table> <thead> <tr> <th>编号</th> <th>用户名</th> <th>性别</th> <th>邮箱</th> <th>操作</th> </tr> </thead> <tbody>
<tr th:each="user : ${users}"> <td th:text="${user.id}"></td> <td th:text="${user.username}"></td> <td th:text="${user.gender == 1 ? '男' : '女'}"></td> <td th:text="${user.email}"></td> <td> <a href="">修改</a> <a href="">删除</a> </td> </tr>
</tbody> </table> </body> </html>
|
6、测试结果:
2.5 实现新增功能
2.5.1 跳转到新增页面
1、在用户列表user_index.html页面,修改新增用户
的超链接:
1
| <a class="add-button" th:href="@{/toAdd}">新增用户</a>
|
2、将user_add.html拷贝到thymeleaf目录下,并进行代码修改如下:
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
| <!DOCTYPE html> <html lang="en" xmlns:th="http:www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>新增用户</title> <link rel="stylesheet" th:href="@{/static/css/user.css}" type="text/css"></link> </head> <body> <h1>新增用户</h1> <form> <label>用户名:</label> <input type="text" name="username" required>
<label>性别:</label> <select name="gender" required> <option value="">-- 请选择 --</option> <option value="1">男</option> <option value="0">女</option> </select>
<label>邮箱:</label> <input type="email" name="email" required>
<button type="submit">保存</button> </form> </body> </html>
|
3、在springmvc.xml文件中配置视图控制器映射
:
1
| <mvc:view-controller path="/toAdd" view-name="user_add"/>
|
4、启动服务器测试:
2.5.2 实现新增功能
1、前端页面发送POST请求,提交表单,修改user_add.html代码如下:
1
| <form th:action="@{/user}" method="post"></form>
|
2、编写控制器UserController:
1 2 3 4 5 6 7
| @RequestMapping(value = "/user", method = RequestMethod.POST) public String save(User user){ userDao.insert(user); return "redirect:/user"; }
|
PS:保存成功后,采用重定向的方式跳转到用户列表。
3、编写UserDao:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public Long generateId(){ Long maxId = users.stream().map(user -> user.getId()).reduce((id1, id2) -> id1 > id2 ? id1 : id2).get(); return maxId + 1; }
public void insert(User user){ Long id = generateId(); user.setId(id); users.add(user); }
|
PS:单独写了一个方法生成id,内部使用了Stream API。
4、启动服务器测试:
2.6 实现新增功能
2.6.1 跳转到修改页面
1、修改user_list.html中修改
超链接:
1
| <a th:href="@{'/user/' + ${user.id}}">修改</a>
|
2、编写Controller:
1 2 3 4 5 6 7 8 9
| @GetMapping("/user/{id}") public String toUpdate(@PathVariable("id") Long id, Model model){ User user = userDao.selectById(id); model.addAttribute("user", user); return "user_edit"; }
|
3、编写UserDao:
1 2 3
| public User selectById(Long id){ return users.stream().filter(user -> user.getId().equals(id)).findFirst().get(); }
|
4、将user_edit.html拷贝thymeleaf目录下,并修改代码如下:
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
| <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>修改用户</title> <link rel="stylesheet" th:href="@{/static/css/user.css}" type="text/css"></link> </head> <body> <h1>修改用户</h1> <form> <label>用户名:</label> <input type="text" name="username" th:value="${user.username}" required>
<label>性别:</label> <select name="gender" required> <option value="">-- 请选择 --</option> <option value="1" th:field="${user.gender}">男</option> <option value="0" th:field="${user.gender}">女</option> </select>
<label>邮箱:</label> <input type="email" name="email" th:value="${user.email}" required>
<button type="submit">修改</button> </form> </body> </html>
|
5、启动服务器测试:
2.6.2 实现修改功能
1、将user_edit.html页面中的form表单修改一下,添加action,添加method,隐藏域的方式提交请求方式put,隐藏域的方式提交id:
1 2 3 4 5 6
| <form th:action="@{/user}" method="post"> <input type="hidden" name="_method" value="put"> <input type="hidden" name="id" th:value="${user.id}"> </form>
|
2、编写Controller:
1 2 3 4 5 6 7
| @PutMapping("/user") public String modify(User user){ userDao.update(user); return "redirect:/user"; }
|
3、编写UserDao:
1 2 3 4 5 6 7 8
| public void update(User user) { for (int i = 0; i < users.size(); i++) { if (user.getId().equals(users.get(i).getId())) { users.set(i, user); break; } } }
|
4、启动服务器测试:
2.7 实现删除功能
删除应该发送DELETE请求,要模拟DELETE请求,就需要使用表单方式提交。因此我们点击删除
超链接时需要采用表单方式提交。
1、在user_list.html页面添加form表单,并且点击超链接时应该提交表单,代码如下:
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
| <a th:href="@{'/user/' + ${user.id}}" onclick="del(event)">删除</a>
<div style="display: none"> <form method="post" id="delForm"> <input type="hidden" name="_method" value="delete"/> </form> </div>
<script> function del(event){ let delForm = document.getElementById("delForm"); delForm.action = event.target.href; if(window.confirm("您确定要删除吗?")){ delForm.submit(); } event.preventDefault(); } </script>
|
2、编写Controller:
1 2 3 4 5 6 7
| @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE) public String del(@PathVariable("id") Long id){ userDao.deleteById(id); return "redirect:/user"; }
|
3、编写UserDao:
1 2 3 4 5 6 7 8
| public void deleteById(Long id) { for (int i = 0; i < users.size(); i++) { if (id.equals(users.get(i).getId())) { users.remove(i); break; } } }
|
4、启动服务器测试: