在设计资源层次结构时,何时应该使用子资源?
我曾经认为,当一个资源不能存在而没有另一个资源时,它应该被表示为它的子资源.我最近跑过这个反例:
我把它建模为: /companies/{companyName}/employee/{employeeId}
请注意,我不需要查找公司以找到员工,我也应该这样做?如果我这样做,我付出代价来查找我不需要的信息.如果我不这样做,这个URL错误地返回HTTP 200:
/companies/{nonExistingName}/employee/{existingId}
Dou*_*rop 17
这是有问题的,因为用户属于特定公司不再明显.
有时,这可能会突出显示您的域模型的问题.为什么用户属于公司?如果我改变公司,我是全新的人吗?如果我在两家公司工作怎么办?我是两个不同的人吗?
如果答案是肯定的,那么为什么不采用一些公司唯一标识符来访问用户呢?
例如用户名:
company/foo/user/bar
(bar我的用户名在该特定公司名称空间内是唯一的)
如果答案是否定的,那么为什么我自己不是用户(人),而且这个company/users集合只是指向我:( <link rel="user" uri="/user/1" />注意:员工似乎更合适)
现在你的具体的例子之外,我认为,当涉及到资源子资源的关系更适合使用,而不是所有权(这就是为什么你与识别一个公司的隐含标识企业用户的冗余挣扎).
我的意思是说users实际上是一个企业资源的子资源,因为使用的是定义一个企业与员工之间的关系-说的另一种方式是:你必须定义一个公司,然后才能开始雇用员工.同样,必须先定义(出生)用户(人)才能招募用户.
Gil*_*ili 15
一年后,我以下面的妥协结束(对于包含唯一标识符的数据库行):
/companies/{id}和/employees/{id})为所有资源分配规范URI .HTTP 307 ("Temporary redirect")指向规范URI.这将导致客户端针对规范URI重复操作./companies但不是/employees.这种方法有以下好处:
/companies/{companyId}/employees/{employeeId}/computers/{computerId}.您决定是否应将资源建模为子资源的规则是有效的.您的问题不是来自错误的概念模型,而是让您的数据库模型泄漏到REST模型中.
从概念上看,employee如果它只能存在于company关系中,则将其建模为合成.将employee可因此仅通过鉴定company.现在数据库发挥作用,所有employee行都获得唯一标识符.
我的建议是不要让您的概念模型中的数据库模型泄露,因为您将基础架构问题暴露给您的API.例如,当您决定切换到像MongoDB这样的面向文档的数据库时会发生什么情况,您可以将员工作为公司文档的一部分进行建模,而不再具有这种人为的唯一ID?你想改变你的API吗?
回答你的额外问题
我应该如何表示属于另一个资源的事实?
通过子资源组成,通过URL链接进行其他关联.
我应该如何表示没有另一个资源无法识别资源的事实?
在资源URL中使用这两个id值,并通过检查"组合"是否存在,确保不要让数据库泄漏到API中.
子资源意味着什么关系,而不是模型?
子资源非常适合于合成,但更一般地说是在没有父资源的情况下资源不能存在并且总是属于一个父资源的模型.您的规则when a resource could not exist without another, it should be represented as its sub-resource是对此决定的良好指导.
小智 6
如果子资源在没有其所属实体的情况下是唯一可识别的,则它不是子资源,并且应该有自己的命名空间(即 /users/{user} 而不是 /companies/{*}/users/{user})。最重要的是:永远不要使用实体的数据库主键作为资源标识符。这是最常见的错误,因为实施细节会泄露给外界。您应该始终拥有一个自然的业务密钥(例如用户名或公司编号,而不是用户 ID 或公司 ID)。如果您愿意,可以通过唯一约束来强制这种键的唯一性,但是实体的主键永远不应该离开应用程序的持久层,或者至少它不应该成为任何服务的参数方法。如果遵循此规则,则区分组合 (/companies/{company}/users/{user}) 和关联 (/users/{user}) 应该不会有任何问题,因为如果您的子资源没有一个自然的业务密钥,可以在全局上下文中识别它,您可以非常确定它确实是一个依赖子资源(或者您必须首先创建一个业务密钥以使其可全局识别)。
| 归档时间: |
|
| 查看次数: |
25292 次 |
| 最近记录: |