大家好,我是路人,这是 SpringMVC 系列第 20 篇。
尚硅谷 Java 学科全套教程(总 207.77GB)
本文主要 2 个主题:介绍 RESTful、SpringMVC 中 RESTful 案例。
目录
1、RESTful 简介
2、RESTful 的实现
3、HiddenHttpMethodFilter
4、RESTful 案例
5、SpringMVC 系列目录
6、更多好文章
7、【路人甲 Java】所有系列高清 PDF
1、RESTful 简介
REST:Representational State Transfer,表现层资源状态转移。
a>资源
资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。因为资源是一个抽象的概念,所以它不仅仅能代表服务器文件系统中的一个文件、数据库中的一张表等等具体的东西,可以将资源设计的要多抽象有多抽象,只要想象力允许而且客户端应用开发者能够理解。与面向对象设计类似,资源是以名词为核心来组织的,首先关注的是名词。一个 资源可以由一个或多个 URI 来标识。URI 既是资源的名称,也是资源在 Web 上的地址。对某个资源感兴趣的客户端应用,可以通过资源的 URI 与其进行交互。
b>资源的表述
资源的表述是一段对于资源在某个特定时刻的状态的描述。可以在客户端-服务器端之间转移(交换)。资源的表述可以有多种格式,例如 HTML/XML/JSON/纯文本/图片/视频/音频等等。资源的表述格式可以通过协商机制来确定。请求-响应方向的表述通常使用不同的格式。
c>状态转移
状态转移说的是:在客户端和服务器端之间转移(transfer)代表资源状态的表述。通过转移和操作资源的表述,来间接实现操作资源的目的。
2、RESTful 的实现
具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。
它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。
操作 | 传统方式 | REST 风格 |
---|
查询操作 | getUserById?id=1 | user/1-->get 请求方式 |
保存操作 | saveUser | user-->post 请求方式 |
删除操作 | deleteUser?id=1 | user/1-->delete 请求方式 |
更新操作 | updateUser | user-->put 请求方式 |
3、HiddenHttpMethodFilter
由于浏览器只支持发送 get 和 post 方式的请求,那么该如何发送 put 和 delete 请求呢?
SpringMVC 提供了 HiddenHttpMethodFilter 帮助我们将 POST 请求转换为 DELETE 或 PUT 请求。
HiddenHttpMethodFilter 处理 put 和 delete 请求的条件:
当前请求的请求方式必须为 post
前请求必须传输请求参数_method
满足以上条件,HiddenHttpMethodFilter 过滤器就会将当前请求的请求方式转换为请求参数_method 的值,因此请求参数_method 的值才是最终的请求方式。
在 web.xml 中注册 HiddenHttpMethodFilter
<filter>
????<filter-name>HiddenHttpMethodFilter</filter-name>
????<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filterclass>
</filter>
<filter-mapping>
????<filter-name>HiddenHttpMethodFilter</filter-name>
????<url-pattern>/*</url-pattern>
</filter-mapping>
使用注意:
目前为止,SpringMVC 中提供了两个过滤器:CharacterEncodingFilter 和 HiddenHttpMethodFilter
在 web.xml 中注册时,必须先注册 CharacterEncodingFilter,再注册 HiddenHttpMethodFilter
原因:
在 CharacterEncodingFilter 中通过 request.setCharacterEncoding(encoding) 方法设置字符集的
request.setCharacterEncoding(encoding) 方法要求前面不能有任何获取请求参数的操作而 HiddenHttpMethodFilter 恰恰有一个获取请求方式的操作:
String?paramValue?=?request.getParameter(this.methodParam);
4、RESTful 案例
4.1、需求
通过 restfull 实现用户的增删改查,需要提供 5 个接口。
接口 | method | 描述 |
---|
/user/list | GET | 获取用户列表 |
/user/{userId} | GET | 根据用户 id 获取用户信息 |
/user | POST | 新增用户信息 |
/user | PUT | 保存用户信息 |
/user/{userId} | DELETE | 删除用户信息 |
4.2、git 代码位置
https://gitee.com/javacode2018/springmvc-series
4.3、UserController
UserController 中实现了需求中提到的 4 个接口,大家重点看下每个接口的方法上用到的注解。
@RestController
public?class?UserController?{
????private?List<User>?userList?=?new?ArrayList<>();
????{
????????userList.add(new?User(1,?"Spring高手系列"));
????????userList.add(new?User(2,?"SpringMVC系列"));
????}
????@GetMapping("/user/list")
????public?List<User>?list()?{
????????System.out.println("list()");
????????return?userList;
????}
????@GetMapping("/user/{userId}")
????public?User?getUser(@PathVariable("userId")?Integer?userId)?{
????????System.out.println("getUser()");
????????for?(User?user?:?userList)?{
????????????if?(user.getUserId().equals(userId))?{
????????????????return?user;
????????????}
????????}
????????return?null;
????}
????@PostMapping(value?=?"/user",?produces?=?"text/html;charset=UTF-8")
????public?String?add(User?user)?{
????????System.out.println("add()");
????????this.userList.add(user);
????????return?"新增成功";
????}
????@PutMapping(value?=?"/user",?produces?=?"text/html;charset=UTF-8")
????public?String?modify(User?user)?{
????????System.out.println("modify()");
????????for?(User?item?:?userList)?{
????????????if?(item.getUserId().equals(user.getUserId()))?{
????????????????item.setName(user.getName());
????????????}
????????}
????????return?"修改成功";
????}
????@DeleteMapping(value?=?"/user/{userId}",?produces?=?"text/html;charset=UTF-8")
????public?String?delete(@PathVariable("userId")?Integer?userId)?{
????????System.out.println("delete()");
????????Iterator<User>?iterator?=?userList.iterator();
????????while?(iterator.hasNext())?{
????????????User?user?=?iterator.next();
????????????if?(user.getUserId().equals(userId))?{
????????????????iterator.remove();
????????????}
????????}
????????return?"删除成功";
????}
????public?static?class?User?{
????????private?Integer?userId;
????????private?String?name;
????????public?User()?{
????????}
????????public?User(Integer?userId,?String?name)?{
????????????this.userId?=?userId;
????????????this.name?=?name;
????????}
????????public?Integer?getUserId()?{
????????????return?userId;
????????}
????????public?void?setUserId(Integer?userId)?{
????????????this.userId?=?userId;
????????}
????????public?String?getName()?{
????????????return?name;
????????}
????????public?void?setName(String?name)?{
????????????this.name?=?name;
????????}
????????@Override
????????public?String?toString()?{
????????????return?"User{"?+
????????????????????"userId="?+?userId?+
????????????????????",?name='"?+?name?+?'\''?+
????????????????????'}';
????????}
????}
}
4.4、添加 HiddenHttpMethodFilter
HiddenHttpMethodFilter?hiddenHttpMethodFilter?=?new?HiddenHttpMethodFilter();
4.5、测试效果
将项目发布到 tomcat,如下图,跑一下 UserController.http 中的 5 个用例,点击每个用户中的绿色箭头即可运行,注意下后面 3 个用例都是 POST 方式提交的,但是参数中多了一个_method 参数用来指定提交的类型,这个参数会被 HiddenHttpMethodFilter 解析。
5、SpringMVC 系列目录
SpringMVC 系列第 1 篇:helloword
SpringMVC 系列第 2 篇:@Controller、@RequestMapping
SpringMVC 系列第 3 篇:异常高效的一款接口测试利器
SpringMVC 系列第 4 篇:controller 常见的接收参数的方式
SpringMVC 系列第 5 篇:@RequestBody 大解密,说点你不知道的
SpringMVC 系列第 6 篇:上传文件的 4 种方式,你都会么?
SpringMVC 系列第 7 篇:SpringMVC 返回视图常见的 5 种方式,你会几种?
SpringMVC 系列第 8 篇:返回 json & 通用返回值设计
SpringMVC 系列第 9 篇:SpringMVC 返回 null 是什么意思?
SpringMVC 系列第 10 篇:异步处理
SpringMVC 系列第 11 篇:集成静态资源
SpringMVC 系列第 12 篇:拦截器
SpringMVC 系列第 13 篇:统一异常处理
SpringMVC 系列第 14 篇:实战篇:通用返回值 & 异常处理设计
SpringMVC 系列第 15 篇:全注解的方式 ?&? 原理解析
SpringMVC 系列第 16 篇:通过源码解析 SpringMVC 处理请求的流程
SpringMVC 系列第 17 篇:源码解析 SpringMVC 容器的启动过程
SpringMVC 系列第 18 篇:强大的 RequestBodyAdvice 解密
SpringMVC 系列第 19 篇:强大的 ResponseBodyAdvice 解密
6、更多好文章
Spring 高手系列(共 56 篇)
Java 高并发系列(共 34 篇)
MySql 高手系列(共 27 篇)
Maven 高手系列(共 10 篇)
Mybatis 系列(共 12 篇)
聊聊 db 和缓存一致性常见的实现方式
接口幂等性这么重要,它是什么?怎么实现?
泛型,有点难度,会让很多人懵逼,那是因为你没有看这篇文章!
7、【路人甲 Java】所有系列高清 PDF
领取方式,扫码发送:yyds