随着互连网应用的深入和发展,三层体系结构的应用模式也得到更多人的青睐。本文介绍了三层结构应用程序的概念和优点,并结合一个实例介绍了如何建立三层结构的ASP应用程序。
一、两层结构的ASP应用有何缺点
ASP有一个天生的缺点,就是ASP代码和HTML代码是混在一起的,ASP程序员既需要考虑与数据库打交道,需要关心如何与HTML配合,有时还需要用ASP直接生成HTML代码。其结果是,当程序逻辑足够复杂时,.asp源文件非常长;而且,无论客户提出用户界面的改变,还是商业逻辑的改变(比如,在考试系统中,"合格"的标准可能从达到60分就算合格,改为进入前100名才算合格),都需要对.asp文件进行改动,而商业逻辑的改变,很可能需要改动很多文件。
二、三层结构的概念
在传统的C/S应用中,也存在着上述同样的问题,多层结构的应用正是在C/S 结构的基础上产生的,并且也扩展到了B/S应用开发领域。 即将应用划分为三层(可以有更多层,但三层最常见): 用户界面层,商业逻辑层,数据库层。
用户界面层负责处理用户的输入和向用户的输出,但并不负责解释其含义(出于效率的考虑,它可能在向上传输用户输入前进行合法性验证),这一层通常用前端工具(VB,VC,ASP等)开发。
商业逻辑层是上下两层的纽带,它建立实际的数据库连接,根据用户的请求生成SQL语句检索或更新数据库,并把结果返回给客户端,这一层通常以动态链接库的形式存在并注册到服务器的注册簿(Registry)中,它与客户端通讯的接口符合某一特定的组件标准(如COM,CORBA),可以用任何支持这种标准的工具开发。
数据库层负责实际的数据存储和检索。 有了这样的结构,上面的问题迎刃而解:还是以考试系统中的合格标准为例,在客户端所有需要显示合格人员名单的地方,调用这样一个函数GetQualifiedList,至于这个函数如何编写,如何与数据库打交道,以至访问的是何种数据库都与其无关(你一定有过这样的经历,在一种数据库系统上运行得很好的SQL语句,有时换到另一种数据库系统上必须加以修改); 在中间层DLL中实现这个GetQualifiedList函数,如果用户对"合格"的定义变了,只需要修改这个函数就可以了,只要此函数的入口参数和返回内容不变,在客户端不需作任何改动。在这里,我们看到了面向对象编程的特性之一封装性的优点,而这一点在开发大型应用时尤其有用--我们可以把开发人员分成两组,一组负责开发界面层,另一组负责开发商业逻辑层,双方只要按照事先商定的函数接口,并行地开发就可以,而不必向从前那样,后面的工作必须等前面的工作完成后才能开始。当然,这样的开发模式需要很好的项目协调和文档作支持。
你也许会问,如果我把这些函数些在一个单独的文件中,再在需要调用的地方把它包含进来,不是同样能达到目的吗? 第一,这种方法效率不高,无论你把这些函数分散到多少个文件中,当你需要调用其中一个时,总会包含进一些实际上并不需要的函数,这无疑加重了服务器的负担,对服务器性能要求较高的Web应用尤其如此。 而DLL只在需要时才调入内存且只调入需要的函数,并且多个应用程序实例可以共享同一个DLL实例;第二,设想一个员工,有20个属性(工号,姓名,年龄,性别......),现在给定某工号,要求返回此员工所有信息。此时如果单纯用函数,只能定义20个全局变量,在函数中改变这些变量值,或者定义一个有20个传参(by reference)参数的函数。显然,第一种方法很麻烦而一旦增加一个属性后一种方法就需要更改函数接口。而在一个对象里,既包含成员方法(即函数和过程),也包括成员属性。如果我们采用对象的方法,则在函数中只需要改变对象的属性,在函数外可以直接引用改变了的对象属性值。 这种方法有些类似第一种方法,但1.属性值无需在函数外逐一说明;2.这些属性值只属于对象,与对象无关的代码不会无意地改变属性值;3.一旦对象被释放,这些值会被一起释放。
三、如何开发三层结构的ASP应用程序
ASP具有良好的扩充性,我们访问数据库时,采用的时ADO对象,访问文件时,采用的是文件系统对象(FSO),其实这时程序已经是三层结构的应用程序了,只不过由于是利用内置的对象而为意识到罢了。这些对象都遵循COM/ActiveX接口,因此我们自己开发的对象也要遵循这个接口。下面,我们就以上文提到的"合格"标准为例,演示如何创建自己的三层结构的ASP应用。
1、在数据库系统中建立如下数据库表:
Employee: EMPLID char (5) not null,
Private msEMPLID as string
private colQualifiedList as new Collection
也许你会说,为何不把集合声明Public,这样在ASP中不是可以直接引用吗?确实,这样也行得通,编程实现起来也更简单些,但是,这样做破坏了封装性原则。因为数据以何格式存储完全是商业逻辑层的事,与用户界面层无关,假设有一天你因为每种原因放弃了用集合来存储数据的设计,而改用数组或记录集(Recordset)来存储,那你只需要修改GetFirst和GetNext两个函数,用户界面层完全无需修改。至此类文件创建完毕,将工程文件存为 test.vbp,选File菜单下的Make test.dll选项将其编译。
3、注册动态链接库
启动Web Server 上的Microsoft Transaction Server (Start--Windows NT Optionpack4--Internet Information Server--Internet Service Manager),展开Microsoft Transaction Server--Computer--My Computer--Package Installed,点鼠标右键选New--Package--Create Empty Package,输入包名Test(这里Test是任选的名字,不一定要与DLL同名),OK-Interactive User-the current Logon user--Finish。双击Test--Component,右键选Component-New-Component-Install New component(s)-- Add File,选择你刚编译好的DLL文件,MTS会发现DLL中有两个类Employee和Employees。至此DLL注册完毕。
4、编写ASP程序
<HTML><Body>
注意在ASP中创建类实例的语法set oEmployees=server.createobject("Test.Employees"),其中Test是DLL的名字,Employees是类的名字; 当然,如果一个函数的返回值是一个对象,类似set oEmployee=oEmployees.GetFirst()这样的语法也是可以的。
至此,一个完整的三层结构的应用程序已经完成了,让我们看以下,如果把"合格"的定义改为:只有成绩进入前100名才算合格,程序需要做那些修改。事实上,如果你的数据库系统是SQL Server,你只需把SQL语句改为: sql="select top 100 EMPLID from Employee order by Score desc" 就已经可以了,即使为了跨数据库系统的兼容性,我们也只需要对GetQualifiedList做如下修改:
sql="select EMPLID from Employee order by Score desc"
Public Function Fun1(p1 as string,p2 as integer) as integer