创建、更新和获取休息端点中的相同/不同 DTO 对象?

Posted

技术标签:

【中文标题】创建、更新和获取休息端点中的相同/不同 DTO 对象?【英文标题】:Same/different DTO object in create, update and get rest end points? 【发布时间】:2016-05-01 15:59:20 【问题描述】:

考虑遵循 UserDTO 类和 UserController 暴露端点以创建、更新和获取用户。

在 UserDTO 类中拥有 id 属性对于创建和更新没有意义。如果我使用 swagger 或其他自动生成的 API 文档,那么它表明 id 可以在创建端点中传递。但是系统不使用它,因为 ids 是内部生成的。

如果我看一下 get 那么可能我可以摆脱 id 属性,但它肯定是列表用户端点所必需的。

我正在考虑在 get/list 端点中返回内部用户域对象。这样我就可以摆脱 UserDTO 类的 id 属性。

我可以为此采用更好的选择吗?

public class UserDTO 
    private int id;
    private String name;

    public int getId() 
        return id;
    

    public void setId(int id) 
        this.id = id;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    


@RestController
@RequestMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController 
    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<Void> create(@RequestBody UserDTO user) 
    

    @RequestMapping(value = "id", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<UserDTO> get(@PathVariable("id") int id) 
    

    @RequestMapping(value = "id", method = RequestMethod.PUT)
    @ResponseBody
    public ResponseEntity<Void> update(@PathVariable("id") int id, @RequestBody UserDTO user) 
    

可能有人问过这个问题,但我找不到。所以请原谅我重复的问题。

【问题讨论】:

【参考方案1】:

Data Transfer Object (DTO) 是一种具有明确目的的模式:将数据传输到远程接口,就像 Web 服务。这种模式非常适合 REST API,从长远来看,DTO 将为您提供更多灵活性

一旦 REST 资源表示不需要具有与持久性对象相同的属性,我建议为您的端点使用定制的类。

为避免使用样板代码,您可以使用映射框架(例如 MapStruct)将您的 REST API DTO 从/到您的持久性对象映射。

有关在 REST API 中使用 DTO 的好处的详细信息,请查看以下答案:

Why you should use DTOs in your REST API Using tailored classes of request and response

要给您的 DTO 起更好的名字,请检查以下答案:

Giving meaningful names to your DTOs

【讨论】:

【参考方案2】:

创建两个不同的接口是什么意思:

interface UserDTO 

    public String getName ();

    public void setName (String name);



interface IdentifiableUserDTO extends UserDTO 

    public Long getId ();

    public void setId (Long id);




class DefaultUserDTO implements IdentifiableUserDTO 


然后在控制器中使用接口而不是 DTO 类:

@RestController
@RequestMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController 
    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<Void> create(@RequestBody IdentifiableUserDTO user) 
    

    @RequestMapping(value = "id", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<UserDTO> get(@PathVariable("id") int id) 
    

    @RequestMapping(value = "id", method = RequestMethod.PUT)
    @ResponseBody
    public ResponseEntity<Void> update(@PathVariable("id") int id, @RequestBody UserDTO user) 
    

【讨论】:

Wael 是的,这是选项之一。但我只是提到了一个这样的属性。还有更多类似 createdBy、createdTime、updatedBy、updatedTime 等,它们在 get 中是必需的,但对 create/update 没有意义。可能会使用这种模式,而不是调用 IdentifiableUserDTO 调用其他东西,不确定什么是合适的。

以上是关于创建、更新和获取休息端点中的相同/不同 DTO 对象?的主要内容,如果未能解决你的问题,请参考以下文章

根据条件限制/锁定所有 Post/Delete Rest API 端点 [关闭]

单个休息“放置”端点是不是足以更新带有嵌套数组的文档?

如何获取 OData 可查询 Web API 端点过滤器并从 DTO 对象映射它?

多个字段解析器使用不同的查询参数解析相同的 REST API

创建 web 应用程序的最佳方法,该应用程序在外部客户端调用他自己的休息服务时动态更新 UI [关闭]

并排托管 WCF 肥皂和休息端点