Spring Boot 后端分层开发实战:从 MVC 到三层架构详解

Spring Boot 后端分层开发实战:从 MVC 到三层架构详解

应用分层

通过上面的练习,我们学习了 Spring MVC 简单功能的开发,但是我们也发现了一些问题。目前我们程序的代码有点 “杂乱”,然而当前只是 “一点点功能” 的开发。如果我们把整个项目功能完成呢?代码会更加的 “杂乱无章”(文件乱,代码内容乱)。

也基于此,咱们接下来学习应用分层。类似公司的组织架构:公司初创阶段,一个人身兼数职,既做财务,又做人事,还有行政。随着公司的逐渐壮大,会把岗位进行细分,划分为财务部门,人事部门,行政部门等。各个部门内部还会再进行细分。

项目开发也是类似,最开始功能简单时,我们前后端放在一起开发,随着项目功能的复杂,我们分为前端和后端不同的团队,甚至更细粒度的团队。后端开发也会根据功能再进行细分。MVC 就是其中的一种拆分方式。但是随着后端人员不再涉及前端,后端开发又有了新的分层方式。

4.1 介绍

阿里开发手册中,关于工程结构部分,定义了常见工程的应用分层结构:

那么什么是应用分层呢?应用分层是一种软件开发设计思想,它将应用程序分成 N 个层次,这 N 个层次分别负责各自的职责,多个层次之间协同提供完整的功能。根据项目的复杂度,把项目分成三层,四层或者更多层。常见的 MVC 设计模式,就是应用分层的一种具体体现。

为什么需要应用分层?在最开始的时候,为了让项目快速上线,我们通常是不考虑分层的。但是随着业务越来越复杂,大量的代码混在一起,会出现逻辑不清晰、各模块相互依赖、代码扩展性差、改动一处就牵一发而动全身等问题。所以学习对项目进行分层就是我们程序员的必修课了。

如何分层(三层架构)

咱们上一节中学习的 “MVC”,就是把整体的系统分成了 Model(模型),View(视图)和 Controller(控制器)三个层次,也就是将用户视图和业务处理隔离开,并且通过控制器连接起来,很好地实现了表现和逻辑的解耦,是一种标准的软件分层架构。

目前现在更主流的开发方式是 “前后端分离” 的方式,后端开发工程师不再需要关注前端的实现,所以对于 Java 后端开发者,又有了一种新的分层架构:把整体架构分为表现层、业务逻辑层和数据层。这种分层方式也称之为 “三层架构”。

  1. 表现层:就是展示数据结果和接受用户指令的,是最靠近用户的一层;
  2. 业务逻辑层:负责处理业务逻辑,里面有复杂业务的具体实现;
  3. 数据层:负责存储和管理与应用程序相关的数据。

可以看到,咱们前面的代码,并不符合这种设计思想,而是所有的代码堆砌在一起。

这三个部分,在Spring的实现中,均有体现:

按照上面的层次划分,Spring MVC 站在后端开发人员的角度上,也进行了支持,把上面的代码划分为三个部分:

  • 请求处理、响应数据:负责,接收页面的请求,给页面响应数据。
  • 逻辑处理:负责业务逻辑处理的代码。
  • 数据访问:负责业务数据的维护操作,包括增、删、改、查等操作。

这三个部分,在 Spring 的实现中,均有体现:

  • Controller:控制层。接收前端发送的请求,对请求进行处理,并响应数据。
  • Service:业务逻辑层。处理具体的业务逻辑。
  • Dao:数据访问层,也称为持久层。负责数据访问操作,包括数据的增、删、改、查。

MVC 和三层架构的区别和联系

关于二者的关系,一直存在不同的观点。有人认为三层架构是 MVC 模式的一种实现,也有人认为 MVC 是三层架构的替代方案,等等各种说法都有。根本原因是大家站在不同的角度来看待这个问题的。

JavaEE 部分的学习重在 “实践”,大家根据自己的理解,能够自圆其说,说出自己的观点即可,也不建议大家去背书。

从概念上来讲,二者都是软件工程领域中的架构模式。

  • MVC 架构模式由三部分组成,分别是:模型 (Model),视图 (View) 和控制器 (Controller)。
  • 三层架构将业务应用划分为:表现层,业务逻辑层,数据访问层。

