如何设计REST API
分段学习REST是一回事,而将所有这些学到的概念应用到实际应用程序设计中则完全是另一挑战。在本教程中,我们将学习为基于网络的应用程序设计REST API。请注意,整个练习的主要内容是学习如何在设计过程中应用REST原理。
- 设计REST服务的步骤
- 识别对象模型
- 创建模型URI
- 确定表示形式
- 分配HTTP方法
- 更多操作
识别对象模型
设计基于REST API的应用程序的第一步是–确定将作为资源呈现的对象。
对于基于网络的应用程序,对象建模要简单得多。可以有很多东西,例如设备,管理实体,路由器,调制解调器等。为简单起见,我们将仅考虑两个资源,即
- 设备
- 构型
这里的配置是设备的子资源。设备可以具有许多配置选项。
请注意,我们上面的模型中的两个对象/资源都将具有唯一的标识符,这是integer id
属性。
创建模型URI
现在,当对象模型准备就绪时,就该确定资源URI了。在此步骤中,在设计资源URI时 -着重于资源及其子资源之间的关系。这些资源URI是RESTful服务的端点。
在我们的应用程序中,设备是顶级资源。而配置是设备下的子资源。让我们写下URI。
/devices
/devices/{id}
/configurations
/configurations/{id}
/devices/{id}/configurations
/devices/{id}/configurations/{id}
请注意,这些URI不使用任何动词或操作。在URI中不要包含任何动词非常重要。URI都只能是名词。
确定制图表达
现在确定了资源URI后,让我们开始研究它们的表示形式。通常,表示形式以XML或JSON格式定义。我们将看到XML示例在表达数据构成方面更具表现力。
设备资源收集
返回收集资源时,仅包括有关资源的最重要信息。这将使有效负载的大小保持较小,因此将提高REST API的性能。
<devices size="2">
<link rel="self" href="/devices"/>
<device id="12345">
<link rel="self" href="/devices/12345"/>
<deviceFamily>apple-es</deviceFamily>
<OSVersion>10.3R2.11</OSVersion>
<platform>SRX100B</platform>
<serialNumber>32423457</serialNumber>
<connectionStatus>up</connectionStatus>
<ipAddr>192.168.21.9</ipAddr>
<name>apple-srx_200</name>
<status>active</status>
</device>
<device id="556677">
<link rel="self" href="/devices/556677"/>
<deviceFamily>apple-es</deviceFamily>
<OSVersion>10.3R2.11</OSVersion>
<platform>SRX100B</platform>
<serialNumber>6453534</serialNumber>
<connectionStatus>up</connectionStatus>
<ipAddr>192.168.20.23</ipAddr>
<name>apple-srx_200</name>
<status>active</status>
</device>
</devices>
单设备资源
与集合URI相反,此处在此URI中包含设备的完整信息。在这里,还包括子资源和其他支持的操作的链接列表。这将使您的REST API HATEOAS驱动。
<device id="12345">
<link rel="self" href="/devices/12345"/>
<id>12345</id>
<deviceFamily>apple-es</deviceFamily>
<OSVersion>10.0R2.10</OSVersion>
<platform>SRX100-LM</platform>
<serialNumber>32423457</serialNumber>
<name>apple-srx_100_lehar</name>
<hostName>apple-srx_100_lehar</hostName>
<ipAddr>192.168.21.9</ipAddr>
<status>active</status>
<configurations size="2">
<link rel="self" href="/configurations" />
<configuration id="42342">
<link rel="self" href="/configurations/42342" />
</configuration>
<configuration id="675675">
<link rel="self" href="/configurations/675675" />
</configuration>
</configurations>
<method href="/devices/12345/exec-rpc" rel="rpc"/>
<method href="/devices/12345/synch-config"rel="synch device configuration"/>
</device>
配置资源收集
与设备集合表示类似,仅使用最少的信息即可创建配置集合表示。
<configurations size="20">
<link rel="self" href="/configurations" />
<configuration id="42342">
<link rel="self" href="/configurations/42342" />
</configuration>
<configuration id="675675">
<link rel="self" href="/configurations/675675" />
</configuration>
...
...
</configurations>
请注意,configurations
内部的集合表示device
类似于顶级configurations
URI。唯一的区别是,configurations
一个设备只有两个,因此只有两个配置项被列为设备下的子资源。
单一配置资源
现在,单个配置资源表示必须具有有关该资源的所有可能信息-包括相关链接。
<configuration id="42342">
<link rel="self" href="/configurations/42342" />
<content><![CDATA[...]]></content>
<status>active</status>
<link rel="raw configuration content" href="/configurations/42342/raw" />
</configuration>
单个设备下的配置资源收集
配置的此资源集合将是配置的主要集合的子集,并且仅特定于设备。由于它是主集合的子集,因此请勿创建与主集合不同的表示形式数据字段。使用与主要集合相同的表示字段。
<configurations size="2">
<link rel="self" href="/devices/12345/configurations" />
<configuration id="53324">
<link rel="self" href="/devices/12345/configurations/53324" />
<link rel="detail" href="/configurations/53324" />
</configuration>
<configuration id="333443">
<link rel="self" href="/devices/12345/configurations/333443" />
<link rel="detail" href="/configurations/333443" />
</configuration>
</configurations>
请注意,此子资源集合具有两个链接。
一个用于直接在子集合中表示,即/devices/12345/configurations/333443
,
另一个指向其在主要集合中的位置,即/configurations/333443
。
具有两个链接非常重要,因为您可以以更独特的方式提供对设备特定配置的访问,并且您将能够屏蔽某些字段(如果设计需要),这些字段在辅助集合中不可见。
单个设备下的单个配置资源
此表示应具有与主集合中的Configuration表示完全相同的表示;或者,您可能会掩盖一些字段。
此子资源表示形式还将具有指向其主要表示形式的附加链接。
<configuration id="11223344">
<link rel="self" href="/devices/12345/configurations/11223344" />
<link rel="detail" href="/configurations/11223344" />
<content><![CDATA[...]]></content>
<status>active</status>
<link rel="raw configuration content" href="/configurations/11223344/raw" />
</configuration>
现在,在进入下一部分之前,让我们记下一些观察结果,以免您错过它们。
- 资源URI都是名词。
- URI通常采用两种形式-资源收集和单一资源。
- 收集可以采用两种形式:一次收集和二次收集。次要集合是仅主要集合中的子集合。
- 每个资源/集合至少包含一个链接,即指向自身的链接。
- 集合仅包含有关资源的最重要信息。
- 要获取有关资源的完整信息,您仅需要通过其特定的资源URI进行访问。
- 表示形式可以具有额外的链接(即单个设备中的方法)。这里
method
代表一个POST方法。您也可以以全新的方式拥有更多属性或形成链接。 - 我们还没有谈论这些资源上的操作。
分配HTTP方法
因此,我们的资源URI及其表示形式现已修复。让我们确定应用程序中可能的操作,并将这些操作映射到资源URI。网络应用程序的用户可以执行浏览,创建,更新或删除操作。因此,让我们对其进行映射。
浏览所有设备或配置[主集合]
HTTP GET /devices
HTTP GET /configurations
如果集合很大,则也可以应用分页和过滤。例如,下面的请求将从集合中获取前20条记录。
HTTP GET /devices?startIndex=0&size=20
HTTP GET /configurations?startIndex=0&size=20
浏览所有设备或配置[次级集合]
HTTP GET /devices/{id}/configurations
这主要是一个小规模的集合-因此无需在此处启用过滤或筛选。
浏览单个设备或配置[主集合]
要获取设备或配置的完整详细信息,请GET
对单个资源URI 使用操作。
HTTP GET /devices/{id}
HTTP GET /configurations/{id}
浏览单个设备或配置[次级集合]
HTTP GET /devices/{id}/configurations/{id}
子资源表示将与主要表示相同或相同。
创建设备或配置
创建不是幂等操作,并且在HTTP协议中- POST
也不是幂等。因此,请使用POST。在REST API的上下文中,发出多个相同的请求与发出单个请求具有相同的效果–然后将该REST API称为幂等
HTTP POST /devices
HTTP POST /configurations
请注意,请求有效负载将不包含任何id
属性,因为服务器负责决定它。创建请求的响应将如下所示:
HTTP/1.1 201 Created
Content-Type: application/xml
Location: http://example.com/network-app/configurations/678678
<configuration id="678678">
<link rel="self" href="/configurations/678678" />
<content><![CDATA[...]]></content>
<status>active</status>
<link rel="raw configuration content" href="/configurations/678678/raw" />
</configuration>
更新设备或配置
更新操作是幂等操作,HTTP PUT
也是幂等方法。因此我们可以使用PUT方法进行更新操作。
HTTP PUT /devices/{id}
HTTP PUT /configurations/{id}
PUT响应可能如下所示。
HTTP/1.1 200 OK
Content-Type: application/xml
<configuration id="678678">
<link rel="self" href="/configurations/678678" />
<content><![CDATA[. updated content here .]]></content>
<status>active</status>
<link rel="raw configuration content" href="/configurations/678678/raw" />
</configuration>
删除设备或配置
删除始终是一项DELETE
操作。
HTTP DELETE /devices/{id}
HTTP DELETE /configurations/{id}
成功的响应应该是202 (Accepted)
资源是否已排队删除(异步操作),或者200 (OK)
/ 204 (No Content)
如果资源已永久删除(同步操作)。
在异步操作的情况下,应用程序应返回一个任务ID,该任务ID可以跟踪成功/失败状态。
*请注意,当从系统中删除子资源时,您应该进行足够的分析以确定行为。通常,您可能希望在这些请求中“ **软删除”*资源-换句话说,将其状态设置为“不活动”。通过遵循这种方法,您也无需在其他地方查找和删除其引用。
从设备应用或删除配置
在实际应用程序中,您将需要在设备上应用配置–或者您可能希望从设备(而不是从主集合中)删除配置。在这种情况下,由于其幂等性质,应使用PUT和DELETE方法。
// Apply Configuration on a device
HTTP PUT /devices/{id}/configurations
//Remove Configuration on a device
HTTP DELETE /devices/{id}/configurations/{id}