RESTful编程到底是什么?
当前回答
答案很简单,罗伊·菲尔丁写了一篇论文。]1在那篇论文中,他定义了REST原则。如果应用程序满足所有这些原则,那么这就是REST应用程序。
之所以创建RESTful一词,是因为ppl通过将其非REST应用程序称为REST而耗尽了REST一词。此后,RESTful一术语也耗尽了。现在我们讨论的是Web API和超媒体API,因为大多数所谓的REST应用程序都没有实现统一接口约束的HATEOAS部分。
REST约束如下:
客户端-服务器体系结构因此,它不适用于例如PUB/SUB套接字,而是基于REQ/REP。无状态通信因此,服务器不维护客户端的状态。这意味着您不能使用服务器侧会话存储,并且必须对每个请求进行身份验证。您的客户端可能通过加密连接发送基本身份验证标头。(对于大型应用程序,很难维护许多会话。)如果可以,请使用缓存因此,您不必一次又一次地满足相同的请求。作为客户机和服务器之间通用契约的统一接口客户端和服务器之间的契约不由服务器维护。换句话说,客户端必须与服务的实现分离。您可以通过使用标准解决方案来达到这种状态,例如用于标识资源的IRI(URI)标准、用于交换消息的HTTP标准、用于描述消息体序列化格式的标准MIME类型、用于描述邮件体不同部分语义的元数据(可能是RDF vocabs、微格式等)。为了将IRI结构与客户端分离,必须以超媒体格式(HTML、JSON-LD、HAL等)向客户端发送超链接。因此,客户端可以使用分配给超链接的元数据(可能是链接关系、RDF vocabs),通过适当的状态转换来导航应用程序的状态机,以实现其当前目标。例如,当客户想要向网络商店发送订单时,必须检查网络商店发送的响应中的超链接。通过检查链接,可以找到http://schema.org/OrderAction.客户机知道schema.org vocab,因此它知道通过激活这个超链接,它将发送订单。因此它激活超链接并发送POSThttps://example.com/api/v1/order以恰当的方式传递信息。之后,服务处理消息并以具有正确HTTP状态标头的结果进行响应,例如201-由成功创建。为了用详细的元数据注释消息,标准解决方案使用RDF格式,例如JSON-LD和REST vocab,例如Hydra和领域特定vocab(如schema.org或任何其他链接数据vocab),如果需要,还可以使用定制的应用程序特定vocab。现在这并不容易,这就是为什么大多数应用程序使用HAL和其他简单格式,这些格式通常只提供REST vocab,但不提供链接数据支持。构建分层系统以提高可扩展性REST系统由层次结构层组成。每一层包含使用下一层组件的服务的组件。因此,您可以轻松添加新的图层和组件。例如,有一个包含客户端的客户端层,在该层之下有一个服务层,该服务层包含单个服务。现在,您可以在它们之间添加客户端缓存。之后,您可以添加另一个服务实例和负载平衡器等…客户端代码和服务代码不会更改。扩展客户端功能的按需代码此约束是可选的。例如,您可以向客户端发送特定媒体类型的解析器,等等…为了做到这一点,您可能需要客户端中的标准插件加载器系统,或者您的客户端将耦合到插件加载器解决方案。
REST约束导致了一个高度可扩展的系统,其中客户端与服务的实现分离。因此,客户端可以是可重用的,就像web上的浏览器一样。客户机和服务共享相同的标准和语音,因此尽管客户机不知道服务的实现细节,但它们可以相互理解。这使得创建能够找到并利用REST服务实现其目标的自动化客户端成为可能。从长远来看,这些客户端可以像人类一样相互通信,在任务上相互信任。如果我们向这些客户端添加学习模式,那么结果将是一个或多个使用机器网络的人工智能,而不是一个服务器园区。因此,伯纳斯-李的梦想终于实现了:语义网络和人工智能将成为现实。因此,到2030年,我们最终被天网终止。在此之前…;-)
其他回答
REST定义了6个体系结构约束,使任何web服务都成为真正的RESTful API。
统一接口客户端-服务器无国籍的可缓存的分层系统按需编码(可选)
https://restfulapi.net/rest-architectural-constraints/
RESTful编程是关于:
资源由持久标识符标识:URI是当今普遍使用的标识符使用一组常见的动词来操纵资源:HTTP方法是常见的情况-古老的Create、Retrieve、Update、Delete变为POST、GET、PUT和Delete。但REST并不局限于HTTP,它只是目前最常用的传输。为资源检索的实际表示取决于请求,而不是标识符:使用Accept标头来控制是否需要XML、HTTP,甚至是表示资源的Java对象保持对象中的状态并在表示中表示状态在资源表示中表示资源之间的关系:对象之间的链接直接嵌入到表示中资源表示描述了如何使用表示,以及在什么情况下应该以一致的方式丢弃/重新处理表示:HTTP缓存控制头的使用
最后一个可能是REST的后果和整体有效性方面最重要的。总体而言,大多数RESTful讨论似乎都集中在HTTP及其在浏览器中的使用上。我知道R.Fielding在描述导致HTTP的架构和决策时创造了这个术语。他的论文更多的是关于资源的体系结构和缓存能力,而不是HTTP。
如果你真的对RESTful架构是什么以及它为什么工作感兴趣,请读几遍他的论文,并阅读整个内容,而不仅仅是第5章!接下来看看DNS为什么工作。阅读DNS的分级组织以及转介的工作原理。然后阅读并考虑DNS缓存的工作原理。最后,阅读HTTP规范(尤其是RFC2616和RFC3040),并考虑高速缓存的工作方式及其原因。最终,它只会咔嚓一声。当我看到DNS和HTTP之间的相似性时,我得到了最后的启示。在这之后,了解SOA和消息传递接口是可伸缩的就开始了。
我认为,要理解RESTful和SharedNothing架构的架构重要性和性能含义,最重要的技巧是避免被技术和实现细节所困扰。关注谁拥有资源,谁负责创建/维护资源等。然后思考表示、协议和技术。
如果我没有直接回答这个问题,我很抱歉,但通过更详细的例子更容易理解这一切。由于所有的抽象和术语,字段化并不容易理解。
这里有一个很好的例子:
解释REST和超文本:垃圾邮件清理机器人Spam-E
更棒的是,这里有一个简单的例子(powerpoint更全面,但你可以在html版本中获得大部分内容):
http://www.xfront.com/REST.ppt或http://www.xfront.com/REST.html
看完这些例子后,我明白了Ken为什么说REST是超文本驱动的。但我实际上并不确定他是对的,因为/user/123是指向资源的URI,我不清楚它是否是非RESTful的,因为客户端知道它是“带外”的
xfront文档解释了REST和SOAP之间的区别,这也非常有用。当Fielding说:“这是RPC。它尖叫RPC。”时,很明显RPC不是RESTful的,所以了解这一点的确切原因很有用。(SOAP是RPC的一种类型。)
这个答案是针对初学者的,让我们了解一下目前最常用的API架构。
了解Restful编程或Restful API。首先,您必须了解什么是API,在一个非常高级的API上,它代表应用程序编程接口,它基本上是一个软件,可以由另一个软件使用,以允许应用程序相互对话。
全球使用最广泛的API类型是web API,而每当有请求时,它都会向客户端发送数据。
事实上,API不仅用于发送数据,而且并不总是与web开发、javascript、python或任何编程语言或框架相关。
API中的应用程序实际上可以意味着许多不同的事情,只要软件的pice是相对独立的。以文件系统或HTTP模块为例,我们可以说它们是一小块软件,我们可以使用它们,我们可以通过使用它们的API与它们进行交互。例如,当我们对任何编程语言的文件系统模块使用read-file函数时,我们实际上使用的是file_system_reading API。或者,当我们在浏览器中进行DOM操作时,我们实际上并不是在使用JavaScript语言本身,而是在使用浏览器向我们公开的DOM API,因此它为我们提供了访问它的权限。或者,再举一个例子,让我们用Java等任何编程语言创建一个类,然后向其添加一些公共方法或财产,这些方法将成为从该类创建的每个对象的API,因为我们给其他软件提供了与我们的初始软件(在本例中为对象)交互的可能性。S0,API实际上具有比构建web API更广泛的含义。
现在让我们来看看构建API的REST体系结构。
REST(代表代表性状态转移)基本上是一种以逻辑方式构建web API的方式,使其易于为自己或他人使用。
要按照REST架构构建Restful API,我们只需要遵循几个原则。1.我们需要将API分成逻辑资源。2.然后应使用基于资源的URL公开这些资源。3.要对数据执行不同的操作,如读取、创建或删除数据,API应使用正确的HTTP方法,而不是URL。4.现在,我们实际发送回客户端或从客户端接收到的数据通常应该使用JSON数据格式,如果应用了某种格式标准。5.最后,EST API的另一个重要原则是它们必须是无状态的。
将API分离为逻辑资源:REST中信息的关键抽象是一种资源,因此,我们希望在API中共享的所有数据都应该划分为逻辑资源。什么是资源?好吧,在REST的上下文中,它是一个对象或某个事物的表示,它有一些与之相关的数据。例如,像导游、用户、地点或评论之类的应用程序就是逻辑资源的例子。因此,基本上任何可以命名的信息都可以是资源。不过,只需要命名,而不是动词。
暴露结构:现在我们需要暴露,这意味着使用一些结构化的URL来提供数据,客户端可以向其发送请求。例如,像这样的整个地址被称为URL。并且调用了这个/addNewTour和API端点。
我们的API将有许多不同的端点,如下所示
https://www.tourguide.com/addNewTour
https://www.tourguide.com/getTour
https://www.tourguide.com/updateTour
https://www.tourguide.com/deleteTour
https://www.tourguide.com/getRoursByUser
https://www.tourguide.com/deleteToursByUser
这些API中的每一个都会将不同的数据发送回客户端,并执行不同的操作。现在,这里的这些端点有一些非常错误的地方,因为它们确实没有遵循第三条规则,即我们应该只使用HTTP方法来对数据执行操作。因此,端点应该只包含我们的资源,而不是我们对其执行的操作,因为它们很快就会成为维护的噩梦。
我们应该如何在实践中使用这些HTTP方法?好了,让我们看看这些端点实际上应该是如何以/getTour开头的。所以这个getTour端点是为了获取关于一个旅游的数据,所以我们应该简单地命名这个端点/旅游,并在向这个端点发出get请求时发送数据。换句话说,当客户端使用GET HTTP方法访问端点时,
(我们只有端点或URL中的资源,没有动词,因为动词现在在HTTP方法中,对吗?通常的做法是总是使用复数形式的资源名称,这就是我写/tours或/tours的原因。)惯例是,当调用端点/游览时,将返回数据库中的所有游览,但如果我们只希望游览具有一个ID,比如说七个,我们会在另一个斜杠(/tours/7)或搜索查询(/tours?ID=7)中添加七个,当然,它也可以是游览的名称而不是ID。
HTTP方法:这里真正重要的是端点名称如何与所有端点名称完全相同。
GET: (for requesting data from the server.)
https://www.tourguide.com/tours/7
POST: (for sending data to the server.)
https://www.tourguide.com/tours
PUT/PATCH: (for updating requests for data to the server.) https://www.tourguide.com/tours/7
DELETE: (for deleting request for data to the server.)
https://www.tourguide.com/tours/7
PUT和PATCH之间的差异->通过使用PUT,客户端应该发送整个更新的对象,而使用PATCH,客户端应该只发送已更改的部分对象。
通过使用HTTP方法,用户可以执行基本的四个CRUD操作,CRUD代表创建、读取、更新和删除。
现在可能会出现如下情况:
因此,/getToursByUser可以简单地转换为/users/tours,对于第3号用户,终点将类似/users/3/tours。
如果我们想删除特定用户的特定游览,那么URL应该是/users/3/tours/7,这里是用户id:3和游览id:7。
因此,像这样整合资源的可能性真的很多。
以JSON形式发送数据:现在,关于客户端实际接收到的数据,或者服务器从客户端接收到的,我们通常使用JSON数据格式。典型的JSON可能如下所示:在发送JSON数据之前,我们通常会进行一些简单的响应格式化,这有几个标准,但其中一个非常简单的标准叫做Jsend。我们只需创建一个新对象,然后向其添加一条状态消息,以通知客户端请求是成功、失败还是错误。然后我们将原始数据放入一个名为data的新对象中。
像我们在这里所做的那样,将数据包装到一个额外的对象中称为包络,这是缓解一些安全问题和其他问题的常见做法。
Restful API应该始终是无状态的:最后,Restful API应该总是无状态的,这意味着,在无状态的Restful API中,所有状态都在客户端处理,而不是在服务器上。状态只是指应用程序中可能随时间变化的一段数据。例如,某个用户是登录的还是在一个包含多个页面的列表的页面上,当前页面是什么?现在,状态应该在客户端上处理这一事实意味着每个请求都必须包含在服务器上处理特定请求所需的所有信息。因此,为了处理当前请求,服务器永远不必记住以前的请求。
让我们假设目前我们在第五页,我们想前进到第六页。因此,我们可以有一个名为/tours/nextPage的简单端点,并向服务器提交一个请求,但服务器必须确定当前页面是什么,并根据该页面将下一个页面发送给客户端。换句话说,服务器必须记住先前的请求。这正是我们希望在RESTful API中避免的。
我们应该创建一个/tours/page端点,而不是这种情况并将数字6粘贴到其上,以请求第6页/游览/第6页。所以服务器不必记住其中的任何内容,它所要做的就是按照我们的要求发回第六页的数据。
无状态和无状态是计算机科学和一般应用中非常重要的概念
REST==HTTP类比是不正确的,除非你不强调它“必须”是HATEOAS驱动的。
罗伊自己在这里清除了它。
输入REST API时,除了初始URI(书签)和适用于预期受众的一组标准化媒体类型(即,预期任何可能使用该API的客户端都能理解)之外,不应有任何先验知识。从那时起,所有应用程序状态转换都必须由客户端选择服务器提供的选择来驱动,这些选择出现在接收的表示中,或者由用户对这些表示的操作来暗示。转换可以由客户端对媒体类型和资源通信机制的知识来确定(或限制),这两者都可以动态地改进(例如,按需编码)。
[这里的失败意味着带外信息正在驱动交互,而不是超文本。]
推荐文章
- ReferenceError: description没有定义NodeJs
- REST API - dto还是不是?
- OData和REST web服务的区别
- Symfony 2.x中的所有东西都应该捆绑吗?
- 用Spring我可以做一个可选的路径变量吗?
- 什么是HTTP“主机”报头?
- 用Python构建最小的插件架构
- 哪个HTTP状态代码表示“尚未准备好,稍后再试”?
- Django REST框架:向ModelSerializer添加额外字段
- 如何阻止恶意代码欺骗“Origin”报头来利用CORS?
- 模式、表和数据库之间的区别是什么?
- 为什么说“HTTP是无状态协议”?
- 我需要HTTP GET请求的内容类型报头吗?
- REST和RPC之间的Web服务差异
- 单页应用:优点和缺点