分段学习REST是一回事,而将所有学到的概念应用到实际应用程序设计中则完全是另一挑战。在本教程中,我们将学习为基于网络的应用程序设计REST API。请注意,整个练习的主要内容是学习如何在设计过程中应用REST原理。
识别对象模型
设计基于REST API的应用程序的第一步是–确定将作为资源呈现的对象。
对于基于网络的应用程序,对象建模要简单得多。可以有很多东西,例如设备,管理实体,路由器,调制解调器等。为简单起见,我们将仅考虑两种资源,即
- 设备
- 构型
这里的配置是设备的子资源。设备可以具有许多配置选项。
请注意,我们上面的模型中的两个对象/资源都将具有唯一的标识符,这是integerid属性。
创建模型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形式类似于顶级configurationsURI。唯一的区别是,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。
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> |
更新设备或配置
更新操作是幂等操作,HTTPPUT也是幂等方法。因此我们可以使用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。
请注意,当从系统中删除子资源时,您应该进行足够的分析以确定行为。通常,您可能希望在这些请求中“软件删除”资源-换句话说,将其状态设置为“不活动”。通过遵循这种方法,您也无需在其他地方查找和删除其引用。
从设备应用或删除配置
在实际的应用程序中,您将需要在设备上应用配置–或者您可能希望从设备(而不是从主集合中)删除配置。在这种情况下,由于其幂等性质,应使用PUT和DELETE方法。
//Apply Configuration on a device HTTP PUT /devices/{id}/configurations
//Remove Configuration on a device HTTP DELETE /devices/{id}/configurations/{id} |
更多操作
到目前为止,我们仅设计了对象模型,URI,然后确定了HTTP方法或对其的操作。您还需要处理应用程序的其他方面:
1)记录
2)安全
3)发现等
在下一篇文章中,我们将使用Java创建此应用程序以更详细地了解。