如何解决REST和数据库的对象命名约定
在使用Java的REST API构建CRUD应用程序时,我一直在不断创新,我正在寻找某种适用的标准。
让我们以示例的方式进行。假设我有一个“用户”表和这些REST端点:
GET /users/{user_id} // returns a user
POST /users // creates a user
PUT /users/{user_id} // updates a user
在每种方法中,我必须选择,插入或更新数据库中的用户。
对于这六个操作中的每个操作(REST操作3个,数据库操作3个),我需要通过REST传入或发送到数据库的“用户” POJO的不同属性集。
例如,在REST端,创建用户时,我不需要user_id(因为它是由数据库创建的),但是我确实需要密码。获取用户时,我确实需要user_id,但我永远不想将密码返回给客户端。更新用户时,我可能要忽略一些字段,因为它们是只读的(例如用户名或创建日期)。
在数据库方面,我可能需要不同的字段,这些字段不会在REST API中传递回去,例如“ is_approved”或“ some_secret”。而且我经常需要创建派生字段,例如“ password_hash”。
因此,正如我所说,同一件事的六个不同表示形式。在Java中,我通过制作六个不同的POJO类来做到这一点。并不总是需要那么多独特的类,但有时却需要。
在REST API中,我不想对所有端点使用相同的类,而只是忽略某些字段,因为该类已传递给我们的API文档工具并且其属性已发布。
这六个类是否有标准的命名约定?
过去,对于REST,我曾使用过CreateUser,GetUser和UpdateUser。我不喜欢这些名称,因为它们是动词,应该是名词。
UserForCreation和UserForUpdate很尴尬。 NewUser和ModifiedUser可能不错,但是我不知道如何调用GET用户。
在数据库端,我还需要另外一套完整的名称。
对于这种事情,肯定有一个标准或约定。有人知道这是什么吗?
解决方法
我认为您通常对每个请求和响应都具有特定对象的想法是正确的;但是,根据API的设计,您实际上只需要一个User
类。您可以使用构建器来抽象出创建逻辑(例如生成用户ID),并将请求对象传递到位于REST端和数据库之间的DAO中。 DAO将仅接受请求,检索用户数据,构建并返回User
对象。
一旦创建了用户对象,便可以将其用于创建响应对象,该对象将被序列化并放入响应数据中。最好编写两个用户类(类似User
和InternalUser
),以便更明确地向客户端公开哪些数据,尤其是在写入客户端的情况下。与API相同的库。您无法实现额外的InternalUser
并无法在响应对象构建器,工厂或构造器中处理字段过滤;但是,如果客户端是在同一库中编写的,则可能会泄漏敏感或必要的信息。
您可能希望查看Swagger个文件。该标准提供了一个很好的REST Api规范,该规范非常简单,并提供了一种模板化API结构的好方法,即使它们经常看起来像json或xml的墙一样。
tl;博士 (根据@Turing85
的建议- CreateUser [请求|响应]
- GetUser [请求|响应]
- UpdateUser [请求|响应]
- 用户
- InternalUser
此方法受到HexagonalArchitecture / Clean Architecture / Ports and Adapters的借鉴/启发。由于我们已经将DTO和业务对象完全分开,因此我们非常接近上述架构。在“干净架构”中,鲍伯叔叔谈到了“用例”。每个用例都有一些输入和一些输出。我们可以将输入想象成对用例的 request ,将输出看作对给定请求的 response 。因此,对于业务实体User
以及create
,get
,update
等的用例,...其中一个这样的实体,我建议使用以下命名模式:
<use-case><Business-entity>[Request|Response]
对于给定的示例,这意味着我们将创建类
-
CreateUserRequest
,CreateUserResponse
-
GetUserRequest
,GetUserResponse
-
UpdateUserRequest
,UpdateUserResponse
更重要的是:对于Create
和Update
之类的复杂操作,我们可以提取公共字段并将它们放在超类中(如果只有Java具有多重继承性,我们可以使用mixins ... ),只留下实际的用例请求数据来定义我们真正需要的数据。在许多情况下,响应是相同的,因此有意义的是使用通用的UserResponse
类而不是许多不同的响应。这提供了一致的API响应的额外好处,例如如果要返回用户列表,则可以返回List<UserResponse>
(可能还有一些分页信息)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。