应用分层
目前我们程序的代码有点"杂乱",然而当前只是"一点点功能"的开发。如果把整个项目功能完成呢?代码会更加的"杂乱无章"(文件乱,代码内容乱)。
也基于此,我们接下来学习应用分层。
(1) 介绍
阿里开发手册中,关于工程结构部分,定义了常见的应用分层结构:
那么什么是应用分层呢?
应用分层是一种软件开发思想,它将应用程序分成N个层次,这N个层次分别负责各自的职责,多个层次之间协同提供完整的功能。根据项目的复杂程度,把项目分成三层、四层或者更多层。
常见的 MVC 设计模式,就是应用分层的一种具体体现。
为什么需要应用分层?
在最开始的时候,为了让项目快速上线,我们通常是不考虑分层的,但是随着业务越来越复杂,大量的代码混在一起会出现逻辑不清楚、各模块相互依赖、代码扩展性差、一改动就牵一发动全身等问题。
如何分层
目前更流行的开发方式是"前后端分离"的方式,后端开发工程师不再需要关注前端的实现,所以对于Java后端开发者,又有了一种新的分层架构:把整体架构分为表现层、业务逻辑层和数据层。这种分层方式也称之为"三层架构"。
1.表现层:就是展示数据结果和接受用户指令的,最靠近用户的一层
2.业务逻辑层:负责处理业务逻辑,里面有复杂业务的具体实现
3.数据层:负责存储和管理与应用程序相关的数据
按照上面的层次划分,Spring MVC站在后端开发人员的角度上,也进行了支持,把上面的代码划分成为三个部分:
- 请求处理、响应数据:负责接收页面的请求,给页面响应数据
- 逻辑处理:负责业务逻辑处理的代码
- 数据访问:负责业务数据的维护操作,包括增删改查等操作
这三个部分在Spring的实现中,均有体现:
- Controller:控制层.接受前端发送的请求,对请求进行处理,并响应数据
- Service:业务逻辑层.处理具体的业务逻辑
- Dao:数据访问层,也称为持久层.负责数据访问操作,包括数据的增删改查
MVC和三层架构的区别和联系
从概念上来看,二者都是软件工程领域中的架构模式
三层架构将业务应用划分为:表现层,业务逻辑层,数据访问层
二者其实是从不同角度对软件工程进行了抽象.
MVC模式强调数据和视图分离,将数据展示和数据处理分开,通过控制器对两者进行合并
三层架构强调不同维度数据处理的高内聚和低耦合,将交互界面,业务处理和数据库操作的逻辑分开
二者的目的都是相同的,都是"解耦,分层,代码f复用"
软件设计原则"高内聚低耦合"
高内聚指的是:一个模块中各个元素之间的联系的紧密程度,如果各个元素(语句,程序段)之间的联系程度越高,则内聚性越高.
低耦合指的是:软件中各个层,模块之间的依赖关联程度越低越好.修改一处代码,其他模块的代码改动越少越好.
企业规范
- 类名使用大驼峰风格,但以下情形例外:DO/BO/DTO/AO/VO
- 方法名,参数名,成员变量,局部变量统一使用小驼峰风格
- 包名统一使用小写,点分隔符之间有且仅有一个自然语义的单词
图书管理系统
需求:
1.登录:用户输入账号,密码完成登录功能
2.列表展示:展示图书
接口定义:
1.登录接口
@RestController @RequestMapping("/user") public class UserName { @RequestMapping("/login") public Boolean login(String name,String password){ if(!StringUtils.hasLength(name)||!StringUtils.hasLength(password)){ return false; } if("admin".equals(name)&&"admin".equals(password)){ return true; } return false; } }2.列表展示接口
package com.imu.springbook; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Random; @RestController @RequestMapping("/book") public class BookController { @RequestMapping("/getList") public List<BookInfo> getList(){ List<BookInfo> list=new ArrayList<>(); for (BookInfo bookInfo:list){ if(bookInfo.getStatus()==1){ bookInfo.setStatusCN("可借阅"); }else{ bookInfo.setStatusCN("不可借阅"); } } return list; } public List<BookInfo> mockBook(){ List<BookInfo> bookInfos=new ArrayList<>(); for (int i = 0; i < 8; i++) { BookInfo bookInfo=new BookInfo(); bookInfo.setAuthor("作者"+i); bookInfo.setId(i); bookInfo.setCount(i*5+1); bookInfo.setPrice(new BigDecimal(new Random().nextInt(100))); bookInfo.setPublish("中国人民出版社"); bookInfo.setStatus(i%5==0?2:1); } return bookInfos; } }