目前在开发Web应用时,一个关键的问题就是选择哪个Web Framework。在Web普及之前,与人进行交互的GUI程序基本上就是普通桌面应用,那个时候并没有这么多界面架构,人们在开发一个桌面应用的时候很少去要考虑选择哪个GUI Framework;转眼到了Web界面应用的年代,从最早的CGI到现在的Rich Web Client,各种Web Framework层出不穷(特别是在Java领域)。要了解这些繁多的Web Framework是一件恼人的事情,Web Framework应该有什么功能,挑选它们的时候又要考虑哪些因素呢?
最近我在阅读一些JSF的资料,在学习JSF的过程中,也将自己一直以来关于Web界面应用开发的想法进行了梳理。我计划从桌面应用开始,逐一谈谈自己对GUI/Web Framework的思考。
一、Desktop Client Application
1. GUI Framework
开发一个桌面应用,
第一步就是要选择一个GUI Framework。你可能会觉得疑惑,我刚才不是说不需要考虑么?不需要考虑并不是说不需要选择,只不过这种选择非常自然以至于大部分人都没有感觉。当我们需要在荧屏上显示一个按钮的时候,并不是自己画线条图案将按钮画出来,而是通过某个具体的GUI Framework来显示。当我们用VC、VB、Delphi开发时,自然就选择了其附带的GUI Framework,当使用Java就会选择JFC/Swing,或者某些情况下使用跨平台的
wxWidgets。
2. 界面布局
接下来就要根据需求定义界面,输入框多大、放在什么地方,下拉选择框放置在哪里,菜单包含什么项,有哪些按钮等等。主要是要说明界面由GUI Framework的哪些组件组成,组建的组成关系,以及这些组件的属性(包括内容、布局等)。
完成这个工作基本上有两种方式,一种是直接在源代码中编程说明,例如下面这段Java Swing程序,就定义了一个窗体(Frame),并且往其中增加了一个文本说明(Label)。
JFrame frame = new JFrame("HelloWorldSwing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add the ubiquitous "Hello World" label. JLabel label = new JLabel("Hello World"); frame.getContentPane().add(label); |
另外一种就是通过IDE进行布局,这种开发环境往往会有相关的布局文件,在其中描述界面。例如Delphi的DFM文件,Visual Basic的FRM文件。这些界面描述文件往往对开发人员是透明的,由IDE负责它们与源代码之间的同步。
3. 组件对象树
在面向对象的GUI Framework中,每个组件都一个对象与其对应,当程序运行起来后,通过
Composite Pattern把不同的组件按照父子关系形成一个组件树。开发人员可以通过更改组件对象的属性(颜色、大小、内容)影响其外观,一般来说也可以任意一个组件出发,通过getParent()/getChild()等方法遍历整个组件树。
4. 用户事件处理
在定义好界面后,就要编写处理用户操作的程序。这里主要解决两个问题:1)如何捕获用户的操作;2)如何得到用户的输入。现在的GUI Framework都是采用事件(Event)机制传送用户的操作,而程序捕获事件的方式一般有两种:
a)针对某个组件注册一个事件处理函数,当这个组件或者其子组件有事件发生时,系统就会调用所注册的函数进行处理。灵活的注册机制除了针对组件之外,还可以针对不同的事件类型进行注册。
b)组件对象已经定义了一系列的事件处理方法,开发人员可以重载这些方法来实现自己的逻辑。例如常见onClicked()等方法就是这种类型。
至于获得用户的输入,因为用户在界面输入的值都保留在对应的组件对象中,因此只要在事件处理方法中获得所关心的组件对象,就能得到用户的输入。
5. 界面逻辑和业务逻辑
在事件处理方法中,开发人员主要处理两种逻辑:首先是根据用户的请求进行相关处理,例如查询更改数据库、调用域对象的功能等,这部分属于业务逻辑;在得到结果后,则根据结果更新界面,或者只是更新界面的某个部分,或者是切换到另外的窗口,这部分一般称之为界面逻辑。
到这里我们可以看到,GUI界面编程最关键的就是面向组件、事件驱动的GUI Framework,它是界面开发的基础。同时面向组件的框架使得开发人员能够自定义组件,设计出复杂的组件并重用。
二、Simple Web Application
所谓的
World Wide Web,最基本的三个协议分别是
Uniform Resource Identifier (
URI),
HyperText Transfer Protocol (
HTTP)和
HyperText Markup Language (
HTML)。
HTTP协议是一个浏览器与服务器之间请求/相应模式的协议,因此Web应用的基本模式是:
1、浏览器显示HTML页面
2、用户填写HTML Form,点击“提交”按钮;或者直接点击某个连接
3、浏览器将用户请求组装成HTTP请求发送给服务器
4、服务器处理请求,并返回HTTP相应——HTML页面
为了进行Web应用开发,人们最早发明了CGI(
Common Gateway Interface)协议,接着一类是CGI的改进,例如NSAPI、ISAPI、Java Servlet等;另外一类是脚本语言,例如PHP、ASP、JSP等。但无论如何,其应用基本模式没有变化。
让我们来对照一下Web应用的基本模式与桌面应用的不同:
1. GUI Framework
无。开发人员直接面对最基础的HTML协议。
2. 界面布局
采用HTML进行界面描述。
3. 组件对象树
无。实际上运行时服务端没有任何对象与浏览器的显示相对应。
4. 用户事件处理
只有一种事件,就是HTTP请求。事件处理程序通过URL映射来指定,用户的输入值通过解析Query String获得。
5. 界面逻辑和业务逻辑
业务逻辑与桌面应用相似。由于HTTP的特性,每次请求的相应都是重新构造一个HTML页面,也此Web应用的界面逻辑就是页面的跳转逻辑。
对于Web应用,与桌面应用最大的不同就不存在一个GUI Framework,因此相比之下Web开发人员的开发模式可以说是非常简陋的,就只是针对HTTP请求——字符串——进行编程。由于没有GUI Framework,开发人员直接面对HTML,也带来了臭名昭著的“代码混淆”问题,就是HTML和程序代码混淆在一起。
总的来说,Web应用都有这样的特征:
1. 请求/响应模式
2. 界面逻辑体现为页面的跳转
三、Struts Like Web Framework
前面提到Web应用开发中的一个常见问题——“代码混淆”,为了解决这个问题,以及为了提高Web应用的开发效率,一系列的Web开发框架被提出来,其中应用最广泛的是Apache旗下的
Struts。
页面=>操作=>页面=>操作,这是每个Web开发人员都要处理的流程,在这个流程中,主要包含这样的逻辑:
1、根据用户的输入、以及上下文关系,调用正确的“操作”;
2、根据操作的结果,将用户导向到正确的页面。
这个流程,一般来说也是应用业务流程的表现,往往被淹没在“代码的海洋”中,使得普通的Web应用难以维护。想想如果你接受一个前任的Web项目,里面包含了上百个JSP页面和数十个Servlet,要从中找出相关的逻辑关系想必是件非常头痛的事情。Struts在采用MVC模式后,将这些逻辑从代码从抽取出来,通过配置文件来说明。
为了更加方便获得用户的输入,Struts提出ActionForm的概念,道理其实很简单,就是HTML Form属性和Java对象的自动转换。这样,在“操作”中,开发人员所处理的参数是不再是恼人的字符串,而是一个真正的Java对象。
Struts主要做到了三点:
1、严格的MVC分离
2、页面/操作逻辑配置化
3、HTML Form与ActionForm的自动转换
从编程模式上来看,Struts和普通Web是相同的:
1、同样基于请求/相应模式,但是作了改进,根据配置调用具体的操作,HTML Form的自动转换
2、界面逻辑同样体现为页面的跳转
在Struts之后,还出现了一系列的Web Framework,例如webwork、Spring-MVC等。主要是因为随着XP的流行,大家对“可测试、可维护”更加重视了。而Struts的Action Class严重依赖HTTPServlet,难以独立测试;再加上使用ActionForms所带来的不便。所以你看到这些Web Frameworks的努力主要有:
1、降低“操作”方法对Servlet容器的依赖,提高可测试性
2、支持HTML Form与POJO的自动转换
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=709254