RESTful编程到底是什么?


当前回答

如果我没有直接回答这个问题,我很抱歉,但通过更详细的例子更容易理解这一切。由于所有的抽象和术语,字段化并不容易理解。

这里有一个很好的例子:

解释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的一种类型。)

其他回答

什么是REST?

用官方的话说,REST是一种基于使用当前“Web”基础的特定原则构建的架构风格。web有5个基本基础,可用于创建REST服务。

原则1:一切都是资源在REST体系结构风格中,数据和功能被视为资源,并使用统一资源标识符(URI)(通常是Web上的链接)进行访问。原则2:每个资源都由唯一标识符(URI)标识原则3:使用简单统一的接口原则4:通过代表进行沟通原则5:无状态

REST使用各种HTTP方法(主要是GET/PUT/DELETE)来处理数据。

您不需要使用特定的URL来删除方法(例如/user/123/delete),而是向/user/[id]URL发送delete请求,以编辑用户,检索有关向/user/[id]发送GET请求的用户的信息

例如,取而代之的是一组URL,可能看起来像下面的一些。。

GET /delete_user.x?id=123
GET /user/delete
GET /new_user.x
GET /user/new
GET /user?id=1
GET /user/id/1

您使用HTTP“动词”并具有。。

GET /user/2
DELETE /user/2
PUT /user

老问题,新的回答方式。关于这个概念有很多误解。我总是努力记住:

结构化URL和Http方法/动词不是restful编程。JSON不是restful编程RESTful编程不适用于API

我将restful编程定义为

如果应用程序以客户端理解的媒体类型提供资源(是数据+状态转换控件的组合),则该应用程序是静止的

要成为一个安静的程序员,您必须尝试构建允许参与者做事的应用程序。不仅仅是公开数据库。

只有当客户端和服务器同意资源的媒体类型表示时,状态转换控制才有意义。否则,无法知道什么是控件,什么不是控件,以及如何执行控件。IE如果浏览器不知道html中的<form>标签,那么在浏览器中就没有什么可以提交到过渡状态。

我不想自我推销,但我在演讲中深入阐述了这些想法http://techblog.bodybuilding.com/2016/01/video-what-is-restful-200.html .

我演讲中的一段摘录是关于经常提到的richardson成熟度模型,我不相信这些级别,你要么是RESTful(级别3),要么不是,但我想指出的是,在你走向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年,我们最终被天网终止。在此之前…;-)

这个答案是针对初学者的,让我们了解一下目前最常用的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页。所以服务器不必记住其中的任何内容,它所要做的就是按照我们的要求发回第六页的数据。

无状态和无状态是计算机科学和一般应用中非常重要的概念