MVC层次划分简述
写在前面的一段话:
首先要知道MVC和三层架构之间有什么关系:
-
MVC:【 Model(数据模型) - View(视图) - Controller(控制器) 】
-
三层架构:【 Presentation tier(展现层) - Application tier(应用层)+Date tier(数据访问层) 】
很多人都有一个误解,认为Spring MVC的M、V、C对应三层架构,其实是不对的!MVC只是三层架构中的展现层,MVC中的M是数据模型,是包含数据的对象,通常我们使用Spring MVC的时候有一个包叫Model,里面放的类就是用来和V交互的,V就是视图界面,包jsp,html,freemarker,velocity,thymeleaf等,C就是控制器了(通常用@Controller注解的类)。
而整个三层架构,其实是由Spring负责全局管理的,一般Service和Dao跟应用层和数据访问层有关。
早期分层:[ M - V - C ]:
MVC框架强制性的把各层的实现功能划分开,各自处理各自的任务,利于解耦和,极大的增强了代码的可读性、维护性。
- M(Model)数据模型——与数据库交互的数据模型,进行数据相关操作
- V(View)视图——是展示给用户的最终页面。视图负责将数据以用户友好的形式展现出来,负责收集展示数据。
- C(Controller)控制器——收到请求后,调用模型层与数据库交互获取数据,最后将数据返回给视图(用户), 负责整体的接收数据和逻辑处理,处理 HTTP 请求的任何操作所必须经过的中介。
1. Model的职责
对于Model而言,最主要就是保存事物的信息,保证事物的行为和对他可以进行操作。比如,Post类必然有一个用于保存博客文章标题的title属性,必然有一个删除的操作,这都是Model的内容。以下是关于Model的几个原则:
- 数据、行为、方法是Model的主要内容;
- 实际工作中,Model是MVC中代码量最大,逻辑最复杂的地方,因为关于应用的业务逻辑也要在这里表示;
- 注意与Controller区分开。Model是处理业务方面的逻辑,Controller只是简单的协调Model和View之间的关系。Controller 和套套一样,应该越薄越好。只要是与业务有关的,就该放在Model里面。好的设计,应该是胖Model,瘦Controller。
2. View的职责
其中,View部分比较明确,就是负责显示。一切与显示界面无关的东西,都不应该出现在view里面。因此,view中一般不会出现复杂的判断语句,不会出现复杂的运算过程。对于Java的Web应用而言,毫无疑问,html和JSP是view中的主要内容。如下是关于view的几个原则:
- 负责显示界面,以HTML为主;
- 一般没有复杂的判断语句或运算过程,可以有简单的循环语句、格式化语句。比如,博客首页的文字列表就是一种循环;
- 从不调用Model的写方法。也就是说,View只从Model中获取数据,从不改写Model,所以我们说他们是老死不相往来的。
- 一般没有任何准备数据处理的内容,如查询数据库等。这些一般是放在Controller里面,并以变量的形式传给视图。也就是说,视图里面要用到的数据,就是一个变量。
3. Controller的职责
对于Controller,主要是响应用户请求:决定使用什么视图、需要准备什么数据用来显示。
以下是有关Controller的设计原则:
- 用于处理用户请求,因此,对于request的访问代码应该放在Controller里面,比如
doGET
、doPOST
等。但仅限于获取用户请求数据,不应该对数据有任何操作或预处理,这应该放在model里面。 - 调用model类的方法,对model进行写操作。
- 调用视图渲染函数,形成对用户request的response。
- 一般不要有html代码等其他表现层的东西,这应该是属于view的内容。
当用户通过浏览器发送请求到视图层(view)时,控制层(controller)分发调用模型层(model),进行数据库查询,接下来模型层(model)再将数据库查询到的数据返回给控制层(controller),控制层(controller)再将其返回给视图层(view),view层通过web页面把数据信息显示给用户。
Yii Framework 官方文档:In a well-designed MVC application, controllers are often very thin, containing probably only a few dozen lines of code; while models are very fat, containing most of the code responsible for representing and manipulating the data.
在设计良好的MVC应用程序中,Controller通常非常薄,可能只包含几十行代码;而Model则非常胖,其中包含负责表示和操作数据的大多数代码。
目前市面上流行的实际分层方式[ S - D(M) - V - C ]:
以前,很多人认为可以直接在Controller层就调用model层来进行数据库的交互。但是这是不严谨的,耦合性太强,违背了MVC的初衷,即解耦。所以随着MVC学习的深入,慢慢地又加入到了业务层Service和数据访问层Dao:
- D(Dao)数据访问对象——与数据库建立连接,封装了对数据库的CURD操作
- S(Service)业务逻辑模型——做一些业务逻辑地处理,并给Controller返回结果
- V(View)视图——是展示给用户的最终页面。视图负责将数据以用户友好的形式展现出来,负责收集展示数据。
- C(Controller)控制器——接收用户传递过来的数据,将数据封装到实体类中,调用业务逻辑模型,进行业务逻辑的处理,根据业务逻辑模型返回的结果,进行不同的视图跳转。
当请求来了,controller就会将相应的请求分发到相应的service层,在service层中再调用dao层进行数据库交互。这里的dao层其实就是之前的model层,封装了对数据库的操作。这样一来,就把业务处理逻辑从controller中分离出来,从而实现了解耦。
一个典型的页面浏览行为在程序端的流程是这样的:
- 控制器最先被调用,并被赋予外部输入
- 控制器根据外部输入向模型请求数据
- 模型从数据库获取数据并发送数据到控制器
- 控制器处理该数据并发送封装好的数据到视图
- 视图根据接到的数据最终展示页面给用户浏览
使用Java进行MVC模式开发时,数据模型往往分为两部分,即DAO(Data Access Object,数据访问对象)和Service(业务逻辑模型)。在第2步中(控制器根据外部输入向模型请求数据),控制器向模型请求数据时,并不是直接向DAO请求数据,而是通过Service向DAO请求数据。这样做的好处是,可以将业务逻辑与数据库访问独立开,为将来系统更换数据保存介质(如目前系统使用文件系统存储数据,将来可以更换为使用数据库存储,又或者是现在使用了MySQL存储数据,将来更换为Oracle或是Mysql等)提供了很大的灵活性。另外,由工具层(util),实体类层(model/po/pojo)被其他层调用,为其提供服务。