当前位置: 首页 > news >正文

MVC与三层架构分层

1. 应用分层

        应用分层类似公司的组织架构。我们进行项目开发时,最开始功能简单,前后端放在一起开发,但随着项目功能的复杂,项目会被前端和后端不同的团队接手,甚至更细粒度的团队。甚至后端开发也会根据功能再进行细分。MVC就是其中的一种拆分方式。

        随着后端人员不再涉及前端,后端开发又有了新的分层方式。

1.1 介绍

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

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

  1.1.1 为什么需要应用分层

        在最开始的时候,为了让项目快速上线,通常是不考虑分层的。但是随着业务越来越复杂,大量的代码混在一起,会出现逻辑不清楚、代码扩展性插、改一处导致处处改等问题。

1.1.2 如何分层?(三层架构)

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

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

1、表现层:就是展示数据结果和接受用户指令的,是最靠近用户的一层。

2、业务逻辑层:负责处理业务逻辑,里面有复杂业务的具体实现。

3、数据层:负责存储和管理应用程序相关的数据。

       可以看到, 咱们前⾯的代码, 并不符合这种设计思想, ⽽是所有的代码堆砌在⼀起,如下图所示:
 

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

1、请求处理:响应数据:负责接受页面的请求,给页面响应数据。

2、逻辑处理:负责业务逻辑处理的代码。

3、数据访问:负责业务数据的维护操作,包括增、删、改、查。

        这三个部分,在Spring的实现中,都有体现,如下图所示:

 1、Controller:控制器。接收前端发送的请求,对请求进行处理,并且响应数据。

2、Service:业务逻辑层。处理具体的业务逻辑。

3、Dao:数据访问层,也称为持久层。负责数据访问操作,包括数据的增、删、改、查。

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

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

        1、MVC架构模式由三部分组成:View(视图)、Controller(控制器)、Model(模型)

        2、三层架构将业务应用划分为:表现层、业务逻辑层、数据访问层

        MVC中的视图和控制器对应三层架构中的表现层。MVC中的模型对应三层架构中的业务逻辑层、数据层、实体类;二者架构图如下所示:

         由上图可知,二者都是从不同角度对软件工程进行了抽象。

        MVC模式强调数据和视图分离,将数据展示和数据处理分开。控制器是它们之间的桥梁,通过控制器对两者进行组合。

        三层架构强调不同维度数据处理的高内聚和低耦合,将交互界面、业务处理、数据库操作的逻辑分开。

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

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

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

1.3.1 高内聚

        一个模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间的联系程度越高,则内聚性越高,即 “高内聚”。

  1.3.2 低耦合

        软件中各个层、模块之间的依赖关联程序越低越好。修改一处代码,其他模块的代码改动越少越好。

        那么高内聚和低耦合矛盾吗?其实不矛盾,高内聚是指一个模块中的各个元素之间的紧密程度,低耦合是指各个模块之间的精密程度。如图:

          好比在大明1566朝堂里,清流和严党之间的关联性要尽可能小,严党出问题了,清流党要尽可能减少两党之间的关系,反之被牵连,这就是低耦合;而当严党自己内部出了问题时,整个党派之间的所有成员要紧密的团结在一起,一起解决、克服已经出现的问题,这就是高内聚。

2、代码重构

        上篇写了图书管理系统,但是代码非常乱,现在进行代码重构,先创建对应包的路径,如图:

2.1 表现层

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

package com.example.zxslzw2014_8_11.controller;import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpSession;@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/login")public String login(String userName, String password, HttpSession session) {//1、校验参数//2、校验密码是否正确//3、返回响应结果System.out.println(userName + " " + password);if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {return "用户名或者密码为空";}if(!"smy".equals(userName) || !"111".equals(password)) {return "账号或密码错误";}session.setAttribute("userName", userName);return "登录成功";}
}
package com.example.zxslzw2014_8_11.controller;import com.example.zxslzw2014_8_11.model.BookInfo;
import com.example.zxslzw2014_8_11.service.BookService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/book")
public class BookController {@RequestMapping("/getBookList")public List<BookInfo> getBookList() {BookService bookService = new BookService();return bookService.getBookList();}
}

 2.2 service业务逻辑层

package com.example.zxslzw2014_8_11.service;import com.example.zxslzw2014_8_11.dao.BookDao;
import com.example.zxslzw2014_8_11.model.BookInfo;import java.util.List;public class BookService {public List<BookInfo> getBookList() {BookDao bookDao = new BookDao();List<BookInfo> bookInfos = bookDao.mockData();for(BookInfo bookInfo : bookInfos) {if(bookInfo.getStatus() == 2) {bookInfo.setStatusCN("不可借阅");} else {bookInfo.setStatusCN("可借阅");}}return bookInfos;}
}

 2.3 dao:数据访问层

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

