Front Controller(前端控制器)

Front Controller(前端控制器)

发布日期: 4/1/2004 | 更新日期: 4/1/2004

Front Controller(前端控制器)

版本: 1.0.1

本页内容
上下文上下文
问题问题
影响因素影响因素
解决方案解决方案
示例示例
结果上下文结果上下文
测试考虑事项测试考虑事项
相关模式相关模式
致谢致谢

上下文

您已经决定使用Model-View-Controller(MVC) 模式将动态 Web 应用程序的用户界面逻辑与业务逻辑分隔开来。您已经考察了Page Controller 模式,但您的页面控制器类具有复杂的逻辑,并且是较深的继承层次结构的一部分,或者,您的应用程序是基于可配置的规则来动态确定页面导航的。

问题

如何为非常复杂的 Web 应用程序构建最佳的控制器结构,以便在避免代码重复的同时实现重用性和灵活性?

影响因素

下面是适用于 Front Controller 模式的、由 Model-View-Controller 带来的各种具体的影响因素:

如果在系统的不同视图内复制公共逻辑,则需要集中此逻辑才能减少代码重复量。删除重复的代码是改进系统的总体可维护性的关键。

数据检索最好也集中在一个位置进行处理。一个好的示例是,让一系列视图使用数据库中的相同数据。与让每个视图检索数据并重复数据库访问代码相比,在一个位置实现对此数据的检索是更好的做法。

MVC 中所述,测试用户界面代码往往是耗时而乏味的。通过区分单各自的角色,可以提高总体可测试性。这不仅适用于模型代码(在 MVC 中已说明),而且适用于控制器代码。

以下影响因素可能使您决定使用 Front Controller,而不是 Page Controller

Page Controller 的一般实现方法涉及为各个页面所共享的行为创建一个基类。但是,随着时间的推移,由于要增加非所有页面公用的代码,这些基类就会不断增大。若需要定期重构此基类以确保其只包括公共行为,则需要制定规则。例如,您不希望由页面检查请求并决定(基于请求参数)是否将控制权转移给另一个页面,因为这种类型的决定对于特定功能来说更具体,而不是所有页面共有的。

为了避免在基类中添加过多的条件逻辑,您会创建更深的继承层次结构以删除条件逻辑。例如,在具有三个功能区域的应用程序中,只使用一个包含应用程序公共功能的基类可能是很有用的。每个功能区域可能还有另一个类,该类继承总体应用程序的基类。乍一看,这种类型的结构是简单的,但它通常会导致非常脆弱的设计和实现,并给代码带来问题。

Page Controller 解决方案描述了每个逻辑页面使用一个对象。当需要跨多个页面对处理过程进行控制或协调时,此解决方案将不可行。例如,假定在 Web 应用程序中具有复杂的可配置导航(以 XML 格式存储)。当收到请求时,应用程序必须根据其当前状态查找下一步要前进到哪个位置。

由于Page Controller 是通过每个逻辑页面使用一个对象来实现的,因此,很难在 Web 应用程序的所有页面中一致地应用特定操作。例如,安全性最好以协调方式实现。让每个视图或页面控制器对象分别处理安全性是有问题的,因为它可以被不一致地应用,并导致安全问题。此问题的其他解决方案还将在Intercepting Filter中进行讨论。

对于 Web 应用程序来说,URL 与特定控制器对象的关联可以是强制性的。例如,假定您的站点具有类似向导的界面用于收集信息。此向导包括许多必备页面和许多基于用户输入的可选页面。在使用 Page Controller 实现时,必须使用基类中的条件逻辑来实现可选页面,才能选择下一页面。

解决方案

Front Controller 通过让单个控制器负责传输所有请求,从而解决了在 Page Controller 中存在的分散化问题。控制器本身通常分为以下两部分实现:处理程序和命令层次结构(见图 1)。


图 1:Front Controller 结构

处理程序具有以下两项职责:

