摘 要:本文以图书管理系统为案例(当前主流框架SpringMVC的原理来分析MVC的设计理念等),深入浅出地分析常用的WEB设计模式MVC。将从MVC的历史、MVC每一层的作用,MVC能为我们带来什么好处又存在哪些问题以及MVC的前景如何等方面结合实际项目对该架构进行分析。通过本文你将从多个层面对MVC架构设计有一个初步的认识,让你快速走近MVC设计思想,通过实际项目的剖析以及图文交互的表达方式让您轻松理解MVC架构。
关键词:MVC;SpringMVC;分层;视图;控制器;模型
0 引言
Web应用的根本都是从数据存储和检索数据并将其显示给用户。在用户更改数据之后,系统再将更新内容存储到数据存储中。因为关键的信息流发生在数据存储和用户界面之间,所以很多Web应用将数据和用户界面这两部分绑在一起,以减少编码量并提高应用程序性能。但是,这种看起来自然而然的方法有一些大问题。一是,用户界面的更改往往比数据存储系统的更改频繁得多。二是,这种情况下耦合往往会合并其他的业务逻辑。那么如何让 Web 应用程序的用户界面功能实现模块化,以便可以轻松地单独修改各个部分呢?面向对象的设计模式是Web设计经验的总结,MVC架构可以很好地解决上述问题。
1 MVC简介
MVC架构把数据处理,程序输入输出控制及数据显示分离开来,并且描述了不同部件的对象间的通信方式。使得软件可维护性,可扩展性,灵活性以及封装性大大提高;MVC(Model-View-Controller)把系统的组成分解为M(模型)、V(视图)、C(控制器)三种部件。视图表示数据在屏幕上的显示。控制器提供处理过程控制,它在模型和视图之间起连接作用。控制器本身不输出任何信息和做任何处理,它只负责把用户的请求转成针对Model的操作,和调用相应的视图来显示Model处理后的数据。三者之间关系如下图1 (MVC关系图)
图1 MVC关系图
2 为什么要使用MVC
用户界面逻辑的更改往往比业务逻辑频繁,尤其是在基于Web的应用程序中。例如,可能添加新的用户界面页,或者可能完全打乱现有的页面布局。对显示的更改,尽可能地不要影响到数据和业务逻辑。
目前大部分Web应用都是将数据代码和表示混在一起。经验比较丰富的开发者会将数据从表示层分离开来,但这通常不是很容易做到的,它需要精心的计划和不断的尝试。MVC从根本上强制性的将它们分开。尽管构造MVC应用需要一些额外的工作,但它带来的好处是毋庸置疑的。
2.1 提高代码重用率
最重要的一点就是多个视图可以共享同一个模型,把视图表达和底层数据分离。不论用户想要什么视图,只需要修改视图的模式,而数据可以根据接口自由传递,避免了同时修改视图和数据部分代码的困难,提高了代码的可重用性。
2.2 提高程序可维护性
因为模型是自包含的,并且与控制器和视图相分离,所以很容易改变数据层和业务规则。例如,把数据库从MySQL移植到Oracle,或者把基于RDBMS数据源改变到LDAP,只需改变模型即可。一旦正确的实现了模型,不管数据来自哪里,视图都会正确的显示它们。MVC架构的运用,使得程序的三个部件相互对立,大大提高了程序的可维护性。
2.3 有利于团队开发
在开发过程中,可以更好的分工,更好的协作。有利于开发出高质量的软件。良好的项目架构设计,将减少编码工作量 :采用MVC结构 + 代码生成器,是大多数Web应用的理想选择。部分模型(Model)、和存储过程一般可用工具自动生成。控制(Controller)器比较稳定,一般由于架构师(也可能是有经验的人)完成;那么整个项目需要手动编写代码的地方就只有视图(View)了。在这种模式下,个人能力不在特别重要,只要懂点语法基础的人都可以编写,无论项目成员写出什么样的代码,都在项目管理者的可控范围内。即使项目中途换人,也不会有太大问题。在个人能力参差不齐的团队开发中,采用MVC开发是非常理想的。
3 基于SpringMVC的案例分析
系统采用了SpringBoot框架,而SpringBoot是对SpringMVC的扩展,本质上依然是MVC架构模式,下面将以此为例带你了解MVC的原理和实现过程。
3.1 MVC的工作流程
SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架属于SpringFrameWork的后续产品,已经融合在 Spring Web Flow 中。
MVC的工作流程: 用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器。
3.2 SpringMVC实现原理
先看一张原理图(图2 SpringMVC原理图)首先用户发起请求,请求被DispatcherServlet拦截,拦截之后去寻找请求对应的映射器。DispatcherServlet是核心,一切的一切都是从拦截请求开始的,当请求被拦截时,SpringMVC会根据请求,去处理请求映射关系,从而找到该请求对应的控制器,把处理器的名字返回到DispatcherServlet,而后再由DispatcherServlet找到该控制器,控制器完成的工作主要是封装数据,返回用户需要的视图,视图返回后,由DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。(获得model and view 中的数据,解析视图名字,拼接视图路径)视图解析器将解析的逻辑视图名传给DispatcherServlet。DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
图2 SpringMVC原理图
3.3 MVC项目目录结构
在基于SpringMVC的图书管理系统中,该框架在文件目录上把MVC清晰地分为了三层目录结构,分别对应了数据模型层(完成控制层和数据库的交互,完全不用干涉视图层),控制层(通过控制器决定了视图层的用户需要得到什么数据,成为视图层和数据模型层的桥梁),视图层(专注于如何把控制层传来的数据更好的展示给用户),目录结构如下图3。
图3 SpringMVC目录结构图
3.4 MVC核心
SpringMVC乃至整个MVC架构的核心在控制层,控制层起到了承上启下,交互的作用。控制层决定了什么样的数据要传给什么样的视图,下面介绍一下SpringMVC是如何实现控制层的。
为了方便管理,控制层被进一步分解出服务层(Service)这一层主要负责数据的获取,Controller层只需要去调用Servie层获取数据,而不需要既关注数据又关注视图。结构如图4所示:
图4 SpringMVC Controller层结构图
4 MVC的优点和不足
4.1 MVC的优点
MVC的优点体现在以下几个方面:
(1) 有利于团队开发分工协作和质量控制,降低开发成本。
(2) 可以为一个模型在运行时同时建立和使用多个视图。变化-传播机制可以确保所有相关的视图及时得到模型数据变化,从而使所有关联的视图和控制器做到行为同步。
(3) 视图与控制器的可接插性,允许更换视图和控制器对象,而且可以根据需求动态的打开或关闭、甚至在运行期间进行对象替换。
(4) 模型的可移植性。因为模型是独立于视图的,所以可以把一个模型独立地移植到新的平台工作。需要做的只是在新平台上对视图和控制器进行新的修改。
(5) 潜在的框架结构。可以基于此模型建立应用程序框架,不仅仅是用在设计界面的设计中。
4.2 MVC的不足
MVC的不足体现在以下几个方面:
(1)增加了系统结构和实现的复杂性。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
(2)视图对模型数据的访问效率低。视图可能需要多次调用Model才能获得足够的显示数据。
(3)完全理解MVC并不是很容易。使用MVC需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。 同时由于模型和视图要严格的分离,这样也给调试应用程序到来了一定的困难。