MVC 中,视图和控制器合起来对应三层架构中的表现层。模型对应三层架构中的业务逻辑层、数据层,以及实体类。

二者其实是从不同角度对软件工程进行了抽象。

  • MVC 模式强调数据和视图分离,将数据展示和数据处理分开,通过控制器对两者进行组合。
  • 三层架构强调不同维度数据处理的高内聚和低耦合,将交互界面、业务处理和数据库操作的逻辑分开。

角度不同也就谈不上互相替代了,在日常的开发中可以经常看到两种共存的情况,比如我们设计模型层的时候往往也会拆分出业务逻辑层(Service 层)和数据访问层(Dao 层)。

但是二者的目的是相同的,都是 “解耦,分层,代码复用”。

软件设计原则:高内聚低耦合

  • 高内聚:指的是一个模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间的联系程度越高,则内聚性越高,即 “高内聚”。
  • 低耦合:指的是软件中各个层、模块之间的依赖关联程序越低越好。修改一处代码,其他模块的代码改动越少越好。

高内聚低耦合矛盾吗?不矛盾,高内聚指的是一个模块中各个元素之间的联系的紧密程度,低耦合指的是各个模块之间的紧密程度。

这就好比一个企业,包含很多部门,各个部门之间的关联关系要尽可能的小,一个部门发生问题,要尽可能对降低对其他部门的影响,就是耦合。但是部门内部员工关系要尽量紧密,遇到问题一起解决,克服。这叫做内聚。

比如邻里邻居,楼上漏水,楼下遭殃,就是耦合。家庭一个成员生病,其他成员帮忙照顾,就叫内聚。一个家庭内部的关系越紧密越好,一个家庭尽可能少的影响另一个家庭,就是低耦合。

4.2 代码重构

我们使用上面的分层思想,来对代码进行改造

  1. 先创建对应的包路径,并把代码移到对应的目录
    • com.example.demo.controller
    • com.example.demo.service
    • com.example.demo.dao
    • com.example.demo.model

1. 代码拆分

控制层(Controller)

接收前端发送的请求,对请求进行处理,并响应数据。

