为REST请求和响应创建不同的类是不是很糟糕?

meo*_*173 8 java rest

我正在使用Spring Boot项目,作为我目前的工具,几乎每个API我都有请求响应类.

例如:

@RequestMapping(value = "/notice", method = RequestMethod.POST)
public AddNoticeResponse addNotice(@Valid @RequestBody AddNoticeRequest){
    Notice notice = ... // creating new notice from AddNoticeRequest
    noticeRepository.save(notice);
    AddNoticeResponse response = ... // creating new response instance from Notice
    return response;
} 
Run Code Online (Sandbox Code Playgroud)

请求和响应类看起来像:

@Data
@AllArgsConstructor
public class AddNoticeRequest{
    private String subject;
    private String message;
    private Long timeToLive;
}
Run Code Online (Sandbox Code Playgroud)
// Ommiting some annotations for brevity
public class AddNoticeResponse{
    private String subject;
    private String message;
    private Long timeToLive;
    private Date createTime;
    private String creator;
} 
Run Code Online (Sandbox Code Playgroud)

我有两个问题.

  • 创建太多的类并将它们命名为有些令我疯了.
  • 一些请求和响应具有共同的字段.

例如:有两种Notice:EmailNotification:

public class Email {
    private String subject;
    private String message;
    private String receiver;
}
Run Code Online (Sandbox Code Playgroud)

那么,我应该使用扩展公共类的内部类还是只将所有字段放入一个类中?哪个更好?

public class AddNoticeRequest {

    private String subject;
    private String message;

    class Email extends AddNoticeRequest{
        private String receiver;
    }
}
Run Code Online (Sandbox Code Playgroud)
public class AddNoticeRequest{
    private String subject;
    private String message;
    private Long timeToLive;
    private String receiver;
}
Run Code Online (Sandbox Code Playgroud)

然后,当客户端执行添加Email通知的请求时,某些字段是否为空?

cas*_*lin 13

从长远来看,使用定制的DTO进行请求和响应将为您提供更大的灵活性.实际上,没有什么能阻止你使用继承和内部类,但我会避免它.

在这里已经回答了类似的问题,强调了在REST API中使用DTO而不是持久性实体的好处.下面你会发现这种方法的一些好处:

  • DTO可以根据您的需求进行定制,并且在仅暴露持久性实体的一组属性时它们非常棒.您不需要注释,例如@XmlTransient@JsonIgnore避免某些属性的序列化.
  • 通过使用DTO,您将避免持久性实体中的注释,也就是说,持久性实体不会因​​非持久性相关注释而膨胀;
  • 您可以完全控制在创建或更新资源时接收的属性;
  • 如果您使用Swagger来记录您的REST API,您可以使用@ApiModel@ApiModelProperty注释来记录您的API模型,而不会弄乱您的持久性实体;
  • 您可以为每个API版本使用不同的DTO;
  • 映射关系时,您将拥有更大的灵活性;
  • 您的DTO可以包含HATEOAS的链接列表.这是不应该添加到持久性对象的那种东西.
  • 您可以使用映射框架(如MapStruct)将REST API DTO映射到/来自持久性对象.