下面我介绍从使用表单到持久层的数据流。但是对于哪些对象应该在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);
}
根据以上流程,我的问题如下:
Controller layer
或Service layer
是否应该将数据从DTO传输到持久实体?
如果在控制器中完成数据传输,则模型实体将在控制器层中声明。如果数据传输在服务层完成,则意味着DTO将在服务层中声明。哪两个更喜欢?
在我的服务层中,我实例化了我的实体对象Patient
的实例。这会产生问题,我应该让Spring contianer管理我的实体bean吗?
Patient patient = new Patient();
答案 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
scope
是singleton
,需要更改为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