MVC MVC是Model-View-Controller的简称,原本是建立Smalltalk 应用的框架。框架支持代表应用状态、屏幕表现和控制流的3个类,他们分别叫做Model、View和Controller。
在Model发生变化的时候,通知View改变;在View需要查询状态的时候,向Model发送请求,当View做出一个动作时,比如对数据的修改等,通知Controller;Controller得到状态改变信息时,发送请求给Model,并且Controller负责选择显示新的View。
下图是典型的Model-View-Controller范式,经常被表示为:一个互相连接的三角形。
图1 MVC 通常表示为3个互相连接的组件 在Design Patterns: Elements of Reusable Object-Oriented Software一书中,作者以smalltalk MVC为例,赞扬了通知/订阅者(notify/subscribe)协议和观察者(Observer)模式的使用。其中局的一个经典的例子是对同一数据,系统可能需要不同的显示视图,比如条形图、饼图、数据表格等等,如下图:
图2不同的View使用相同的Model 图2所示的每种视图可能在同一时间显示给不同的用户。应用必须保证在其下面的数据或者模型改变时视图的更新。为改变模型,用户提交一个请求给控制器,由控制起来配合改变模型。数据视图必须跟着改变,以反映最近的模型改变状态。
Smalltalk MVC 方案使用观察者通知模式。在这种模式下,每个视图注册为一个模型数据的观察者。然后模型可以通过发送消息给所有这册观察者,通知它们相关的改变。其为 Smalltalk MVC 框架已经通用化了,他也可以应用它其他平台上面。
Model2 Model2是Sun公司为了解决JSP不易维护和功能块难以复用提出的。Sun的技术人员,提出使用JSP 和 SERVLET同时来部署web 应用,SERVLET可以应付控制流,而 JSP则可专注于讨厌的编写HTML的任务。
结合使用 JSP 和 SERVLET 开始被称为Model 2 ,而单独使用JSP称为Model 1。
Model2并不是什么新的东西,其思想上实际是对MVC的一种继承。很多场合,交互使用Model 2 和 MVC这两个词。但是还是存在一些争论,即一个应用是否是 MVC,以及是否支持经典的观察者通知模式。没有观察者通知的Model-View-Controller 有时被称为MVC2 或Web MVC。
层模式的MVC结构 人们认为Model2不同于MVC的主要原因之一是:基于观察者/通知模式的经典的MVC是难以在web环境下实现的。
因为HTTP协议是一个请求/响应协议,客户端有请求,服务器端才会有响应,没有请求,就没有响应。而观察者/通知模式要求在服务器端发生变化时能主动给用户端发消息更新。
为了解决经典MVC模式难于在web环境下实现的问题,引入层模式将状态改变和状态查询的职责加于控制器之上,并伴随着改变通知。
如图3,分层的web 应用使用一种比传统MVC模式更加“扁平”的模式。控制器被夹在表现层(View) 和 应用逻辑 (Model)之间。
图3 web应用的层模式 每个组件的主要职责并没有改变。流程有轻微改变,View不再与Model有直接的联系,而它们之间的交互都通过Controller。即查询状态和改变通知都必须通过控制器;当视图,或者表现层需要加工动态页面时,它使用从控制器传递的数据而不是直接来自于模型层。这种改变去除了View 和 Model的耦合,允许控制器选择数据和显示这些数据的视图。
Struts概要介绍 Struts实现层模式的MVC Struts是一个应用框架,它实现了层次化的MVC模式或者说Sun公司提出的Model2模式。
在Model1模式的web编程中,Model部分可以交给EJB及JDBC实现,而View部分可以由Jsp完成,但是却没有合适的工具完成独立的Contrroller。在Model2的思想提出由Servlet应付控制流,在Struts中Servlet就扮演了Front End Controller的角色。
当客户端提出请求,ActionServlet响应请求,并且在指定的Struts-Config.xml文件中查到请求对应的Action(Action是Struts引入的一个核心类,作为Back End Controller,在后文会介绍),对已经实例化的Action,ActionServlet为这个新的请求开一个线程,对未实例化的Action,ActionServlet将其实例化。
Action作为Back End Controller可以与Model部分交互,以实现状态改变或者状态查询,Action还将返回下一步的视图选择给ActionServlet。ActionServlet根据对应的Struts-Config.xml找到视图选择对应物理地址,并把新的View返回给用户端。
图4 Struts实现层模式的MVC结构 另一种常见的关于Srtuts实现MVC模式的看法是认为只有ActionServlet是Controller,而把Action看作BusinessLogic。我认为,这种看法是没有前一种将Action视为Back End Controller的看法合理的,因为Controller部分需要完成的视图选择实际上是由Action实现的。
之所以会有后一种不太合适的关于Struts实现MVC结构的看法存在,主要是起源于编程习惯问题,很多人喜欢把大量的业务逻辑交给Action处理,我认为这是不太合适的。一方面,这样降低了代码的可复用性;另一方面使Action看起来臃肿,降低了可读性。所以,推荐的编程方式是把大量的业务逻辑抽出做成JavaBean,以解放Action。