RESTful 设计:何时使用子资源? [英] RESTful design: when to use sub-resources?

查看:27
本文介绍了RESTful 设计:何时使用子资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在设计资源层次结构时,什么时候应该使用子资源?

When designing resource hierarchies, when should one use sub-resources?

我曾经相信,当一个资源没有另一个资源就不能存在时,它应该被表示为它的子资源.我最近遇到了这个反例:

I used to believe that when a resource could not exist without another, it should be represented as its sub-resource. I recently ran across this counter-example:

  • 员工在所有公司中都是唯一可识别的.
  • 员工的访问控制和生命周期取决于公司.

我将此建模为:/companies/{companyName}/employee/{employeeId}

注意,我不需要查找公司来定位员工,我应该这样做吗?如果我这样做了,我就要付出代价来查找我不需要的信息.如果我不这样做,这个 URL 会错误地返回 HTTP 200:

Notice, I don't need to look up the company in order to locate the employee, so should I? If I do, I'm paying a price to look up information I don't need. If I don't, this URL mistakenly returns HTTP 200:

/companies/{nonExistingName}/employee/{existingId}

  1. 我应该如何表示一个资源属于另一个?
  2. 如果没有其他资源,就无法识别这一事实,我应该如何表述?
  3. 子资源意味着什么关系而不是为了建模?
  1. How should I represent the fact that a resource to belongs to another?
  2. How should I represent the fact that a resource cannot be identified without another?
  3. What relationships are sub-resources meant and not meant to model?

推荐答案

一年后,我以以下妥协结束(对于包含唯一标识符的数据库行):

A year later, I ended with the following compromise (for database rows that contain a unique identifier):

  1. 为所有资源分配根目录下的规范 URI(例如 /companies/{id}/employees/{id}).
  2. 如果一个资源在没有另一个资源的情况下不能存在,它应该被表示为它的子资源;但是,将该操作视为搜索引擎查询.这意味着,不是立即执行操作,而是返回指向规范 URI 的 HTTP 307(临时重定向").这将导致客户端针对规范 URI 重复操作.
  3. 您的规范文档应该只公开与您的概念模型匹配的根资源(不依赖于实现细节).实现细节可能会改变(您的行可能不再是唯一可识别的),但您的概念模型将保持不变.在上面的例子中,你会告诉客户 /companies 而不是 /employees.
  1. Assign all resources a canonical URI at the root (e.g. /companies/{id} and /employees/{id}).
  2. If a resource cannot exist without another, it should be represented as its sub-resource; however, treat the operation as a search engine query. Meaning, instead of carrying out the operation immediately, simply return HTTP 307 ("Temporary redirect") pointing at the canonical URI. This will cause clients to repeat the operation against the canonical URI.
  3. Your specification document should only expose root resources that match your conceptual model (not dependent on implementation details). Implementation details might change (your rows might no longer be unique identifiable) but your conceptual model will remain intact. In the above example, you'd tell clients about /companies but not /employees.

这种方法有以下好处:

  1. 无需进行不必要的数据库查找.
  2. 它将每个请求的健全性检查次数减少到一次.最多,我必须检查一个员工是否属于公司,但我不再需要对 /companys/{companyId}/employees/{employeeId}/computers/{computerId}.
  3. 它对数据库可扩展性有不同的影响.一方面,您通过在更短的时间内锁定较少的表来减少锁争用.但另一方面,您增加了死锁的可能性,因为每个根资源必须使用不同的锁定顺序.我不知道这是净收益还是净损失,但我感到欣慰的是无论如何都无法防止数据库死锁并且由此产生的锁定规则更易于理解和实现.如有疑问,请选择简单.
  4. 我们的概念模型保持不变.通过确保规范文档只公开我们的概念模型,我们可以在未来自由删除包含实现细节的 URI,而不会破坏现有客户端.请记住,只要您的规范将其结构声明为未定义,就不会阻止您在中间 URI 中公开实现细节.
  1. It eliminates the need to do unnecessary database look-ups.
  2. It reduces the number of sanity-checks to one per request. At most, I have to check whether an employee belongs to a company, but I no longer have to do two validation checks for /companies/{companyId}/employees/{employeeId}/computers/{computerId}.
  3. It has a mixed impact on database scalability. On the one hand you are reducing lock contention by locking less tables, for a shorter period of time. But on the other hand, you are increasing the possibility of deadlocks because each root resource must use a different locking order. I have no idea whether this is a net gain or loss but I take comfort in the fact that database deadlocks cannot be prevented anyway and the resulting locking rules are simpler to understand and implement. When in doubt, opt for simplicity.
  4. Our conceptual model remains intact. By ensuring that the specification document only exposes our conceptual model, we are free to drop URIs containing implementation details in the future without breaking existing clients. Remember, nothing prevents you from exposing implementation details in intermediate URIs so long as your specification declares their structure as undefined.

这篇关于RESTful 设计:何时使用子资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