目录
[DAO 层](#DAO 层)
[Service 层](#Service 层)
[Controller 层](#Controller 层)
案例回顾与问题分析
案例情况
- 在上次的案例中,实现了加载并解析 XML 文件数据,处理数据后返回统一响应结果并在页面展示。但所有代码都写在 controller 方法中。
问题指出
- 若开发复杂功能,controller 方法中存在大量数据操作和逻辑处理代码,会导致代码复用性和拓展性差 ,项目难以维护。
三层架构介绍
产生原因
- 基于单一职责原则,为使接口类和方法复杂度低、可读性强、拓展性好且利于维护,在 Web 开发中有了三层架构。
架构层次
- 表示层(控制层,Controller层)
- 即 controller 程序,主要负责接收前端发起的请求,对请求进行处理并响应数据。
- 业务逻辑层(Service 层)
- 主要负责逻辑的处理。
- 数据访问层(DAO 层,也叫持久层)
- 主要负责数据访问操作,包括数据的增删改查。
请求流程
前端发起请求后,先到达 Controller,Controller 接收到请求后调用 Service 进行逻辑处理。Service 处理逻辑前需获取数据,所以会调用 DAO 层,DAO 层操作文件(或其他数据源)中的数据并将数据返回给 Service。Service 拿到数据后进行逻辑处理,再将结果返回给 Controller,Controller 最后响应数据给前端。
案例代码按照三层架构优化
DAO 层
- 先定义 DAO 接口
EmpDao
,其中定义listEmp
方法用于获取员工列表数据,返回值为集合类型。
- 在
DAO
包下创建实现类impl.EmpDaoA
,实现EmpDao
接口,在实现方法中加载并解析 XML 文件获取数据并返回。
java
public class EmpDaoA implements EmpDao {
@Override
public List<Emp> listEmp() {
//加载emp.xml,并解析emp.xml中的数据
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
System.out.println(file);
List<Emp> empList = XmlParserUtils.parse(file,Emp.class);
return empList;
}
}
Service 层
- 创建
EmpService
接口,定义listEmp
方法用于获取处理后的员工列表数据,返回值为集合类型。
- 创建实现类
impl.EmpServicea
,实现EmpService
接口。在实现方法中创建EmpDao
对象(采用面向接口编程,实例化为EmpDaoa
),调用EmpDao
的listEmp
方法获取原始数据,对数据进行转换处理后返回。
java
public class EmpServiceA implements EmpService {
private EmpDao empDao = new EmpDaoA();
@Override
public List<Emp> listEmp() {
//1.调用dao层,获取数据
List<Emp> empList = empDao.listEmp();
//2.对数据进行转换处理 - gender,job
empList.stream().forEach(emp -> {
//处理 gender 1 : 男, 2 : 女
String gender = emp.getGender();
if("1".equals(gender)){
emp.setGender("男");
}else if("2".equals(gender)){
emp.setGender("女");
}
//处理job - 1 : 讲师, 2 : 班主任 , 3 : 就业指导
String job = emp.getJob();
if("1".equals(job)){
emp.setJob("讲师");
}else if("2".equals(job)){
emp.setJob("班主任");
}else if("3".equals(job)){
emp.setJob("就业指导");
}
});
//3.返回处理结果
return empList;
}
}
Controller 层
- 备份原 Controller 方法中不需要的代码(数据访问和逻辑处理部分)并注释掉。在 Controller 中定义
EmpService
类型的对象,实例化为EmpServicea
。调用EmpService
的listEmp
方法获取处理后的数据并响应回去。
java
@RestController
public class EmpController {
private EmpService empService = new EmpServiceA();
@RequestMapping("/listEmp")
public Result list(){
//1.调用service,获取数据
List<Emp> empList = empService.listEmp();
//2.组装数据并返回
return Result.success(empList);
// //1.加载并解析emp.xml
// String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
// System.out.println(file);
// List<Emp> empList = XmlParserUtils.parse(file,Emp.class);
// //2.对数据进行转换处理 - gender,job
// empList.stream().forEach(emp -> {
// //处理 gender 1 : 男, 2 : 女
// String gender = emp.getGender();
// if("1".equals(gender)){
// emp.setGender("男");
// }else if("2".equals(gender)){
// emp.setGender("女");
// }
//
// //处理job - 1 : 讲师, 2 : 班主任 , 3 : 就业指导
// String job = emp.getJob();
// if("1".equals(job)){
// emp.setJob("讲师");
// }else if("2".equals(job)){
// emp.setJob("班主任");
// }else if("3".equals(job)){
// emp.setJob("就业指导");
// }
// });
}
}
总结
拆分前后对比
- 拆分前所有代码写在一起,导致代码复用性差,应用程序难以维护和管理。
- 拆分后将接收请求、响应数据、业务逻辑处理以及数据访问操作分开,更利于程序复用,每一层职责更加单一,方便程序的维护和扩展。
重要性强调
- 三层架构是 Web 开发的标准架构,刚开始从传统写法转到三层架构写法可能不熟悉不习惯,但多练习后会逐渐掌握。
END
学习自:黑马程序员------JavaWeb课程