正如之前的评论中已经解释的那样,REST 不太关心标识唯一资源的链接的实际形式,除非RESTful 约束 https://en.wikipedia.org/wiki/Representational_state_transfer或者违反了超文本传输协议 (HTTP) 本身。
关于查询或路径(甚至矩阵)参数的使用完全取决于您。有没有固定的规则 https://stackoverflow.com/questions/11552248/when-to-use-queryparam-vs-pathparam什么时候使用什么只是个人喜好。
我喜欢使用查询参数,尤其是当该值是可选的并且不需要像 JAX-RS 这样的大量框架时,即允许定义默认值。人们常说查询参数是为了避免缓存响应,但是与其说是事实,不如说是都市传说 http://www.bizcoder.com/caching-resources-with-query-strings,尽管某些实现可能仍然会忽略对包含查询字符串的 URI 进行缓存的响应。
如果参数定义了诸如特定风味属性(即汽车颜色)之类的东西,我更喜欢将它们放入矩阵参数中。它们也可以出现在 URI 的中间,即/api/professors;hair=grey/courses
可以返回所有由头发颜色为灰色的教授开设的课程。
根据我的理解,路径参数是应用程序满足请求所需的强制参数,否则将不会首先在服务端调用相应的方法处理程序。通常这是一些资源标识符,例如分配给特定实体的表行 ID 或 UUID。
在描述关系时,我通常从 1:n 关系的 1 部分开始。如果我面对一种多对多的关系,就像你与教授的情况一样,我通常会从可能更容易存在的实体开始。即使教授不举办任何讲座(在特定术语中),他仍然是教授。如果没有教授,课程就不再是课程,所以我会把教授放在课程之前,尽管就 REST 而言,课程仍然是很好的顶级资源。
因此我会改变你的查询
GET /api/courses?where={professor_id: "teacher45", year: 2016}&order={attr: "topic", sort: "asc"}
像这样的东西:
GET /api/professors/teacher45/courses;year=2016?sort=asc&onField=topic
我稍微改变了你的字段的语义,因为年份属性可能更适合课程而不是教授资源,因为教授已经通过教授 ID 简化为单一资源。然而,这些课程应该仅限于 2016 年举办的课程。由于排序是相当可选的,并且可能指定了默认值,因此这是我放入查询参数部分的完美候选者。排序依据的字段与排序本身相关,因此也属于查询参数。我将年份放入矩阵参数中,因为这是课程本身的特定属性,例如汽车的颜色或汽车的制造年份。
但正如之前所解释的,这是相当固执己见的,可能与您或其他人的观点不符。