我已经阅读了一些有关RESTful API设计的有趣教程,其背后的概念非常清楚......但现在让我们将它付诸实践。
假设我们想要实现一个RESTful API,它提供了处理用户的功能。让我们从模型开始。这是Address
类:
case class Address(
id: Int,
street: String,
zip: String,
city: String,
country: String
)
...这里是User
类:
case class User(
id: Int,
email: String,
firstName: String,
lastName: String,
addresses: Array[Int]
// addresses: Array[Address] would this option be better?
)
......最后是路线:
# Creates a new user
POST /users controllers.users.create
# Gets the user identified by the specified id
GET /users/:userId controllers.users.find(userId)
# Modifies the user identified by the specified id
PUT /users/:userId controllers.users.update(userId)
# Deletes the user identified by the specified id
DELETE /users/:userId controllers.users.delete(userId)
第一个问题是:如何通过电子邮件检索用户,保持我的API投诉与REST规则?以下操作无效,因为它与GET users/:userId
:
# Gets the user identified by the specified email address
GET /users/:email controllers.users.findByEmail(email)
到目前为止,我想到的两个选项是:
GET /users controllers.users.list(Option[email])
或
GET /users/:email/xxx controllers.users.findByEmail(email)
其中xxx
应该是一种虚拟资源。有什么建议吗?
我的第二个也是最后一个问题是:我该如何管理用户地址?我应该获得User
,将新Address
添加到User.addresses
,然后使用PUT更新User
吗?
PUT /users/:userId controllers.users.update(userId)
...或者我应该创建一个特定的控制器来管理这样的用户地址吗?
POST /users/:userId/addresses/ controllers.addresses.create(userId)
就个人而言,我更喜欢第二种选择......但也许有更好的选择。
答案 0 :(得分:1)
从您的问题不清楚您是否要实施“获取”或“查找”。通常,“get”会返回404,如果有该电子邮件的用户不存在,但我希望“find”返回200而没有结果。我个人会用这个:
GET /users/find controllers.users.find(email: Option[String])
对第二个问题的回答取决于您是否计划仅更新地址,或者您将始终更新用户整体。例如,您可以拥有一个包含所有用户详细信息的大型表单的网页。地址,您可以使用一个HTTP请求保存所有内容。
或者另一种观点可能是地址是独立资源还是总是与用户一起使用(创建/读取/更新/删除)。
答案 1 :(得分:0)
以下操作无效,因为它与GET用户/:userId
冲突
如果您的用户ID永远不会是有效的电子邮件地址(在此版本的REST API的生命周期内!),它仍然可以工作,因此您的代码可以区分它们 - 这是您当前类型的情况。当然,如果你想在将来放松这个假设,你可以随时介绍一个新的REST API版本(例如,如果你想让用户id为任意字符串),或者如果你决定不喜欢组合这两种类型的查询这一点。
我应该获得用户,将新地址添加到User.addresses,然后使用PUT更新用户?
默认情况下,这不是交易性的。但是,如果您使用ETag,则可以拒绝用户更新,如果其他内容在此期间更改了用户。
答案 2 :(得分:0)
我只想说GET /users/email/:email controllers.users.findByEmail(email)
,如果存在给定电子邮件的用户存在,则返回200,否则返回404。
我可以看到这个吸引力,但是我会在他的想法上与@Robin搏斗。它在技术上是可行的,但由于我对REST的Identification of Resources元素的解释,它对我来说并不感觉findByName
,findByEmail
等规范方法名称而有所偏见,但从不findByYourGuessIsAsGoodAsMine
。
很明显,用户是有趣的资源,而不是电子邮件(注意我使用电子邮件,您使用地址以区分我脑海中的物理地址)。我的路线看起来与users/:userId/emails/
基本相似,并在Users
控制器中管理它们。我认为没有理由 - 无论是从软件工程角度还是从思想上的REST角度 - 来增加额外课程的开销。