为支持不同ID的GET请求设计REST端点

时间:2018-08-19 08:20:08

标签: rest

我寻求有关设计API端点的建议。

我有一个ID为(PK)的表(资源)和一些其他ID,它们不是唯一的,但没有空约束。

现在设计:

  1. 对于PK搜索/<resourceName>/{id}
  2. 非PK搜索

    2.1 /<resourceName>/someOtherIdName/{someOtherId}-使用路径参数,对于不同的ID是不同的

    2.2或/<resourceName>?<nameOfId>=<value>-使用查询参数

对于第二种方法,哪种方法更好?如果我使用2.2,则可以支持多个ID,但是由于我必须检查nameOfId,所以它变得令人费解。那2.1呢?

编辑:例如,以transactions作为资源,以txn_id作为主键,以txn_event_idtxn_activity_id作为其他键ID。最后两个ID可以代表一组相关的交易。 2.2是否适合最后两个ID?

在2.1的情况下,实现如下所示:

@Path("/transactions")
class TransactionResource {
    @Path("/eventid/{event_id}")
    public List getTxnWithEventId(@PathParam("event_id") String eventId) {
        // do a "event_id" based search
    }

   @Path("/activityid/{activity_id}")
    public List getTxnWithActivityId(@PathParam("activity_id") String txnActivityId) {
        // do a "pin" based search
    }
}

在2.2的情况下,实现类似于:

@Path("/transactions")
class TransactionResource {
    public List getTxnsWithAnotherId(@QueryParam("searchKey") String id, 
        @QueryParam("searchValue") String value) {
        if("event_id".equals(id)) // do a "event_id" based search
        else if("activity_id".equals(id)) // do a "activity_id" based search
        else return null;
    }
}

我认为第二个选项对于搜索而言感觉更好,但如果是这样,为什么不选择第二个呢?

3 个答案:

答案 0 :(得分:0)

我认为一切都取决于开发人员的偏好。我不会使用您列出的任何一个选项。我的方法是collectionId/resourceId/collectionId/resourceId。因此,在您的情况下,将获得users/1/messages特定用户的所有消息,例如users/1/messages/1,以获取该特定用户的ID为1的消息。这样,您可以创建更清晰的API终结点,这些终结点可以在您的应用中更有效地路由,并且可以得到更好的文档编制和管理。

看看Google's API Design Guide如何针对其Gmail资源模型来解决这个问题:

A collection of users: users/*. Each user has the following resources.
A collection of messages: users/*/messages/*.
A collection of threads: users/*/threads/*.
A collection of labels: users/*/labels/*.
A collection of change history: users/*/history/*.
A resource representing the user profile: users/*/profile.
A resource representing user settings: users/*/settings.

答案 1 :(得分:0)

  

对于第二个,哪种方法更好?

对于大多数用例,这两种方法都很好

/<resourceName>?<nameOfId>=<value>
/<resourceName>/<nameOfId>/<value>

西红柿,番茄。

您可能会关心差异的一个原因是相对分辨率和dot segments的使用。点段对于遍历URI的层次结构部分(即路径段)很有用。

您可能会关心的另一个原因是URI的query part并不总是被理解为标识符的一部分。 HTTP规范的Old versions描述了当存在查询部分时缓存规则的例外。在the current standard中,这没有什么不同。

如果您在将URI的可读性与编码到路径段中的数据作斗争时遇到了麻烦,那么有许多拼写约定可能会有所帮助-许多都是从TBL在Matrix URI上的工作中得出的。如果您的客户端和服务器可以访问不错的URI Template实现,那么您已经完成了很多工作。

答案 2 :(得分:-1)

我不确定您的资源具体是什么,但是这里是设计RESTful API时要记住的一些提示

标识什么是主要资源。 例如:员工

在第一种情况下,您将以

的身份访问员工
  1. GET /employees。获取所有员工。
  2. GET /employees/1。获取ID为1的特定员工。

搜索特定于您的需求。如果您需要根据ID提取多名员工,则可以

GET /employees?id=1,2,3,4

或者,如果您发现需要基于多个参数进行搜索,则建议您使用POST

POST /employees/search

{
 id: [1,2,3,4],
 department: "computer-science"
}