作者:老王
更新:鉴于我最初的行文方式有让人误解之嫌,所以我对措辞做了适当的删减,使之更简明扼要。
所谓前端控制器(FrontController),是指一个请求运行的公共起点,并且在这里决定下一步执行什么。
多数PHP框架里都实现了它。统一进行权限限制,会话管理等等公共操作,并且进而通过一个类似路由的装置,把请求委派给一个具体的命令对象来执行。实现方式上,前端控制器通常是以一个名为index.php的文件为载体,通过重写规则把请求都转发到这个文件上,如CakePHP在Apache上的设置:
<IfModule
mod_rewrite.c>
RewriteEngine
On
RewriteCond %{REQUEST_FILENAME}
!-d
RewriteCond %{REQUEST_FILENAME}
!-f
RewriteRule ^(.*)$ index.php?url=$1
[QSA,L]
</IfModule>
不过老话说,物极必反,随着前端控制器使用的泛滥,越来越多的人开始质疑PHP开发是否有必要使用前端控制器。这里以PHP之父Rasmus
Lerdorf的影响最大,早些时候,他在Simple
is Hard里陈述了如果想开发出有扩展性的Web应用,必须保证架构是Share-nothing
Architecture:
Share-nothing
Architecture
* Like HTTP, each request is
distinct
* Shared data is pushed down to the
data-store layer
* Avoid front
controllers
在Rasmus Lerdorf看来,想要让一个网站具有良好的扩展性其实是非常简单的,只需将网站应用分成若干个独立小程序,前端透过API提供服务,后端是应用程序引擎,这样做自然会有扩展性。因为应用的每一个部分,都有不同等级的使用方式,需要有不同的扩充程度,需要不同的机制来处理。以开发雅虎电子邮件而言,是要开发一个地址服务程序、一个读信服务、一个送信服务,而送信程序完全和读信程序无关。以雅虎的规模而言,需要让这些工作完全分离,才有扩充性。这里的关键是你必须建立分离、模块化的独立端点,而不是全部放在同一个大篮子里。大多数现今开发框架,都使用了前端控制器,每一次浏览器发出请求时,就会调用这个前端控制器,再由前端控制器来分辨,使用者想要执行哪一支程序。这样做,一点意义都没有。在浏览器层次,程序完全能知道用户想要做什么事情,例如使用者只是要读信,程序就不用再把需求送到服务器,让服务器判断使用者要读信还是送信。将这类决策工作拉出浏览器,由服务器处理,就会浪费大量服务器资源,来处理那些对用户没有实际功用的工作。
总结:
首先,前端控制器里存在一个路由转发的过程,这个过程是在服务端完成的,不管是什么请求都要经由前端控制再完成路由转发,这个过程很可能会引起性能问题。如果抛弃了前端控制器的做法,转而使用页面控制器的实现方式,那么服务端就不必再存在路由转发的过程,因为在把页面渲染到浏览器上的时候,自然而然就完成了路由的设定,不同的动作对应着不同的URL。功能实现则完全由页面控制器来实现。如果某个动作引起了性能的瓶颈,那么我们只要针对这个动作对应的URL增加更多的服务器就可以完成扩展。
另外,传统的MVC理论里,强调代码逻辑上的分离,但并未就物理分离做出描述,Rasmus
Lerdorf在这方面做出了有益的补充,按Rasmus
Lerdorf的引申想法,M和V是分别位于不同服务器的,V通过WebService调用M上的数据。
请牢记Rasmus
Lerdorf的教诲。
参考链接:Rasmus 校園講座台大場:Simple is Hard