WEB程序的架构基本上可以分成以下三类:
一 、基于“组件”(Component ,GUI设计也常称控件)、事件驱动的架构,最常见的是微软的.NET。基本思想是把程序分成很多组件,每个组件都可以触发事件,调用特定的事件处理器来处理(比如在一个HTML按钮上设置onClick事件链接到一个PHP函数)。这种设计远离HTTP,HTTP请求完全抽象,映射到一个事件。
事实上这种设计原本最常应用于传统桌面GUI程序的开发,例如Delphi,Java Swing等。所有表现层的组件比如窗口,或者HTML表单都可以由IDE来提供,我们只需要在IDE里点击或拖动鼠标就能够自动添加一个组件,并且添加一个相应的事件处理器。
二 、基于“WEB页面/文件”,例如CGI和PHP/ASP程序。程序的文件分别存储在不同的目录里,与URL相对应。当HTTP请求提交至服务器时,URL直接指向某个文件,然后由该文件来处理请求,并返回响应结果。
比如http://www.website.conm/news/readnews.php?id=1234
可以想像,我们在站点根目录的news目录下放置一个readnews.php文件。
这种开发方式最自然,最易理解,也是PHP最常用的方式。要注意产生的URL对搜索引擎不友好,不过你可以用服务器提供的URL重写方案来处理,例如Apache的mod_rewrite。
三 基于“动作”(Action)。这是MVC架构的WEB程序所采用的最常见的方式。目前主流的WEB框架像Struts、Webwork(Java),Ruby on Rails(Ruby),Zend Framework(PHP)等都采用这种设计。URL映射到控制器(controller)和控制器中的动作(action),由action来处理请求并输出响应结果。这种设计和上面的基于文件的方式一样,都是请求/响应驱动的方案,离不开HTTP。
比如 http://www.website.com/news/read/id/1234
可以想像在实际代码中,我们会有一个控制器newsController,其中有一个readAction。不同框架可能默认实现方式稍有不同,有的是一个Controller一个文件,其中有多个Action,有的是每个Action一个文件。当然这些你都可以自己控制,题外话。
这种方式的URL通常都很漂亮,对搜索引擎友好,因为很多框架都自带有URL重写功能。可以自由规定URL中controller、action及参数出现的位置。
另外,还有更直接的基于URL的设计方案,那就是REST。通过人为规定URL的构成形式(比如Action限制成只有几种)来促进网站之间的互相访问,降低开发的复杂性,提高系统的可伸缩性。REST对于Web Services来说是一个创新。
虽然本文讨论的是单个项目所采用的架构,而REST是为了解决网站之间的通讯问题,但REST的出现,会对单个项目的架构造成影响(很显然你在开发时就要构造规范的URL)。将来混用REST和MVC应该也是一种趋势。RoR提供很好的REST支持,Zend Framework也提供了Zend_Rest来支持REST,包括Server和Client。
三代WEB存在的问题:
(1)效率问题
这里指的不是开发效率,而是代码的执行效率。众所周知,正常情况下,PHP的执行是相当高效的。但是目前这种基于控件的框架效率都成问题。Prado本身提供了一个缓存机制来缓解这个问题。如果不采用缓存,可以说很多站点根本不能使用Prado这样的框架,比如门户网站,大型论坛等。
但ASP .NET不太一样,因为它是编译型的框架,最后生成的代码是编译生成的,不需要再次进行中间过程的诸多处理,所以在第一次执行之后速度会很快,执行效率还是很高的。 这是语言层次的功能,Prado无法通过代码层次的努力完全弥补。
(2)没有强大的IDE支持
设置控件的属性,添加其对应的事件处理器,看似简单,但控件多了,这也是个繁重的工作。.NET的强大就在于它把程序员从重复的工作中解放了出来,设置属性很方便,事件处理器也会自动添加。Prado目前没有这样的IDE支持。
总之,这种基于控件的框架比较适合于用户交互较多的,需要对页面中的很多组件设置不同处理操作,但对于性能要求不高的应用。另外,带有组件支持的框架通常对AJAX的支持都较好,比如.NET和Ruby on Rails。
综上,三种架构基本上可以代表目前的所有主流WEB开发方式,包括PHP,JavaEE,.NET,Ruby/RoR。