2016-10-04 48 views
3

我正在构建一个REST API,并且我有一些关系使得我的链接非常长。它们对我来说很有意义,但它是一团糟。我不知道处理这个问题的最好方法是什么。有这么长的链接有问题吗?我是否违反了这些原则?我应该如何处理这样的关系?在REST API中处理非常深的关系

下面的例子是有点人为的,但它说明了我想要做的。

一个公司有许多部门。每个部门有很多雇员。每个雇员可以有许多计算机。每个计算机可以有很多文件就可以了。

GET的路径特定的文档将是:

/companies/:companyId/departments/:departmentId/employees/:employeeId/computers/:computerId/documents/:documentId 

每个ID是该层内的全局唯一 - 没有两个文档ID将是在整个系统中的相同,但一个文件ID可以是与员工ID相同。

这对我来说很有意义,因为每一层只与上面的一件事有关。一个部门将只属于一个公司,一个员工只属于一个部门,一部电脑只属于一个员工,而一个文件只属于一部电脑。

我可以将它们分解为单独的端点,例如/computers,但是我怎么知道在哪里破坏它们?为什么我会选择/computers作为端点,而不是/employees/:employeeId/computers

+0

**是全球唯一的** documentId **吗? – JonSG

+0

@JonSG是的,它在所有文档ID中都是唯一的。我编辑了这个问题来澄清。 – vaindil

+2

我的意见在这里,但我觉得没有必要在API中表示它们的层次结构。你在一个例子中说明的那个,但可能有很多其他的。我觉得你的API应该简化为**/document/[id] **。同样,如果employeeid是全球唯一的,那么** employee/[id] **。为什么让消费者知道员工和部门是否想知道具有已知ID的文件内容?另一方面,初始投贴是一个不同的问题,因此可能需要层次结构。是否需要支持“完整”动词集,或者获得足够的? – JonSG

回答

2

在这个例子中,我将把这些资源中的每一个都移动到顶层。每个顶级资源都可以有下一个“级别”作为成员。所以,

/companies 
/companies/{id} 
/companies/{id}/departments 
/departments 
etc.. 

我只会添加子资源,如果它实际上是最终用户需要操纵集合的内容。

深度嵌套的资源是有问题的。在3个月内,如果您的企业要求找到所有员工,而不管部门为公司{id}工作,会发生什么情况?将员工作为顶级资源,您可以添加对GET /employees?companyId={id}的支持。在上面介绍的设计中,您的选择都很糟糕。在您正式确定嵌套结构时,您放弃的资源之间的关系具有很大的灵活性。

至于你的一些具体问题:

我建立一个REST API

REST是对URI设计的主题完全无关。

我有一些关系让我的链接很长。它们对我来说很有意义,但它是一团糟。 [..]有这么长的链接是一个问题吗?

最终用户将希望永远不会打字这些。如果你的API真的是RESTful的,则客户端将使用您传回的联系,他们不应该在任何输入它们。在一个RESTful系统中,我期望“我有一些X”关系被保存在一个链接中,而不仅仅是通过URI的形式记录。我同意他们是长期的,我会根据上述原因改变他们,但我不认为你的具体担忧是改变他们的好理由。

我违反了这些原则吗?

不是我所知道的。

+0

我完全同意REST是URI不可知的,并且过分强调所谓的干净URI设计。尽管如此,我也不会将每个子资源都更改为顶级资源。我个人的偏好是如果资源能够自己“生存”,就将资源转换为顶级资源。一个部门与一个公司紧密相连,一个员工仍然会在没有公司的情况下生活,但它不再是该公司的员工,因此我将它作为子资源。另一方面,计算机仍然是一台计算机,无论公司如何,因此适用于顶级资源。 –

+0

@RomanVottner所以在这个例子中,你只有部门作为子资源?如果你能确保紧密的耦合是永恒的,我不会不同意这种方法。如果该业务规则发生变化,尽管... –

+0

员工也耦合到公司,否则它不会是员工。如果员工退出公司并且没有任何生命危险发生在她身上,她仍然会生活,但不会成为该公司的员工。即使业务规则发生变化和/或部门合并/分裂,一个真正的RESTful客户端也不会因为他们仅仅从以前的响应中学习而中断。与URI相关的问题总是倾向于自以为是的答案,尽管SO社区并不热衷于关闭这样的问题IMO。 –