在控制器方法中接受请求主体

时间:2019-09-07 08:07:42

标签: spring-boot java-8

在我的控制器中,我有一个使用以下映射映射的方法: @PostMapping(“/")。

此方法需要一个我试图捕获的请求主体,如下所述:

公共字符串创建(@RequestBody任务任务)

任务是我创建的一个自定义类,它映射到请求中期望的请求主体的结构。

我刚接触弹簧靴,不确定最佳实践标准如何。

我的疑问是在我的方法create()中,我应该直接在我的实体类中捕获请求主体还是应该有一个类似的pojo来捕获请求主体,然后将其映射到我的实体类?

关于最佳做法和标准约定的任何建议都将有所帮助。

同时使用这两种方法对我来说都很好,如果直接在实体类中接受请求主体是一个好主意和最佳实践,那我就陷入了困境。

我不想在控制器类中公开我的实体类,因为我不确定这是否是一个好主意。

@PostMapping("/")
public String create(@Valid @RequestBody Task task) {


}

Task.java

public final class Task {

@NonNull
private int id;

@NotBlank(message = "Name is a mandatory field")
private String name;

private String decription;

@NotBlank(message = "date is a mandatory field")
private String date;

private boolean status;

@NotBlank(message = "severenes is a mandatory field")
private String severenes;

public Task(int id, String name, String decription, String date, boolean status, String severenes) {
    super();
    this.id = id;
    this.name = name;
    this.decription = decription;
    this.date = date;
    this.status = status;
    this.severenes = severenes;
}

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;
}

public String getDecription() {
    return decription;
}

public void setDecription(String decription) {
    this.decription = decription;
}

public String getDate() {
    return date;
}

public void setDate(String date) {
    this.date = date;
}

public boolean isStatus() {
    return status;
}

public void setStatus(boolean status) {
    this.status = status;
}

public String getSeverenes() {
    return severenes;
}

public void setSeverenes(String severenes) {
    this.severenes = severenes;
}   

}

Tasks.java(实体CLass)

@Entity
@Table(name = "tasks")
public class Tasks {

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "id")
private int id;

@Column(name = "name")
private String name;

@Column(name = "description")
private String description;

@Column(name = "date")
private LocalDateTime date;

@Column(name = "status")
private boolean status;

@Column(name = "severenes")
private String severenes;


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;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public LocalDateTime getDate() {
    return date;
}

public void setDate(LocalDateTime date) {
    this.date = date;
}

public boolean isStatus() {
    return status;
}

public void setStatus(boolean status) {
    this.status = status;
}

public String getSeverenes() {
    return severenes;
}

public void setSeverenes(String severenes) {
    this.severenes = severenes;
}

}

上述两种方法都能得出相同的结果,而对最佳实践的关注更多。

2 个答案:

答案 0 :(得分:1)

它与软件设计原理有关。在此示例中,这与关注点分离有关。假设您直接将单个Tasks实体用于数据库操作和REST操作,而不是将Task(一种DTO)和Tasks(Entity)分开。

为数据库和REST操作使用任务实体:

  • 您有一个在页面上显示任务的UI。
  • 您正在将任务存储在数据库中。
  • 需求现已更改。您不再将任务状态存储在数据库中,而是需要从第三方端点动态获取它。
  • 您需要从“任务实体”字段中删除状态字段,但仍需要将其返回到UI。由于您在两个图层上都使用了相同的实体,因此无法轻松,清晰地删除它,应该怎么做,以及将来很难维护的一些解决方法?
  • 您需要做更多的工作来提供此功能,一项需求变更会影响应有的更多层。

使用用于REST的任务,用于数据库操作的任务实体

  • 您有一个在页面上显示任务的UI。
  • 您正在将任务存储在数据库中。
  • 需求现已更改。您不再将任务状态存储在数据库中,而是需要从第三方端点动态获取它。
  • 您需要从“任务实体”字段中删除状态字段,并且可以。
  • 您从第三方检索了状态字段。
  • 您通过汇总第三方和任务实体的状态来创建任务对象
  • 您只更改了一层,而不是全部都更改了。 UI甚至没有意识到需求已更改,即使您的逻辑层也不关心它。单一责任原则使您不必担心更改。

是的,似乎存在一些缺陷,例如您需要更多的类来表示单个对象,但这是分离的。它使可维护的项目,易于重构/更改代码并最小化更改的影响。

答案 1 :(得分:0)

您应该创建类CreateTaskRequest,并且该类应该是控制器的参数。通过端点公开您的域是个坏主意。您可以看看here是如何在我的一个项目中完成的。