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

Python 小游戏实战:打造视觉精美的数独小游戏

Python 小游戏实战:打造视觉精美的数独小游戏

Python 小游戏实战:打造视觉精美的数独小游戏 Python 小游戏实战:打造视觉精美的数独小游戏,数独是一款经典的逻辑推理数字游戏,通过填充数字 1-9 到 9x9 的网格中,使得每行、每列和每个 3x3 子网格都包含 1-9 的所有数字,不重复。本文将带大家使用 Python 的 Pygame 库实现一个视觉精美、交互友好的数独小游戏。 一、前言     Python作为一门简洁、易读、功能强大的编程语言,其基础语法是入门学习的核心。掌握好基础语法,能为后续的编程实践打下坚实的基础。本文将全面讲解Python3的基础语法知识,适合编程初学者系统学习。Python以其简洁优雅的语法和强大的通用性,成为当今最受欢迎的编程语言。本专栏旨在系统性地带你从零基础入门到精通Python核心。无论你是零基础小白还是希望进阶的专业开发者,都将通过清晰的讲解、丰富的实例和实战项目,逐步掌握语法基础、核心数据结构、函数与模块、面向对象编程、文件处理、主流库应用(如数据分析、Web开发、自动化)

By Ne0inhk
Python从0到100(九十五):空洞卷积(Dilated Convolution)网络架构与PAMAP2数据集实验分析

Python从0到100(九十五):空洞卷积(Dilated Convolution)网络架构与PAMAP2数据集实验分析

前言:零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、 计算机视觉、机器学习、神经网络以及人工智能相关知识,成为学业升学和工作就业的先行者! 【优惠信息】 • 新专栏订阅前500名享9.9元优惠 • 订阅量破500后价格上涨至19.9元 • 订阅本专栏可免费加入粉丝福利群,享受: - 所有问题解答 -专属福利领取 欢迎大家订阅专栏:零基础学Python:Python从0到100最新最全教程! 本文目录: * 一、空洞卷积的基础原理 * 1. 传统卷积的短板 * 2. 空洞卷积的巧妙之处 * 二、空洞卷积的架构 * 1. 输入层 * 2. 空洞卷积模块 * 2.1 空洞卷积层 * 2.2 批归一化和激活 * 3. 整体结构 * 三、代码实现详解

By Ne0inhk

用 Python 30 分钟做出自己的记事本

🌟 《零基础手把手:用 Python 30 分钟做出自己的记事本》 —— 不是照抄代码,而是理解每行代码的「灵魂」 🧩 第一步:为什么我们需要「基础窗口」?(新手必懂!) ❌ 常见错误:直接写 window.show() 但窗口不显示? ✅ 正确逻辑:程序运行流程图 启动程序 创建应用对象 创建窗口 显示窗口 进入事件循环 📝 代码详解(逐行解释): import sys # 必须!用于接收系统参数(比如文件路径)from PyQt6.QtWidgets import QApplication, QMainWindow # 从PyQt库导入两个核心组件# 1️⃣ 创建应用对象(灵魂!所有PyQt程序必须有) app = QApplication(sys.argv)# sys.argv = 系统传递的命令行参数(比如打开的文件名)

By Ne0inhk
Python从0到100(九十八):融合选择性卷积与残差结构的SKResNet架构详解

Python从0到100(九十八):融合选择性卷积与残差结构的SKResNet架构详解

前言:零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、 计算机视觉、机器学习、神经网络以及人工智能相关知识,成为学业升学和工作就业的先行者! 【优惠信息】 • 新专栏订阅前500名享9.9元优惠 • 订阅量破500后价格上涨至19.9元 • 订阅本专栏可免费加入粉丝福利群,享受: - 所有问题解答 -专属福利领取 欢迎大家订阅专栏:零基础学Python:Python从0到100最新最全教程! 本文目录: * 一、SKResNet的理论基础与创新点 * 1. 传统卷积神经网络的局限性 * 2. SKResNet的核心创新 * 3. 技术优势分析 * 二、SKResNet架构设计详解 * 1. 整体架构概览 * 2. SKBlock:选择核模块详解 * 2.1 多尺度卷积核设计 * 2.2 注意力机制实现 * 2.

By Ne0inhk