package com.example.zxslzw2014_8_11.dao;import com.example.zxslzw2014_8_11.model.BookInfo;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;public class BookDao {public List<BookInfo> mockData() {//理论上应该从数据库中获取数据,当前采用mock方式List<BookInfo> bookInfos = new ArrayList<>();for (int i = 1; i <= 15; i++) {BookInfo bookInfo = new BookInfo();bookInfo.setId(i);bookInfo.setBookName("图书" + i);bookInfo.setAuthor("作者" + i);bookInfo.setNum(i * 2 + 1);bookInfo.setPrice(new BigDecimal(i * 3));bookInfo.setPublishName("出版社" + i);if(i % 5 == 0) {bookInfo.setStatus(2);
//                bookInfo.setStatusCN("不可借阅");} else {bookInfo.setStatus(1);
//                bookInfo.setStatusCN("可借阅");}bookInfos.add(bookInfo);}return bookInfos;}
}

2.4 model:实体类

package com.example.zxslzw2014_8_11.model;import lombok.Data;import java.math.BigDecimal;@Data
public class BookInfo {private Integer id;private String bookName;private String author;private Integer num;private BigDecimal price;private String publishName;private Integer status;//1-可借阅   2-不可借阅private String statusCN;//状态的中文含义
}

2.5  应用分层的好处

(1)降低层与层之间的依赖,结构更加的明确,利于各层逻辑的复用。

(2)开发人员可以只关注整个结构中的其中某一层,极大地降低了维护成本和维护时间。

(3)可以很容易的用新的实现来替换原有层次的实现。

(4)有利于标准化。

3.企业规范

1、类名使用大驼峰风格,但以下情形例外:DO / BO / DTO / VO / AO。

2、方法名、参数名、成员变量、局部变量统一使用小驼峰风格。

3、包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。

        常见命名风格:

大驼峰:所有单词首字母都需要大写,又叫帕斯卡命名发,比如:UserController

小驼峰:除了第一个单词,其他单词首字母大写,比如:userController。

蛇形:用下划线(_)作用单词间的分隔符,一般小写,又叫下划线命名法,比如user_controller。

串形:用短横线(-)作用单词间的分隔符,又叫脊柱命名法,例如:user-controller。

4. 学习Spring MVC的总结

1、学习Spring MVC,其实就是学习各种Web开发需要用到的注解:

a、@RequestMapping:路由映射

b、@RequestParam:后端参数重命名

c、@RequestBody:接收JSON类型的参数

d、@PathVariable:接收路径参数

e、@RequestPart:上传文件

f、@ResponseBody:返回数据

g、@CookieValue:从Cookie中获取值

h、@SessionAttribute:从Session中获取值

i、@RequestHeader:从Header中获取值

j、@Controller:定义一个控制器,Spring框架启动时加载,把这个对象交给Spring管理。默认返回视图。

k、@RestController:@ResponseBody + @Controller 返回数据

2、Cookie和Session都是会话机制,Cookie是客户端机制,Session是服务端机制。二者通过SessionId来关联。Spring MVC 内置 HttpServletRequest,HttpServletResponse两个对象。需要使用时,直接在方法中添加对应参数即可,Cookie和Session可以从HttpServletRequest中来获取,也可以直接使用HttpServletResponse设置Http响应状态码。

ps:本次的内容就到这里了,如果对你有所帮助的话,就请一键三连哦!!!

本文的封面来自:bilibili苏杉杉的pv,侵权删 url:https://www.bilibili.com/video/BV1vo4y167eh/?spm_id_from=333.999.0.0&vd_source=866da5be2ef0ddd213b053523da53138
————————————————

电子签名:上嘉路

 

相关文章:

  • 用Golang实现图形面积计算
  • HiveSQL实战——大厂面试真题
  • 【JPCS出版】第三届机械、航天技术与材料应用国际学术会议 (MATMA 2024)
  • Go 语言协程管理精解
  • 解决 Go 语言并发问题
  • 我问GPT flutter
  • 2024年10月湖北省自学考试报名流程(5步)
  • LLM概念梳理(一):训练流程之PT、SFT和PO
  • OriginPro快速上手指南:数据可视化与分析的利器
  • Android笔试面试题AI答之Kotlin(18)
  • 本科生毕业答辩全攻略:从开题到终期答辩的全面指南
  • 中国第一起名大师的老师颜廷利: 名字中的姓氏家谱字辈的最新解析
  • Vitis AI 进阶认知(Torch量化基础+映射+量化参数+对称性+每通道+PTQ+QAT+敏感性)
  • PHP进阶篇(奇怪的知识又增加了)
  • 局部整体(三)利用python绘制饼图
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • 5、React组件事件详解
  • classpath对获取配置文件的影响
  • JavaScript DOM 10 - 滚动
  • javascript 哈希表
  • js中forEach回调同异步问题
  • Kibana配置logstash,报表一体化
  • v-if和v-for连用出现的问题
  • 高度不固定时垂直居中
  • 高性能JavaScript阅读简记(三)
  • 排序(1):冒泡排序
  • 人脸识别最新开发经验demo
  • 深入浏览器事件循环的本质
  • 首页查询功能的一次实现过程
  • 微服务框架lagom
  • 小而合理的前端理论:rscss和rsjs
  • 优化 Vue 项目编译文件大小
  • ​520就是要宠粉,你的心头书我买单
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​决定德拉瓦州地区版图的关键历史事件
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (1)(1.13) SiK无线电高级配置(五)
  • (第9篇)大数据的的超级应用——数据挖掘-推荐系统
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (每日一问)设计模式:设计模式的原则与分类——如何提升代码质量?
  • (篇九)MySQL常用内置函数
  • (七)Knockout 创建自定义绑定
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (一)项目实践-利用Appdesigner制作目标跟踪仿真软件
  • .gitignore文件设置了忽略但不生效
  • .net core 6 redis操作类
  • .NET Core WebAPI中封装Swagger配置
  • .Net Core 微服务之Consul(二)-集群搭建
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .NET 设计模式—适配器模式(Adapter Pattern)
  • .net6Api后台+uniapp导出Excel
  • .NET导入Excel数据
  • :=