JavaWeb——分层解耦(1/5):三层架构(架构层次、请求流程,DAO 层、Service 层、Controller 层,总结)

目录

案例回顾与问题分析

三层架构介绍

产生原因

架构层次

请求流程

案例代码按照三层架构优化

[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课程

相关推荐
SimonKing36 分钟前
Workbuddy太占C盘空间了,写个迁移工具迁走10G的数据
java·后端·程序员
Hvitur1 小时前
Java - Lambda
java·开发语言·python
xiaoye-duck1 小时前
《C++ 项目:手写大模型接入 SDK》DataManager数据管理模块:SQLite持久化存储
开发语言·数据库·c++·sqlite
Evand J1 小时前
【MATLAB例程,PMSM19】永磁同步电机(PMSM)基于多速率无迹卡尔曼滤波(UKF)的转速与转子位置估计。测量缺失、状态预测与恢复性能分析
开发语言·matlab·电机·ekf·卡尔曼·电机滤波
喵了几个咪1 小时前
GoWind Flow 拆解:一个 Go 工作流引擎与它的双模式设计器
开发语言·人工智能·后端·golang
꧁细听勿语情꧂2 小时前
二叉树余题,排序、直接插入排序、希尔排序
c语言·开发语言·数据结构·算法
是main不是漫2 小时前
【C++——类和对象(上)】筑基篇:以封装奠定面向对象之基
c语言·开发语言·c++
apcipot_rain6 小时前
C++转Java日记(06)
java·开发语言
金銀銅鐵11 小时前
带您看懂字节码指令(一):一帧里有什么
java·后端·ai编程
nice_lcj52012 小时前
【从零理解 Spring AI · 14】RAG 的四个环节:加载、切分、向量化、检索
java·spring boot·embedding·向量数据库·rag·spring ai·ai应用开发