我有一个典型的Spring Boot Rest API来对用户对象进行crud操作。
Class User{
long id
String displayName
String email
String passwordHash
String passwordSalt
Instant passwordExpiryDate
boolean locked
Instant version (sql timestamp for optimistic locking)
}
POST users/
:创建用户GET users/{id}
:获取用户详细信息PUT users/{id}
:更新用户名和电子邮件PUT users/{id}/password
:更新用户密码PUT users/{id}/unlock
:将锁定状态设置为false DELETE users/{id}
:POST users/
:您不需要提供ID,密码salt / hash或版本,而是生成它们。GET users/{id}
:无需返回id,请求者已经知道了。PUT users/{id}
:只需要一个新的电子邮件,名称和版本。PUT users/{id}/password
:只需要一个新密码和版本PUT users/{id}/unlock
:只需要版本为了应对这种情况,我开始创建几个"请求"类:
这确保我的输入和输出仅包含所需的内容,并且不必读取任何文档以了解哪些属性是强制/使用的。缺点是它很愚蠢,因为它们都代表同一个实体,只是它的不同方面。此外,任何验证(我使用javax约束注释)都会多次声明。
我正在考虑删除所有请求主体,而是使用requestparams(查询参数)来仅提供必要的详细信息,但这会导致我在没有请求主体的情况下进行放置和发布操作。
对于api的客户端和内部结构,似乎没有解决方案。此API设计的最佳实践是什么?
答案 0 :(得分:1)
我强烈建议您为Web API创建模型,而不是公开域(或持久性)模型,从而对API生成和使用的数据进行细粒度控制。
域(或持久性)模型很复杂,通常包含您不希望(或不必)公开的关系和属性。随着时间的推移,字段可能会添加到您的域模型,删除,重命名,修改等等。 如果您公开此类模型,您可能会发现很难在不破坏客户的情况下编排多个版本的API。
通过引入映射框架,您当然可以减少将API模型映射到域模型/从域模型映射的样板代码。
应该对服务层中的域模型执行验证。但是,没有什么可以阻止您对控制器层中的Web API模型执行某种级别的验证。
相关:此answer已解决类似主题。
答案 1 :(得分:0)
我认为为每个操作创建不同的类是错误的,因为业务逻辑围绕同一个实体运行。对所有操作使用相同的对象本身(域对象模型)。您可以根据此类创建不同的验证。