如何设计REST API

学习REST是件好事,而将所有学到的概念应用到实际应用程序设计中则完全是另一项挑战。在本教程中,我们将学习为基于网络的应用程序设计REST API。请注意,整个练习的内容是学习如何在设计过程中应用REST原则

设计REST服务的步骤
识别对象模型
创建模型URI
确定表示形式
分配HTTP方法
更多操作

googletag.cmd.push(function() { googletag.display('waldo-tag-4084'); });

识别对象模型

设计基于REST API的应用程序的第一步是 - 识别将作为资源呈现的对象。

对于基于网络的应用程序,对象建模非常简单。可能有许多东西,如设备,管理实体,路由器,调制解调器等。为简单起见,我们将只考虑两个资源,即

  • 设备
  • 配置

这里配置是设备的子资源。设备可以有许多配置选项。

请注意,上述模型中的两个对象/资源都将具有唯一标识符,即整数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类似于顶级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 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}

浏览单个设备或配置[Secondary Collection]

HTTP GET /devices/{id}/configurations/{id}

子资源表示将与主要表示相同或为主要表示的子集。

创建设备或配置

Create不是幂等操作,在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>

更新设备或配置

更新操作是幂等操作,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。

请注意,在从系统中删除子资源时,应该对决定行为进行足够的分析。通常,您可能希望在这些请求中SOFT删除资源 - 换句话说,将其状态设置为INACTIVE。通过遵循此方法,您不需要从其他位置查找和删除其引用。

从设备应用或删除配置

在实际应用程序中,您需要在设备上应用配置 - 或者您可能希望从设备中删除配置(而不是从主要集合中删除)。在这种情况下,您应使用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中创建此应用程序以获得更详细的理解。