检索参数。处理程序接收来自 Web 服务器的 HTTP Post 或 Get 请求,并从请求中检索相关参数。

选择命令。处理程序首先使用请求中的参数选择正确的命令,然后将控制权转移给该命令以便执行处理。

图 2 显示这两项职责。


图 2:Front Controller 的典型方案

命令本身也是控制器的一部分。命令代表具体的操作,这在 Command 模式 [Gamma95] 中有相应的介绍。通过将命令表示为单独的对象,控制器可以按一般方式与所有命令交互,这与调用公共命令类上的特定方法相反。在命令对象完成操作之后,将由命令选择使用哪个视图来显示页面。

结果上下文

Front Controller 模式具有下列优缺点:

优点

集中化控制。Front Controller 用于协调向 Web 应用程序发出的所有请求。此解决方案描述了使用单一控制器,而不是 Page Controller 中所用的分布式模型。此单一控制器处于很好的位置来实施全应用程序范围的策略,如安全性和使用情况跟踪。

线程安全。由于每个请求都涉及创建新的命令对象,因此命令对象本身不需要是线程安全的。这意味着,命令类中避免了线程安全问题。但是,这并不意味着您可以完全避免线程问题,因为命令所作用的代码(即模型代码)仍然必须是线程安全的 [Fowler03]。

可配置性。只需要在 Web 服务器中配置一个前端控制器;处理程序执行其余的调度。这简化了 Web 服务器的配置。一些 Web 服务器是很难配置的。使用动态命令可以添加新的命令,而无需进行任何更改 [Fowler03]。

缺点

性能考虑事项。Front Controller 是用来处理对 Web 应用程序的所有请求的单个控制器。在这两部分中,应该仔细检查处理程序中是否有性能问题,因为处理程序将确定负责执行请求的命令的类型。如果处理程序必须执行数据库查询或 XML 文档查询才能作出决定,则可能导致性能非常缓慢。

增加了复杂性。Front Controller Page Controller 更复杂。它通常涉及将内置控制器替换为自定义的 Front Controller。实现此解决方案会增加维护成本和新手的学习难度。

测试考虑事项

从视图中删除业务逻辑简化了视图的测试难度,因为此后可以在独立于控制器的情况下测试视图。如 Page Controller 模式中所述,测试控制器可能受到以下情况的阻碍:控制器包含了使其依赖于 HTTP 运行时环境的代码。通过使用两阶段的 Web 处理程序(如 Martin Fowler 所著的 Patterns for Enterprise Application Architecture [Fowler03] 和 Page Controller 模式中所述),可以解决此依赖问题。控制器被分为两部分:Web 处理程序和调度程序。Web 处理程序从 Web 请求中检索数据,并以调度程序不依赖于 Web 服务器框架的方式(例如,在一个常规集合对象中),将其传递给调度程序。这样,就可以在没有 Web 服务器框架的情况下测试调度程序。

相关模式

有关详细信息,请参阅下列相关模式:

Intercepting Filter。此模式描述了在 Web 应用程序内实现重复功能的另一种方式。Intercepting Filter 的工作原理是,先通过可配置的筛选器链传递每个请求,然后将控制权传递给控制器。筛选器往往会处理较低级别的功能(如解码、授权、验证和会话管理),而 Front Controller Page Controller 则处理应用程序级别的功能。筛选器的另一个方面是它们通常是无状态的。例如,在开始对用户授权时,Web 服务器必须验证会话。如果用户已通过身份验证,则过程继续进行。如果没有,则将用户重定向到其他位置。Intercepting Filter 的一个优点是,在大多数实现中,不必修改页面本身就能添加其他功能。

Page Controller。此模式是 Front Controller 的更简单替代方案。在 Page Controller 模式中,每个页面各有一个控制器对象,这与所有请求使用一个对象的方案相反。对于大多数应用程序来说,Page Controller 是更合适的起点。仅当需要 Front Controller 时才应该使用它。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值