显然,REST只是关于如何使用HTTP的一组惯例。我想知道这些惯例提供了哪些优势。有人知道吗?
我认为你不太可能得到一个好的答案,部分原因是因为没有人真正同意REST的定义。维基百科页面充斥着流行语,但解释很少。讨论页值得一读,因为里面有很多人对此存在争议。据我所知,REST 的意思是这样的:
不采用随意命名的 setter 和 getter URL,并在所有 getter 中使用 GET
,在所有 setter 中使用 POST
,而是尝试让 URL 标识资源,并使用 HTTP 动作GET
、POST
、PUT
和DELETE
来对其进行操作。所以,我们不再使用类似于下面的方式:
GET /get_article?id=1
POST /delete_article id=1
你可以这样做
GET /articles/1/
DELETE /articles/1/
然后POST
和PUT
分别对应“创建”和“更新”操作(但没有人同意哪个是哪个)。
我认为缓存参数是错误的,因为查询字符串通常被缓存,而且你不一定需要使用它们。例如Django可以轻松地实现这样的功能,但我不会说它是RESTful的:
GET /get_article/1/
POST /delete_article/ id=1
甚至可以将动词直接包含在URL中:
GET /read/article/1/
POST /delete/article/1/
POST /update/article/1/
POST /create/article/
在这种情况下,GET
表示没有副作用的操作,而 POST
表示会在服务器上更改数据的操作。我认为这样可能会更加清晰和易于理解,尤其是你可以避免整个 PUT
vs POST
的问题。此外,如果需要,您可以添加更多的动词,因此您不必人为地受限于HTTP所提供的内容。例如:POST /hide/article/1/
POST /show/article/1/
(或其他什么,直到它们发生才难以想出例子!)
因此,总的来说,我只能看到两个优点:
synchronize("/articles/1/")
或其他什么。这在很大程度上取决于您的代码。但是我认为有一些相当大的缺点:
PUT
和 POST
的顺序混乱。在英语中,它们的意思相似(“我要在墙上放/发布一个通知。”)。因此,总结一下,我会说:除非您真的想要付出额外的努力,或者如果您的服务与 CRUD 操作非常匹配,请将 REST 留给 API 的第二个版本。
我刚刚遇到 REST 的另一个问题:在一个请求中执行多个操作或指定要获取的复合对象的哪些部分不容易。这在移动设备上尤其重要,因为往返时间可能很长,而连接也不可靠。例如,假设您正在获取 Facebook 时间线上的帖子。“纯粹”的 REST 会像这样:
GET /timeline_posts // Returns a list of post IDs.
GET /timeline_posts/1/ // Returns a list of message IDs in the post.
GET /timeline_posts/2/
GET /timeline_posts/3/
GET /message/10/
GET /message/11/
....
这有点荒谬。在我看来,Facebook的API非常棒,那么让我们看看他们是如何做到的:
默认情况下,在查询时返回大多数对象属性。您可以使用“fields”查询参数选择要返回的字段(或连接)。例如,此URL仅返回Ben的id、name和picture: https://graph.facebook.com/bgolub?fields=id,name,picture
我不知道如何用REST实现这样的功能,即使你这样做了,它是否仍然算作REST也不确定。但无论如何,我肯定会忽略任何试图告诉你不应该这样做的人(特别是如果原因是“因为它不是REST”)!
/user/{id}
获取用户信息”,那么它就不是RESTful的。请考虑一下:你的浏览器是否需要预先程序化地知道如何获取Stack Overflow问题页面的HTML? - Claudiu简单来说,REST 意味着使用 HTTP 的标准方式。
可以阅读 Roy Fielding 关于 REST 的论文。我认为每个从事 web 开发的人都应该阅读。
需要注意的是,Roy Fielding 也是 HTTP 协议背后的重要推动者之一。
以下是一些优势:
简单来说:没有。
请随意点踩,但我仍然认为与非REST HTTP相比没有真正的好处。所有当前的答案都是无效的。以下是目前得票最多的答案中的论点:
使用REST需要为服务端和客户端脚本提供额外的通信层=>实际上比非REST HTTP更复杂。
缓存可以通过服务器发送的HTTP头来控制。REST不会增加任何非REST所缺少的功能。
REST并不会帮助您组织事物。它强制您使用由您正在使用的服务端库支持的API。当您使用非REST方法时,您可以以相同或更好的方式组织应用程序。例如,请参见模型-视图-控制器或MVC路由。
并不完全正确。这完全取决于您如何组织和记录您的应用程序。REST不会神奇地使您的应用程序变得更好。
在我看来,REST最大的优势是减少客户端/服务器之间的耦合程度。使用REST接口更容易随着时间的推移进行演进而不会破坏现有的客户端。
每个资源都引用了其他资源,可以通过层次结构或链接轻松浏览。这对于开发客户端的人来说是一个优势,免去了不断查阅文档并提供建议的麻烦。它还意味着服务器可以单方面更改资源名称(只要客户端软件没有硬编码URL)。
您可以使用CURL访问API的任何部分,或使用Web浏览器导航资源。这样可以更容易地进行调试和测试集成。
允许您指定操作而无需寻找正确的措辞。想象一下如果OOP属性的getter和setter没有标准化,有些人使用retrieve
和define
。您将不得不记忆每个单独访问点的正确动词。知道只有少量动词可用就可以解决这个问题。
在RESTful API中,如果您 GET
不存在的资源,您可以确保会收到404
错误。这与非RESTful API形成对比,后者可能会返回包装在各种层中的{error:"未找到"}
。如果您需要额外的空间向另一侧开发者编写消息,您始终可以使用响应的正文部分。
想象两个具有相同功能的API,一个遵循REST,另一个不遵循。现在想象以下这些API的客户端:
RESTful:
GET /products/1052/reviews
POST /products/1052/reviews "5 stars"
DELETE /products/1052/reviews/10
GET /products/1052/reviews/10
HTTP:
GET /reviews?product_id=1052
POST /post_review?product_id=1052 "5 stars"
POST /remove_review?product_id=1052&review_id=10
GET /reviews?product_id=1052&review=10
现在考虑以下问题:
如果每个客户端的第一个调用都有效,您对其余的调用是否有信心也会有效?
API 进行了重大更新,可能已更改这些访问点。你需要重新阅读多少文档?
你能预测最后一个查询的返回结果吗?
在删除之前,你必须编辑发布的评论。你能在不查看文档的情况下完成吗?
我建议看一下Ryan Tomayko的《如何向妻子解释REST》
从waybackmaschine链接中摘录:
举个例子,你是一名教师,想管理学生:
如果这些系统都是基于网络的,那么每个涉及到的名词都可能有一个URL:student、teacher、class、book、room等
。 ... 如果每个URL都有一个机器可读的表示形式,那么将新工具连接到系统中就非常简单了,因为所有的信息都可以以标准方式被消费。... 你可以建立一个全国性的系统,能够与每个单独的学校系统对话,以收集测试分数。
每个系统都使用简单的HTTP GET从彼此获取信息。如果一个系统需要向另一个系统添加内容,则使用HTTP POST。如果一个系统想要更新另一个系统中的内容,则使用HTTP PUT。唯一留下的问题是数据应该长什么样子。
缓存。
REST有许多更深入的好处,涉及通过松耦合和超文本实现可演化性,但缓存机制是你应该关心RESTful HTTP的主要原因。
GET /get_article/19/
和POST /update_article
?您仍然可以只用GET
和POST
完成所有操作,并且我认为REST
意味着“仅使用GET
,POST
,PUT
和DELETE
”,而不仅仅是“不要使用查询字符串”。因此,我的建议不会符合REST
。不过,毕竟没有人真正同意REST
到底是什么,所以我把它放在一个和“Web 2.0”一样的桶里。 - Timmmm这些内容可以在Fielding dissertation中找到,但如果你不想阅读太多:
@Timmmm,关于你的编辑:
GET /timeline_posts // could return the N first posts, with links to fetch the next/previous N posts
这将大大减少调用次数。
而且,您可以设计一个服务器,接受HTTP参数来表示客户端可能需要的字段值...
但这只是一个细节。
更重要的是,您没有提到REST架构风格的巨大优势(由于服务器无状态性,可实现更好的可扩展性;由于服务器无状态性,可实现更好的可用性;使用REST架构风格时,可以更好地利用标准服务,例如缓存等;由于使用统一接口,客户端和服务器之间的耦合度更低等等)
至于您的评论:
"并非所有操作都容易映射到CRUD(创建、读取/检索、更新、删除)."
:RDBMS也使用CRUD方法(SELECT / INSERT / DELETE / UPDATE),并且总有一种方法来表示和处理数据模型。
关于您的句子:
"您甚至可能不涉及对象类型资源"
RESTful 设计本质上是一种简单的设计,但这并不意味着设计它很简单。你看出区别了吗?你需要深入思考你的应用程序将代表和处理的概念,必须通过资源来表示它,或者更确切地说,你需要思考它必须完成什么任务。但如果你这样做,最终会得到一个更简单、更高效的设计。