package com.example.demo.controller; import com.example.demo.model.BookInfo; import com.example.demo.service.BookService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RequestMapping("/book") @RestController public class BookController { @RequestMapping("/getList") public List<BookInfo> getList() { BookService bookService = new BookService(); // 获取数据 List<BookInfo> books = bookService.getBookList(); return books; } } 
业务逻辑层(Service)

处理具体的业务逻辑。

import com.example.demo.dao.BookDao; import com.example.demo.model.BookInfo; import java.util.List; public class BookService { public List<BookInfo> getBookList() { BookDao bookDao = new BookDao(); List<BookInfo> books = bookDao.mockData(); for (BookInfo book : books) { if (book.getStatus() == 1) { book.setStatusCN("可借阅"); } else { book.setStatusCN("不可借阅"); } } return books; } } 
数据访问层(Dao)

负责数据访问操作,包括数据的增、删、改、查。

import com.example.demo.model.BookInfo; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Random; public class BookDao { /** * 数据Mock 获取图书信息 * @return */ public List<BookInfo> mockData() { List<BookInfo> books = new ArrayList<>(); for (int i = 0; i < 5; i++) { BookInfo book = new BookInfo(); book.setId(i); book.setBookName("书籍"+i); book.setAuthor("作者"+i); book.setCount(i*5+3); book.setPrice(new BigDecimal(new Random().nextInt(100))); book.setPublish("出版社"+i); book.setStatus(1); books.add(book); } return books; } } 

4.3 应用分层的好处

  • 降低层与层之间的依赖,结构更加明确,利于各层逻辑的复用
  • 开发人员可以只关注整个结构中的其中某一层,极大地降低了维护成本和维护时间
  • 可以很容易的用新的实现来替换原有层次的实现
  • 有利于标准化

4.4  企业规范

课件中出现的企业规范,适用于多数企业,均不做强制要求。具体以所在企业为准。
  1. 类名使用大驼峰风格,但以下情形例外:DO/BO/DTO/VO/AO
  2. 方法名、参数名、成员变量、局部变量统一使用小驼峰风格
  3. 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。
常见命名风格介绍
  • 大驼峰:所有单词首字母都需要大写,又叫帕斯卡命名法,比如: UserController
  • 小驼峰:除了第一个单词,其他单词首字母大写,比如: userController
  • 蛇形:用下划线 (_) 作用单词间的分隔符,一般小写,又叫下划线命名法,比如: user_controller
  • 串形:用短横线 (-) 作用单词间的分隔符,又叫脊柱命名法,比如: user-controller

4.5 总结

  1. 学习 Spring MVC,其实就是学习各种 Web 开发需要用到的注解:
    • @RequestMapping:路由映射
    • @RequestParam:后端参数重命名
    • @RequestBody:接收 JSON 类型的参数
    • @PathVariable:接收路径参数
    • @RequestPart:上传文件
    • @ResponseBody:返回数据
    • @CookieValue:从 Cookie 中获取值
    • @SessionAttribute:从 Session 中获取值
    • @RequestHeader:从 Header 中获取值
    • @Controller:定义一个控制器,Spring 框架启动时加载,把这个对象交给 Spring 管理。默认返回视图。
    • @RestController@ResponseBody + @Controller,返回数据
  2. Cookie 和 Session 都是会话机制,Cookie 是客户端机制,Session 是服务端机制。二者通过 SessionId 来关联。Spring MVC 内置HttpServletRequestHttpServletResponse两个对象。需要使用时,直接在方法中添加对应参数即可,Cookie 和 Session 可以从HttpServletRequest中来获取,也可以直接使用HttpServletResponse设置 Http 响应状态码。
  3. Java EE 学习阶段会涉及较多工具、插件的学习,来帮助我们提高开发效率。比如 Postman、lombok、EditStarter,后面还会继续学习其他的工具或插件。

注意事项:

Spring , SpringBoot , SpringMVC 之间的关系以及区别?

名称定位核心作用
Spring Framework基础框架提供 IoC(控制反转)、DI(依赖注入)、AOP(面向切面编程)等核心能力,是整个 Spring 生态的基石。
Spring MVCWeb 框架基于 Spring 的 Web 层解决方案,专注于处理 HTTP 请求、路由、视图渲染等 Web 开发任务。
Spring Boot快速开发框架基于 Spring 和 Spring MVC,通过 “约定大于配置” 的思想,简化配置、内置服务器、自动装配,让开发者快速搭建可独立运行的应用。

二、它们之间的联系

  1. Spring 是基础Spring MVC 和 Spring Boot 都构建在 Spring Framework 之上,依赖它的核心功能(如 IoC 容器)。
  2. Spring MVC 是 Spring 的 Web 模块早期开发 Web 应用时,需要手动配置大量 XML,整合 Spring 和 Spring MVC,步骤繁琐。
  3. Spring Boot 是对 Spring 和 Spring MVC 的封装与简化
    • 它自动配置了 Spring MVC 的常用组件(如 DispatcherServlet、视图解析器)。
    • 内置了 Tomcat 等 Web 服务器,无需单独部署。
    • 通过 starter 依赖,一键引入 Spring MVC 等模块,大幅减少配置和依赖管理的工作量。

三、它们之间的区别

维度Spring FrameworkSpring MVCSpring Boot
核心目标提供企业级 Java 开发的通用解决方案专注于 Web 层开发简化 Spring 应用的开发和部署
配置方式大量 XML 或 JavaConfig 配置依赖 Spring 的配置,需额外配置 Web 相关组件自动配置(Auto-Configuration),极少手动配置
部署方式需要部署到外部 Web 服务器需要部署到外部 Web 服务器内置服务器,可直接运行 JAR 包
依赖管理手动管理依赖,易出现版本冲突手动管理依赖通过 starter 自动管理依赖和版本
使用场景所有需要 IoC、AOP 等能力的 Java 应用传统的 Spring Web 应用开发快速开发微服务、独立应用、RESTful API

四、一句话总结

  • Spring 是 “地基”,提供了最核心的编程模型和能力。
  • Spring MVC 是 “房子的框架”,专门用来盖 Web 应用这栋楼。
  • Spring Boot 是 “精装修套餐”,把地基和框架都准备好了,你只需要拎包入住,快速开发。

Read more

Flutter 三方库 diff_match_patch 鸿蒙文本比对拼接算法双向核心适配研判:毫秒解构海量字符差异区块建立丝滑无感知的协同编辑冲突强容错合并-适配鸿蒙 HarmonyOS ohos

Flutter 三方库 diff_match_patch 鸿蒙文本比对拼接算法双向核心适配研判:毫秒解构海量字符差异区块建立丝滑无感知的协同编辑冲突强容错合并-适配鸿蒙 HarmonyOS ohos

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 diff_match_patch 鸿蒙文本比对拼接算法双向核心适配研判:毫秒解构海量字符差异区块建立丝滑无感知的协同编辑冲突强容错合并机制 在文本编辑器、版本控制系统或协同办公应用中,快速、精准地找出两段文字之间的差异并生成补丁(Patch)是核心能力。diff_match_patch 库基于 Google 开发的高效算法,提供了业界领先的文本处理解决方案。本文将详解该库在 OpenHarmony 环境下的适配与实战。 前言 随着鸿蒙分布式能力的不断增强,多终端设备(手机、平板、电脑)之间的文档同步与协作编辑变得愈发频繁。直接传输整段文本不仅浪费带宽,且难以处理冲突。diff_match_patch 通过计算文本的最小增量,能够大幅提升鸿蒙分布式数据通信的效率。 一、原理解析 1.1 基础概念 diff_match_patch

By Ne0inhk

Flutter 三方库 vertex_ai 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、全能的 Google Vertex AI (Gemini/PaLM) 智能交互与向量搜索增强引擎

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 vertex_ai 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、全能的 Google Vertex AI (Gemini/PaLM) 智能交互与向量搜索增强引擎 在鸿蒙(OpenHarmony)系统开发 AI 辅助、智慧化物流、智能客服或复杂的向量语义搜索(Matching Engine)应用时,如何通过一套 Dart 代码,即可连接到全球领先的 Google Vertex AI 服务器?vertex_ai 为开发者提供了一套工业级的、基于云端 API 的智能交互封装方案。本文将深入实战其在鸿蒙 AI 应用中的核中核应用。 前言 什么是 Vertex

By Ne0inhk

【免费下载】 WSL2 Linux 内核更新包(适用于 x64 计算机)

WSL2 Linux 内核更新包(适用于 x64 计算机) 【下载地址】WSL2Linux内核更新包适用于x64计算机本仓库提供了一个适用于 x64 计算机的 WSL2 Linux 内核更新包。该更新包旨在帮助用户在 Windows Subsystem for Linux 2 (WSL2) 中获得最新的 Linux 内核版本,以提升系统性能和兼容性 项目地址: https://gitcode.com/open-source-toolkit/68d9c 简介 本仓库提供了一个适用于 x64 计算机的 WSL2 Linux 内核更新包。该更新包旨在帮助用户在 Windows Subsystem for Linux 2 (WSL2) 中获得最新的 Linux 内核版本,以提升系统性能和兼容性。 资源文件说明 * 文件名:

By Ne0inhk
Flutter for OpenHarmony:mockito 单元测试的替身演员,轻松模拟复杂依赖(测试驱动开发必备) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:mockito 单元测试的替身演员,轻松模拟复杂依赖(测试驱动开发必备) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 在软件开发中,单元测试(Unit Testing)是保证代码质量的基石。然而,在测试某个具体的业务逻辑(如 UserService)时,我们往往会遇到各种外部依赖,比如数据库查询、网络请求、设备传感器等。 如果直接调用真实的 Database 或 HttpClient,不仅测试速度慢,而且容易因为网络抖动或环境问题导致测试失败。此外,我们很难复现一些极端场景(如 500 服务器错误、数据库连接超时)。 Mockito 就是为了解决这个问题而生的。它允许我们创建对象的 Mock(替身),并精确控制这些替身的行为(Stubbing)和验证它们的交互(Verification)。 在 OpenHarmony 应用开发中,使用 mockito 可以让我们在开发机(Host)上就能快速验证大部分业务逻辑,通过后再部署到鸿蒙真机进行集成测试,

By Ne0inhk