[toc]
| 单词 | 词性 | 音标 | 含义 |
|---|---|---|---|
| RESTFul | adj. | /ˈrestfəl/ | 符合REST风格的(指遵循REST架构设计原则的Web服务,强调资源导向、无状态交互等特性) |
| representational | adj. | /ˌreprɪzenˈteɪʃənl/ | 表征的;表示的(REST中“Representational”指资源的表现形式,如JSON、XML等数据格式) |
| state | n. | /steɪt/ | 状态(REST中“State”指资源的状态,客户端通过操作资源表现形式来改变资源状态,服务端本身保持无状态) |
| transfer | v. / n. | /ˈ trænsfɜː(r)/ | 传输(REST中“Transfer”指资源表现形式的传递,客户端与服务端通过HTTP传输资源状态的表征) |
| Uniform | adj. | /ˈjuːnɪfɔːm/ | 统一的(REST原则中“Uniform Interface”指统一接口,通过URI、HTTP方法等标准化方式交互) |
| Resource | n. | /ˈriːsɔːs/ | 资源(REST的核心概念,指网络中可标识的实体或信息,如用户、订单等,通过URI唯一标识) |
| Locator | n. | /ləʊˈkeɪtə(r)/ | 定位器(指URI作为资源定位器,用于唯一标识和定位网络中的资源,如/users/123定位特定用户资源) |
Lecture06-请求-实验05-RESTFul
1、REST 概念
REST:Representational State Transfer,表现层资源状态转移。
- 定位:互联网软件架构风格
- 倡导者:Roy Thomas Fielding
- 文献:Roy Thomas Fielding的博士论文
Roy Thomas Fielding是美国计算机科学家,1965年出生于加利福尼亚州拉古纳海滩。以下是关于他的详细介绍:
- 教育背景:2000年,他在加利福尼亚大学欧文分校获得博士学位,其博士论文为《Architectural Styles and the Design of Network-based Software Architectures》。
- 职业经历:他是Adobe系统公司的高级首席科学家,曾担任Apache软件基金会的主席三年,并在其董事会任职至2014年5月。他还曾是OpenSolaris临时董事会的成员,直到2008年从社区辞职。
- 主要贡献:他是HTTP规范的主要作者之一,也是代表性状态转移(REST)架构风格的创始人,REST架构风格已成为创建API和Web服务的广泛使用的模型。此外,他还参与了HTML和统一资源标识符(URI)的开发,并共同创立了Apache HTTP服务器项目。
- 所获荣誉:1999年,他被《麻省理工科技评论》TR100评为35岁以下的世界100大创新者之一。
2、挑战与应对
①一项技术标准规范一统天下
端到端之间的交互协议、技术实现方案有多少种?
- SOAP
- WSDL
- XML-RPC
- socket
- SMTP
- POP3
- ……
面对各种不同领域的各种不同协议、技术标准、解决方案,我们程序员是真的头秃。增加学习成本不说,还复杂难以调试,再加上参考资料稀缺、晦涩难懂。于是 HTTP 协议来了,它来拯救我们了,它有什么优势呢?
- 在最广大的范围内,HTTP 协议拥有最广泛的共识
- 报文结构清晰,简单明了
- 无状态,消除了请求与请求之间的耦合关系
- 无类型,却能够展示丰富的数据类型
- 解耦合,双方一旦确定使用 HTTP 协议交互,那就不必关心对方采用什么技术、基于什么平台
②功能还是资源?
传统的软件系统仅在本地工作,但随着项目规模的扩大和复杂化,不但整个项目会拓展为分布式架构,很多功能也会通过网络访问第三方接口来实现
在通过网络访问一个功能的情况下,我们不能轻易假设网络状况稳定可靠
所以当一个请求发出后没有接收到对方的回应,那我们该如何判定本次操作成功与否?
下面以保存操作为例来说明一下针对功能和针对资源进行操作的区别:
-
针对功能设计系统
保存一个 Employee 对象,没有接收到返回结果,判定操作失败,再保存一次
但是其实在服务器端保存操作已经成功了,只是返回结果在网络传输过程中丢失了
而第二次的补救行为则保存了重复、冗余但 id 不同的数据,这对整个系统数据来说是一种破坏
-
针对资源设计系统
针对 id 为 9527 的资源执行操作,服务器端会判断指定 id 的资源是否存在
- 如果不存在,则执行保存操作新建数据;
- 如果存在,则执行更新操作
所以这个操作不论执行几次,对系统的影响都是一样的
在网络状态不可靠的情况下可以多次重试,不会破坏系统数据
幂等性:如果一个操作执行一次和执行 N 次对系统的影响相同,那么我们就说这个操作满足幂等性
而幂等性正是 REST 规范所倡导的
③无论内外一视同仁?
确立 HTTP 协议作为项目架构设计规范和统一标准后,无论系统内部的远程方法还是系统外部的第三方接口,对我们当前所在模块来说都是网络上的资源,完全可以使用相同(或类似)的方式来访问和调用。这非常有利于我们建构大型、超大型互联网项目体系。
3、REST 规范的内涵
①资源
URL:Uniform Resource Locator 统一资源定位器。意思是网络上的任何资源都可以通过 URL 来定位。但是在传统开发中,我们往往是使用 URL 来对应一个具体的功能,而不是资源本身
REST 规范则倡导使用 URL 对应网络上的各种资源,任何一个资源都可以通过一个 URL 访问到,为实现操作幂等性奠定基础
而这个资源可以是网络上的一个文本、音频、视频、图片、商品等等……
②状态转移
REST 倡导针对资源本身操作,所以对资源的操作如果满足幂等性,那么操作只会导致资源本身的状态发生变化而不会破坏整个系统数据。
4、REST 规范具体要求
①四种请求方式对应四种常见操作
REST 风格主张在项目设计、开发过程中,具体的操作符合 HTTP 协议定义的请求方式的语义。
| 操作 | 请求方式 |
|---|---|
| 查询操作 | GET |
| 保存操作 | POST |
| 删除操作 | DELETE |
| 更新操作 | PUT |
另有一种说法:
- POST 操作针对功能执行,没有锁定资源 id,是非幂等性操作
- PUT 操作锁定资源 id,即使操作失败仍然可以针对原 id 重新执行,对整个系统来说满足幂等性
- id 对应的资源不存在:执行保存操作
- id 对应的资源存在:执行更新操作
这个说法更加深刻
②URL 地址风格
REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。还有一点是不要使用请求扩展名。
| 传统 URL 地址 | REST 风格地址 |
|---|---|
| /remove/emp?id=5 | /emp/5 |
5、REST 风格URL的好处
①含蓄,安全
使用问号键值对的方式给服务器传递数据太明显,容易被人利用来对系统进行破坏
使用 REST 风格携带数据不再需要明显的暴露数据的名称
②风格统一
URL 地址整体格式统一,从前到后始终都使用斜杠划分各个单词,用简单一致的格式表达语义
/user/info/2343
/mall/product/phone/45464
③无状态
在调用一个接口(访问、操作资源)的时候,可以不用考虑上下文,不用考虑当前状态,极大的降低了系统设计的复杂度
④严谨,规范
严格按照 HTTP1.1 协议中定义的请求方式本身的语义进行操作
⑤简洁,优雅
过去做增删改查操作需要设计4个不同的URL,现在一个就够了
| 操作 | 传统风格 | REST 风格 |
|---|---|---|
| 保存 | /CRUD/saveEmp | URL 地址:/CRUD/emp 请求方式:POST |
| 删除 | /CRUD/removeEmp?empId=2 | URL 地址:/CRUD/emp/2 请求方式:DELETE |
| 更新 | /CRUD/updateEmp | URL 地址:/CRUD/emp 请求方式:PUT |
| 查询(表单回显) | /CRUD/editEmp?empId=2 | URL 地址:/CRUD/emp/2 请求方式:GET |
⑥丰富的语义
通过 URL 地址就可以知道资源之间的关系。它能够把一句话中的很多单词用斜杠连起来,反过来说就是可以在 URL 地址中用一句话来充分表达语义
http://localhost:8080/shop
http://localhost:8080/shop/product
http://localhost:8080/shop/product/cellPhone
http://localhost:8080/shop/product/cellPhone/iPhone
6、@ResponseBody注解延伸
- @ResponseBody注解标记在类上:相当于类中每个方法都加了这个注解
- 标记在类上的@ResponseBody注解与@Controller注解合并
@Controller
@ResponseBody
public @interface RestController {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
* @since 4.0.1
*/
@AliasFor(annotation = Controller.class)
String value() default "";
}
7、总结
RESTFul风格对操作层面的要求:
- CRUD的请求方式遵循HTTP协议的语义(GET、POST、PUT、DELETE)
- URL地址不要携带请求参数,需要携带数据时把数据放到路径中,使用路径变量
- URL地址整体上风格保持一致