月度归档:2011年10月

前端控制器

前端控制器

表现层的请求处理机制需要支持每个用户多个请求,我们可以以集中式或分散式的方式管理这些请求。

如果以分散的方式进行管理可能会导致如下的一些问题:

  • 每个请求都有一个共同的操作,分散处理可能会导致代码的重复。
  • 可能会导致视图导航和视图内容的耦合。
  • 分散处理可能会带来更高的维护成本。

如果我们采用集中的方式进行管理,则可以对安全认证、国际化等操作统一处理,同时也可以在一个集中点处理站点的某些操作(如日志记录,站点全局访问控制等),
并且可以在一个地方处理逻辑在多个视图中重复显示。如此我们有了选择前端控制器的理由。

前端控制器建议集中处理所有请求的处理,然而它并没有限制系统中请求处理器的个数,对于不同的服务,完全可以提供不同的处理器。
这与集中式的管理并不矛盾,其实集中只是一种相对的集中,从而达到解决分散式所产生的问题的目的,
任何一种模式只是为解决一些应用场景的特定问题。

运行机制
一个前端控制器其本体包括两部分:一个分发中心(或叫调度处理程序)和一个command(或动作)层次结构。
当一个请求到达服务器,前端控制器接收此请求,从其请求信息中获取足够的内容并决定下一步操作,然后委托给某个command,执行操作。

分发中心可以是一个类或几个类,它没有页面输出,它的作用就是决定最终运行哪一个command。
这里简单点,可以直接根据参数约定,动态识别并执行。
这种简单方法做到了开闭原则,可以在不修改分发中心的前提下添加新的command。

例子
前端控制器在PHP的框架中基本上都会出现,在实现方式上,前端控制器大多采用Apache的url_rewrite模块,
以在.htaccess中重写规则,将所有请求都转发到index.php文件处理。

如PHP的YII框架,Application即YII framework的前端处理器,它是整个请求过程的运行环境。
Application 接收用户的请求并把它分发到合适的控制器作进一步处理。
其一个访问到动作被执行,简单过程如下:

  • 用户访问 Web 服务器,假设其访问地址为index.php?r=post/show,则其入口脚本 index.php 会处理该请求。
  • index.php建立一个应用实例并运行(run方法,在运行前有若干组件加载,初始化操作)。
  • 在应用从一个叫 HTTPRequest 的应用组件获取此次请求的详情。
  • 在urlManager 的组件的帮助下,根据前面获取的请求详情确定用户要请求的控制器和动作,分别对应CController和CInlineAction。
  • 应用建立一个被请求的控制器实例来进一步处理用户请求,控制器确定由它的actionShow 方法来处理 show 动作。
  • 然后它创建并运行和该动作相关的过滤器(CController->runActionWithFilters( )),如果过滤器允许的话,动作被执行,即CController->runAction() ==> CInlineAction->run()。

对于前端控制器,Java体系中的Struts框架以XML配置方式体现,在strut.xml配置动作,在web.xml中配置过滤器。

  • 前端页面提交以“.do”结尾的请求。
  • FilterDispatcher接收请求并调用Action处理该请求。
  • Action处理完毕返回一个逻辑视图。
  • FilterDispatcher根据Action返回逻辑视图创建物理视图
  • 将物理视图返回给页面。

当然我们也可以在一个PHP文件中实现整个前端控制,直接约定命名规范,根据传递进来的参数动态加载处理器,处理方法,视图等。