web007-三层架构

1.课程复现

解决图片无法加载问题:

直接将图片放进 source 的 image 文件夹里,重新设置图片路径。

2.理解三层架构

严格的 Controller → Service → DAO 三层

每层都有 接口 + 两套实现(A 和 B),用来对比"手动 new"和"Spring IOC 依赖注入"的区别

一、三层架构是什么

三层架构把应用分成三个职责清晰的层:

职责 fifth 中的体现
Controller(表现层) 接收 HTTP 请求、参数校验、调用 Service、返回响应 EmpController
Service(业务逻辑层) 处理业务规则(如 gender 1→男, job 1→讲师) EmpServiceA / EmpServiceB
DAO(数据访问层) 只负责数据的存取(读 XML、查数据库) EmpDaoA / EmpDaoB

为什么要分三层?

对比 fourth 的痛点:

如果想把 XML 数据源换成 MySQL 数据库,fourth 需要改动整个 Controller

如果你想把 gender 的转换规则从 "1→男" 改成 "1→男性",也要在 Controller 里翻找

fifth 的分层好处:

DAO 层只负责取数据,换数据源时只改 DAO 实现

Service 层只负责业务规则,规则变了只改 Service

Controller 层只负责接收/响应请求,不关心数据怎么来的、业务怎么处理的

这就是单一职责原则:每个类只干一件事。

二、耦合是什么

耦合 = 类与类之间的依赖紧密度。

fifth 中 A 系列的强耦合:

java 复制代码
// EmpController.java
public class EmpController {
    public Result list() {
        EmpServiceA empServiceA = new EmpServiceA();  // 硬编码依赖 EmpServiceA
        List<Emp> list = empServiceA.listEmp();
        return Result.success(list);
    }
}

// EmpServiceA.java
public class EmpServiceA implements EmpService {
    private EmpDaoA empDaoA = new EmpDaoA();  // 硬编码依赖 EmpDaoA
    // ...
}

问题:如果你想换一个 DAO 实现(比如 EmpDaoB),你必须修改 EmpServiceA 的源代码。这就是强耦合------牵一发而动全身。

三、IOC(控制反转)和 DI(依赖注入)

问题的本质

传统方式(A 系列):类自己控制依赖的创建

IOC 方式(B 系列):控制权反转给 Spring 容器

IOC = 控制反转

控制权从"程序员手动 new"反转给了"Spring 容器"。

DI = 依赖注入

DI 是 IOC 的具体实现方式。Spring 容器在运行时会自动把依赖对象注入到需要它的地方。

java 复制代码
// EmpBController.java --- B 系列
@RestController
public class EmpBController {
    @Autowired
    private EmpService empService;  // 只声明接口,不关心具体实现
    // Spring 会自动注入 EmpServiceB 实例
}

// EmpServiceB.java
@Component
public class EmpServiceB implements EmpService {
    @Autowired
    private EmpDao empDao;  // 只声明接口,Spring 自动注入 EmpDaoB
}

// EmpDaoB.java
@Component
public class EmpDaoB implements EmpDao {
    // Spring 管理的 Bean
}

关键注解说明

注解 作用 位置
@Component 告诉 Spring:"请把这个类创建为 Bean,放入容器管理" DAO、Service 实现类
@Autowired 告诉 Spring:"请把容器里匹配的 Bean 注入到这个字段" Controller、Service

Spring 容器启动时:

  1. 扫描到 @Component → 创建 EmpDaoB 实例 → 放入容器
  2. 扫描到 @Component → 创建 EmpServiceB 实例
    → 发现 @Autowired EmpDao → 从容器中取出 EmpDaoB → 注入
  3. 扫描到 @RestController → 创建 EmpBController 实例
    → 发现 @Autowired EmpService → 从容器中取出 EmpServiceB → 注入

请求 /listEmp1 时:

前端 → EmpBController.empService (已是注入好的 EmpServiceB)

→ EmpServiceB.empDao (已是注入好的 EmpDaoB)

→ 读取 XML → 返回数据

四、为什么要这么做?

  1. 解耦 --- 代码更容易修改
    想换 DAO 实现?只需要写一个新的 @Component EmpDaoC,不改任何现有代码,Spring 自动切换。

3.通过三层架构重新设计信管资料库网站

结构目录

前端

后端

前后端首页和部分界面未特别区别,只是后端增加了用户管理等功能,目前还在研究将自己的文件录入该系统。

还在优化中,本网站由Tencent 云ai,copilot,文心快码等ai协作。