4. MVC 开发(模型-视图-控制器)
Web应用程序通常采用三层架构:

- [dao]层负责数据访问,通常是存储在SGBD中的持久化数据。但也可能是来自传感器、网络等的数据。
- [metier]层实现应用程序的“业务”算法。该层与任何形式的用户界面均相互独立。 因此,它必须能够同时适用于控制台界面、Web 界面以及富客户端界面。这意味着该层必须能够在脱离 Web 界面的情况下进行测试,特别是通过控制台界面进行测试。这通常是架构中最稳定的层。无论用户界面如何变更,或获取应用程序运行所需数据的方式如何改变,该层均保持不变。
- [interface utilisateur]层,即用户界面(通常为图形界面),用于让用户控制应用程序并接收相关信息。
通信方向从左向右:
- 用户向 [interface utilisateur] 层发起请求
- 该请求由 [interface utilisateur] 层进行格式化,并传输至 [métier] 层
- 若处理该请求时,[métier]层需要数据,则向[dao]层请求
- 每个被查询的层将响应返回给左侧的层,直至最终响应到达用户。
[métier] 和 [dao] 层通常通过 Java 接口进行调用。因此,[métier] 层仅了解 [dao] 层的接口,而不知道实现这些接口的具体类。 正是这一点确保了各层之间的独立性:只要不更改 [dao] 层的接口定义,修改 [dao] 层的实现就不会对 [métier] 层产生任何影响。 [interface utilisateur]层与[métier]层之间也是如此。
当 [interface utilisateur] 层作为 Web 接口时,MVC 架构(模型-视图-控制器)便位于该层中:

客户端请求的处理流程如下:
- 客户端向控制器发送请求。控制器处理所有客户端请求,它是应用程序的入口点,即 MVC 中的 C。
- 控制器 C 处理该请求。为此,它可能需要业务层的协助。一旦处理完客户端的请求,它可能会返回各种响应。一个典型的例子是:
- 如果请求无法正确处理,则返回错误页面
- 否则返回确认页面
- 控制器选择要发送给客户端的响应(即视图)。选择要发送给客户端的响应需要经过多个步骤:
- 选择将生成响应的对象。这被称为视图 V,即 MVC 中的 V。该选择通常取决于用户请求的操作执行结果。
- 向其提供生成该响应所需的数据。实际上,该响应通常包含由控制器计算得出的信息。这些信息构成了所谓的视图模型 M,即 MVC 中的 M。
- 因此,步骤3包括选择一个视图V,并构建该视图所需的模型M。
- 控制器 C 请求显示所选视图。这通常是指调用视图 V 的某个特定方法,该方法负责生成发给客户端的响应。在本文档中,我们将生成客户端响应的对象以及响应本身统称为“视图”。 文献 MVC 对此点未作明确说明。如果应将响应称为视图,那么生成该响应的对象便可称为视图生成器。
- 视图生成器 V 使用控制器 C 准备的模型 M 来初始化其需发送给客户端的响应中的动态部分。
- 响应被发送给客户端。其确切形式取决于视图生成器。可以是 HTML 流、PDF、Excel 等。
MVC Web开发方法论并不一定需要外部工具。 因此,仅需一个简单的 JDK 以及基本的 Web 开发库,即可开发出采用 MVC 架构的 Java Web 应用程序。适用于简单应用程序的一种方法如下:
- 控制器由一个单一的Servlet承担。这就是MVC中的“C”。
- 所有客户端请求都包含一个 action 属性,例如 (http://.../appli?action=liste)。
- 根据 action 属性的值,Servlet 会调用一个 [doAction(...)] 类型的内部方法。
- 方法 [doAction] 执行用户请求的操作。为此,如有需要,它会使用 [métier] 层。
- 根据执行结果,方法 [doAction] 决定要显示的页面 JSP。这是模型 MVC 的视图 V。
- 页面 JSP 包含需由 Servlet 提供的动态元素。方法 [doAction] 将提供这些元素。这是视图的模型,即 MVC 中的 M。 该模板通常放置在请求上下文中(request.setAttribute("键", "值")),较少见的情况下也会放置在会话或应用程序上下文中。JSP页面可以访问这三个上下文。
- [doAction]方法通过将执行流传递给选定的JSP页面来显示视图。为此,它使用类似[getServletContext() .getRequestDispatcher(" pageJSP ").forward(request, response)]的语句。
这种设计模式(Design Pattern)MVC被称为“前端控制器”(Front Controller)模式,或单控制器模式。一个单一的Servlet处理所有用户的请求。
让我们回到前面的Web应用程序架构:

该架构对应于以下 ntier 架构:

实际上只有一层,即 Web 界面层。一般而言,基于 Servlet 和 JSP 页面的 Web 应用程序 将具有以下架构:

对于简单的应用程序,这种架构已经足够。当我们编写了多款此类应用程序后,会发现两个不同应用程序的Servlet:
- 采用相同的机制来确定应执行哪个方法 [doAction] 来处理用户请求的操作
- 实际上仅在这些方法 [doAction] 的内容上有所不同
此时,人们往往会产生强烈的冲动:
- 将处理逻辑 (1) 提取到一个通用 Servlet 中,该 Servlet 不了解调用它的应用程序
- 将处理逻辑 (2) 委托给外部类,因为通用 Servlet 无法识别其被使用的具体应用程序
- 通过配置文件将用户请求的操作与负责处理该操作的类建立关联
一些通常被称为“框架”的工具应运而生,旨在为开发人员提供上述便利。其中历史最悠久且可能最广为人知的便是 Struts(http://struts.apache.org/)。 Jakarta Struts 是 Apache 软件基金会(www.apache.org)的一个项目。该框架的介绍详见 (http://tahe.developpez.com/java/struts/)。
较新出现的 Spring 框架(http://www.springframework.org/)提供了与 Struts 类似的功能。其使用方法已在多篇文章中有所介绍(http://tahe.developpez.com/java/springmvc-part1/)。
下面我们将介绍一个基于Servlet和JSP页面的MVC架构示例。