Spring MVC 中使用 RESTFul 编程风格
1. Spring MVC 中使用RESTFul 编程风格@
目录
[*]1. Spring MVC 中使用RESTFul 编程风格
[*]2. RESTFul 编程风格
[*]2.1 RESTFul 是什么
[*]2.2 RESTFul风格与传统方式对比
[*]3. Spring MVC 中使用RESTFul 编程风格(增删改查)的使用
[*]3.1 预备工作
[*]3.2 RESTFul 风格的 “查询” 所有(RESTFul 规范 需要发送 GET请求)
[*]3.3 RESTFul 风格的 根据 “id 查询”( RESTFul 规范 需要发送 GET请求)
[*]3.4 RESTFul 风格的 “增长数据” (RESTFul 规范 需要发送 POST 请求)
[*]3.5 RESTFul 风格的 “修改数据” (RESTFul 规范 需要发送 PUT 请求)
[*]3.6 RESTFul 风格的 “删除数据” 数据(RESTFul 规范 需要发送 DELETE 请求)
[*]4. 补充: HiddenHttpMethodFilter 过滤器源码阐明
[*]5. 总结:
[*]6. 末了:
2. RESTFul 编程风格
2.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) 是:URL + 请求方式。
状态(State) 是 :服务器端的数据。
转移(Transfer) 是:变化。
表述性转移是指:通过 URL + 请求方式来控制服务器端数据的变化。
2.2 RESTFul风格与传统方式对比
统的 URL 与 RESTful URL 的区别是传统的 URL 是基于方法名举行资源访问和操纵,而 RESTful URL 是基于资源的结构和状态举行操纵的。下面是一张表格,展示两者之间的具体区别:
传统的 URLRESTful URLGET /getUserById?id=1GET /user/1GET /getAllUserGET /userPOST /addUserPOST /userPOST /modifyUserPUT /userGET /deleteUserById?id=1DELETE /user/1从上表中我们可以看出,传统的 URL是基于动作的,而 RESTful URL 是基于资源和状态的,因此 RESTful URL 更加清楚和易于理解,这也是 REST 架构风格被广泛使用的重要原因之一。
3. Spring MVC 中使用RESTFul 编程风格(增删改查)的使用
3.1 预备工作
导入相干依赖 jar 包。
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808738-8844862.png
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808772-679081597.png
<?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.rainbowsea</groupId>
<artifactId>springmvc-007</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</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>
</dependencies>
</project>相干包 / 目录的创建,配置。
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808657-1767196795.png
springmvc.xml 配置文件的配置;
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808389-807867120.png
<?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/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.rainbowsea.springmvc.controller"></context:component-scan>
<bean id="thymeleafViewResolver" >
<property name="characterEncoding" value="UTF-8"/>
<property name="order" value="1"/>
<property name="templateEngine">
<bean >
<property name="templateResolver">
<bean >
<property name="prefix" value="/WEB-INF/templates/"/>
<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:annotation-driven>
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
</beans>3.2 RESTFul 风格的 “查询” 所有(RESTFul 规范 需要发送 GET请求)
RESTFul 规范中规定,如果要查询数据,需要发送 GET 请求。
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808419-1781635879.png
<!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:target="_blank" href="https://www.cnblogs.com/@{/user}">查看用户列表</a>
</body>
</html>控制器 Controller:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808276-256946805.png
import com.rainbowsea.springmvc.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller// 交给 Spring IOC 容器进行管理
public class UserController {
@RequestMapping(value = "/user", method = RequestMethod.GET)
public String getAll() {
System.out.println("正在查询所有用户信息...");
return "ok";
}
}ok 的页面视图:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808339-799791149.png
<!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>启动服务器,测试:http://localhost:8080/springmvc
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808392-1661312411.png
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808863-987437795.png
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808358-1093987916.png
3.3 RESTFul 风格的 根据 “id 查询”( RESTFul 规范 需要发送 GET请求)
RESTFul 规范中规定,如果要查询数据,需要发送GET请求。
首页index.html
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808684-318027729.png
<!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:target="_blank" href="https://www.cnblogs.com/@{/user}">查看用户列表</a>
</body>
</html>查询id=1的这个用户信息
控制器 Controller:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808630-514907856.png
import com.rainbowsea.springmvc.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller// 交给 Spring IOC 容器进行管理
public class UserController {
//@RequestMapping(value = "/user/{占位符}",method = RequestMethod.GET)
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public String getById(@PathVariable(value = "id") String id) {
System.out.println("正在根据用户 id 查询用户信息...用户 id 是" + id);
return "ok";
}
}启动服务器测试:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808378-325281172.png
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808739-1269287067.png
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808745-875070962.png
3.4 RESTFul 风格的 “增长数据” (RESTFul 规范 需要发送 POST 请求)
RESTFul规范中规定,如果要举行保存操纵,需要发送POST请求。
这里我们添加一个 User Bean 类,用于作为对象举行存储。
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808726-757748034.png
package com.rainbowsea.springmvc.bean;
public class User {
private String username;
private String password;
private Integer age;
public User() {
}
public User(String username, String password, Integer age) {
this.username = username;
this.password = password;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", age=" + age +
'}';
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}页面编写:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808472-2126432086.png
<!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:target="_blank" href="https://www.cnblogs.com/@{/user}">查看用户列表</a>
</body>
</html>查询id=1的这个用户信息
用户名:
密码:
年岁:
<hr>控制器 Controller:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808307-1697997292.png
启动服务器测试:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808367-254465449.png
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808346-1857951126.png
3.5 RESTFul 风格的 “修改数据” (RESTFul 规范 需要发送 PUT 请求)
RESTFul规范中规定,如果要举行保存操纵,需要发送PUT请求。
如何发送PUT请求?
第一步:首先你必须是一个POST请求。
第二步:在发送POST请求的时候,提交如许的数据:_method=PUT ,使用隐藏域举行配置
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808393-1515457661.png
第三步:在web.xml文件配置SpringMVC提供的过滤器:HiddenHttpMethodFilter
注意:
<input type="hidden" name="_method" value="put">
隐藏域的 name 必须只能是 “_method”, value是 put(大小写忽略)第一步:首先你必须是一个POST请求。
第二步:在发送POST请求的时候,提交如许的数据:_method=PUT
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808712-1063720063.png
<h2>修改</h2>
<form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="put">
用户名: <input type="text" name="username">
密码:<input type="password" name="password">
年龄: <input type="text" name="age">
<input type="submit" value="修改">
</form>https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808862-1678754230.png
第三步:在web.xml文件配置SpringMVC提供的过滤器:HiddenHttpMethodFilter
注意:该过滤器一定要在字符编码过滤器背面配置,不然,先设置的话,可能会出现获取到的请求数据是乱码
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808810-984875289.png
<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>页面编写:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808802-462639846.png
<!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:target="_blank" href="https://www.cnblogs.com/@{/user}">查看用户列表</a>
</body>
</html>查询id=1的这个用户信息
用户名:
密码:
年岁:
<hr><h2>修改</h2>
<form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="put">
用户名: <input type="text" name="username">
密码:<input type="password" name="password">
年龄: <input type="text" name="age">
<input type="submit" value="修改">
</form>控制器 Controller:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808255-1092385487.png
启动服务器测试:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808664-1495686266.png
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808283-1960351268.png
3.6 RESTFul 风格的 “删除数据” 数据(RESTFul 规范 需要发送 DELETE 请求)
RESTFul规范中规定,如果要举行 删除 操纵,需要发送DELETE 请求。
如何发送 DELETE 请求?,和 发送PUT 请求的三步是一样的,只需要将 value 的值改为 delete 即可
第一步:首先你必须是一个POST请求。
第二步:在发送POST请求的时候,提交如许的数据:_method=PUT ,使用隐藏域举行配置
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808755-1984457275.png
第三步:在web.xml文件配置SpringMVC提供的过滤器:HiddenHttpMethodFilter
注意:
<input type="hidden" name="_method" value="delete">
隐藏域的 name 必须只能是 “_method”, value是 delete (大小写忽略)页面编写:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808409-1422018089.png
<hr>
<h2>删除用户</h2>
<a th:target="_blank" href="https://www.cnblogs.com/@{user/120}" onclick="del(event)">删除用户id = 120 的用户信息</a>
<form id="delForm" method="post">
<input type="hidden" name="_method" value="delete">
</form><!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:target="_blank" href="https://www.cnblogs.com/@{/user}">查看用户列表</a>
</body>
</html>查询id=1的这个用户信息
用户名:
密码:
年岁:
<hr><h2>修改</h2>
<form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="put">
用户名: <input type="text" name="username">
密码:<input type="password" name="password">
年龄: <input type="text" name="age">
<input type="submit" value="修改">
</form><hr>
<h2>删除用户</h2>
<a th:target="_blank" href="https://www.cnblogs.com/@{user/120}" onclick="del(event)">删除用户id = 120 的用户信息</a>
<form id="delForm" method="post">
<input type="hidden" name="_method" value="delete">
</form>控制器 Controller:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808721-54033890.png
package com.rainbowsea.springmvc.controller;
import com.rainbowsea.springmvc.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller// 交给 Spring IOC 容器进行管理
public class UserController {
//@RequestMapping(value = "/user/{占位符}",method = RequestMethod.GET)
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public String getById(@PathVariable(value = "id") String id) {
System.out.println("正在根据用户 id 查询用户信息...用户 id 是" + id);
return "ok";
}
@RequestMapping(value = "/user", method = RequestMethod.GET)
public String getAll() {
System.out.println("正在查询所有用户信息...");
return "ok";
}
@RequestMapping(value = "/user", method = RequestMethod.POST)
public String save(User user) {
System.out.println("正在保存用户信息");
System.out.println(user);
return "ok";
}
@RequestMapping(value = "/user", method = RequestMethod.PUT)
public String modify(User user) {
System.out.println("正在修改用户信息" + user);
return "ok";
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
public String del(@PathVariable(value = "id") String id) {
System.out.println("正删除用户 : " + id);
return "ok";
}
}启动服务器测试:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808369-941337698.png
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808727-282542983.png
4. 补充: HiddenHttpMethodFilter 过滤器源码阐明
HiddenHttpMethodFilter是Spring MVC框架提供的,专门用于RESTFul编程风格。
实现原理可以通过源码查看:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808478-1877419354.png
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808805-476621641.png
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808678-1580831234.png
通过源码可以看到,if语句中,首先判断是否为POST请求,如果是POST请求,调用request.getParameter(this.methodParam)。可以看到this.methodParam是_method,如许就要求我们在提交请求方式的时候必须采用这个格式:_method=put。获取到请求方式之后,调用了toUpperCase转换成大写了。因此前端页面中小写的put或者大写的PUT都是可以的。if语句中嵌套的if语句说的是,只有请求方式是 PUT,DELETE,PATCH的时候会创建HttpMethodRequestWrapper对象。而HttpMethodRequestWrapper对象的构造方法是如许的:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808357-178104928.png
如许method就从POST酿成了:PUT/DELETE/PATCH。
重点注意事项:CharacterEncodingFilter和HiddenHttpMethodFilter的顺序
细心的同学应该注意到了,在HiddenHttpMethodFilter源码中有如许一行代码:
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808343-243049225.png
)
大家是否还记得,字符编码过滤器执行之前不能调用 request.getParameter方法,如果提前调用了,乱码问题就无法办理了。因为request.setCharacterEncoding()方法的执行必须在所有request.getParameter()方法之前执行。因此这两个过滤器就有先后顺序的要求,在web.xml文件中,应该先配置CharacterEncodingFilter,然后再配置HiddenHttpMethodFilter。
5. 总结:
[*]RESTFul风格与传统方式对比区别
[*]RESTFul 风格的 “查询” 所有(RESTFul 规范 需要发送 GET请求)
[*]RESTFul 风格的 根据 “id 查询”( RESTFul 规范 需要发送 GET请求)
[*]RESTFul 风格的 “增长数据” (RESTFul 规范 需要发送 POST 请求)
[*]RESTFul 风格的 “修改数据” (RESTFul 规范 需要发送 PUT 请求)
如何发送PUT请求?
第一步:首先你必须是一个POST请求。
第二步:在发送POST请求的时候,提交如许的数据:_method=PUT ,使用隐藏域举行配置
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808860-1291180559.png
第三步:在web.xml文件配置SpringMVC提供的过滤器:HiddenHttpMethodFilter**
注意:
<input type="hidden" name="_method" value="put">
隐藏域的 name 必须只能是 “_method”, value是 put(大小写忽略)
[*]RESTFul 风格的 “删除数据” 数据(RESTFul 规范 需要发送 DELETE 请求);如何发送 DELETE 请求?,和 发送PUT 请求的三步是一样的,只需要将 value 的值改为 delete 即可
[*]HiddenHttpMethodFilter该过滤器一定要在字符编码过滤器背面配置,不然,先设置的话,可能会出现获取到的请求数据是乱码。
6. 末了:
“在这个末了的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上汲取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”
https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240704215808737-573509215.gif
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]