不同MVC层之间的数据流

时间:2016-10-31 07:28:50

标签: java spring-mvc model-view-controller persistence data-transfer-objects

下面我介绍从使用表单到持久层的数据流。但是对于哪些对象应该在MVC的哪一层以及如何在不同的MVC层之间传输数据有疑问。我正在使用Spring,因此下面发布的代码是Spring框架的代码。

我们开始,我有一个DTO(数据传输对象)PatientForm,它保存用户输入的表单数据。

public class Patient {

private int id;
private String name;
private String medicineOne;
private String medicineTwo;

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 getMedicineOne() {
    return medicineOne;
}
public void setMedicineOne(String medicineOne) {
    this.medicineOne = medicineOne;
}
public String getMedicineTwo() {
    return medicineTwo;
}
public void setMedicineTwo(String medicineTwo) {
    this.medicineTwo = medicineTwo;
}
}

PatientForm传递给控制器​​PatientController,不传输数据,但将表单传递给服务层PatientService

@PostMapping("/patient/addpatient")
public ModelAndView addPatient(@ModelAttribute("patientform") PatientForm patient){
    patientService.addPatient(patient);
    return new ModelAndView("redirect:/");
}

在服务层PatientService中,实际将数据从DTO转移到Pesistent Entity Patient

public void addPatient(com.hp.view.form.PatientForm patientForm){
    String medicineOneName = patientForm.getMedicineOne();
    Medicine medicineOne = medicineService.findByName(medicineOneName);
    if(medicineOne == null){
        medicineService.save(new Medicine(medicineOneName));
        medicineOne = medicineService.findByName(medicineOneName);
    }

    String medicineTwoName = patientForm.getMedicineTwo();
    Medicine medicineTwo = medicineService.findByName(medicineTwoName);
    if(medicineTwo == null){
        medicineService.save(new Medicine(medicineTwoName));
        medicineTwo = medicineService.findByName(medicineTwoName);
    }

    List<Medicine> medicines = new ArrayList<>();
    medicines.add(medicineOne);
    medicines.add(medicineTwo);

    Patient patient = new Patient();
    patient.setName(patientForm.getName());
    patient.setMedicine(medicines);
    patientRepository.save(patient);
}

根据以上流程,我的问题如下:

  1. Controller layerService layer是否应该将数据从DTO传输到持久实体?

  2. 如果在控制器中完成数据传输,则模型实体将在控制器层中声明。如果数据传输在服务层完成,则意味着DTO将在服务层中声明。哪两个更喜欢?

  3. 在我的服务层中,我实例化了我的实体对象Patient的实例。这会产生问题,我应该让Spring contianer管理我的实体bean吗?

  4.   Patient patient = new Patient();
    

3 个答案:

答案 0 :(得分:2)

  

(1)Controller层或服务层是否应该将数据从DTO传输到   持久性实体?

FormBeans是特定于客户端/通道/端点的,因此Controller层应该执行客户端特定的验证(如最小长度,最大长度等),然后将FormBean的数据转换为实体Bean,然后将其传递给服务层。 在3层体系结构中,服务层应该是可重用的(如下所述),它不应该知道FormBeans,因此接收实体对象并且应该负责处理业务逻辑(执行业务验证和核心逻辑以及与DAO / Repository类交互) )。

  

(2)如果在控制器中完成数据传输,则模型实体将是   在控制器层声明。如果数据传输是在服务中完成的   层表示DTO将在服务层中声明。两者中哪一个是   首选?

可以重用/公开单个服务以连接多个端点(如Controller或不同的Web服务),并且每个端点可能需要不同的formbeans,因此Controller(端点)层首选处理端点特定验证,然后创建/传递正确的实体对象到服务。

  

(3)在我的服务层中,我实例化了我的实体的实例   对象病人。这会产生问题,我应该让Spring   容器管理我的实体bean?

没问题。由于实体对象不是单例,您可以像在服务中一样在服务中创建它们。但是如果您允许Spring管理它们,则需要确保为每个输入请求创建一个实例。这是因为Spring bean的default scopesingleton,需要更改为request范围。

答案 1 :(得分:1)

实际上,我会选择完全不同的方法。 DTO可能会受到特定Web应用程序框架的约束。这会降低服务的可重用性。相反,您可以创建类似&#34; DTO的实体转换器&#34;。一个简单的界面,看起来像这样:

public interface DtoToEntityConverter<T, R> {
    R getEntity(T t);
}

然后你可以定义具体的类(甚至在更简单的情况下使用lambdas):

@Component
public class PatientFormConverter implements DtoToEntityConverter<PatientForm, Patient> {

    public Patient getEntity(PatientForm form) {
        // Conversion rules and stuff...
    }
}

然后,只需将该组件注入控制器并在添加患者时调用getEntity

addPatient(patientFormConverter.getEntity(patientForm));

答案 2 :(得分:0)

在春天,你让应用程序上下文来管理你的bean(即你没有初始化你的类),然后你可以自动装配(包括在其他类中)而无需显式初始化它们。

1)服务层用作控制器和模型之间的中介。也就是说,您将服务自动装入您的休息控制器。

2和第3个答案在上面解释。

P.S。:此处autowire表示dependency injection - 。http://www.javatpoint.com/dependency-injection-in-spring