webclass实现动态web编程之理论篇
(作者:苏红超 2001年01月10日 15:50)
在前一段时间,我曾经在“用vb activex dll实现asp编程”一文中详细探讨过如何使用activex dll技术替代简单的纯asp来实现核心代码和商业逻辑的封装。适当的利用activex dll技术在构建动态web站点的时候的确能够带来很多的好处,这是显而易见的,但是仍然需要一个单独的asp文件来创建和销毁我们所编写的activex dll组件,在asp中大量使用activex dll是不现实的,并且我们的asp编程仍然不可以像往常的应用程序那样进行编写,因为凌乱的asp代码和html代码交织在一起,并且,无论是单纯的asp程序还是封装了activex dll的asp程序,一个最大的弊端就是在项目开发过程中的调试困难,比如很难设置断点并随时暂停程序来察看某些变量的值。那有没有两全其美的方法呢,既保证开发web程序的高效率,又可以向平常的应用程序那样可以方便的调试和编写呢?答案当然是肯定的,微软公司在vb6版本之后就引入了“webclass”的概念,并且在新建项目中增添了名叫“iis应用程序”的项目类型。webclass正是微软公司提出的用来使得程序员可以像开发普通应用程序那样来开发web程序的解决方案!
说起“iis应用程序”,大家会认为这和asp程序有何区别呢?asp不就是运行在iis上面的web应用程序吗?其实这是微软命名上面的一点小错误,使得大家在名称上面比较容易混淆。我们现在应该清楚,“iis应用程序”就是采用webclass技术用来实现和asp同样功能的应用程序,它避免了asp的种种缺点,比如源代码是透明的、解释执行带来的速度慢。其实webclass应用程序也是一种vb组件,使用他完成的web应用程序将会是编译之后的,其运行速度有很大提高,同时也避免了源代码和核心技术及商业机密被泄漏。
webclass 在实质上是一个vb组件,确切一点说来讲webclass是一个activex dll。他使得你可以编写服务器端代码以响应来自用户的浏览器请求。对用户来说,一个 iis 应用程序好象是由一系列的html页面组成;对开发者来说,一个 iis 应用程序是由一些被称为 webclass 的特殊类型对象组成。webclass可以直接访问所有的asp内置对象(request、response、application、session、server)。任何使用asp开发的web项目都可以在webclass中实现。由于在webclass中引入了html模版的概念,从而有效的避免了asp中的程序代码和html代码相互交织带来的缺陷,很好的实现了商业逻辑层和最终表现层的分离(有些类似当前xml和xsl的形式),极大的提高了web项目的开发效率。
iis 应用程序在表面上和 active server pages 应用程序相似。这两种应用程序都显示动态的 web 站点,并且都是在服务器上而不是在客户端上执行它们的处理。但是,每一种都有自己独特的优点:
(1)active server pages 适合于对制作 web 页面感兴趣的脚本开发者,它提供了将脚本和 html 混合起来的独特能力。
(2)iis 应用程序适合于构造基于 web 应用程序而不是 web 页面的 visual basic 开发者。iis 应用程序允许复杂的事务处理,并且几乎任何的浏览器或平台都可以很容易地访问它。
使用iis应用程序来开发web项目可以有如下优点:
(1)熟悉的开发环境和模型。可以利用 visual basic向工程添加类(class)、模块(model)或任何 visual basic activex 部件,因而易于调试和编写。
(2)使用的广泛性。可以被大多数的浏览器支持。
(3)可重复使用的部件。类似于面向对象编程;各个对象之间可互相访问。
(4)代码和 html 相分离:和编写asp 应用程序不同,server 端处理程序和client端程序分离,便于维护和修改。
(5)可自定义处理事件,因而编写方法灵活
接下来我们来看看webclass的具体组成部分是什么:
webclass 由html模板和自定义 webitem 组成。( html模板和自定义 webitem统称webitem)当然不是必须包含模板和自定义的webitem。
(1)一个 html 模板文件是与 webclass 相关联的html页面。当 webclass 收到一个请求时,它可以向浏览器发送用于显示的html页面。模板和常规html页面的不同仅在于向浏览器发送页面之前,它常常包含 webclass 可以处理的替换区域(通常是用"wc@"标签定义的范围)。这样就允许自定义自己的响应。
(2)一个自定义的 webitem 是由一个或多个事件处理程序组成的程序资源。在页面加载或用户选择一个 html 元素时,这些事件处理程序被浏览器调用。这些事件处理程序可以对浏览器产生一个响应或将处理传递到另一个 webclass 的 webitem。
一个完整的webclass应用程序的大致流向如下所示:
a.指定某一个webclass(比如test1)作为首先启动的项目
b.激活这个webclass(test1)的webclass_start事件
c.在test1的webclass_start事件中调用某一个html模板的writetemplate方法,比如check. writetemplate这里的check就是一个属于test1这个webclass的一个html模板
d.在你的这个check模板中如果有<form>存在,那就会触发这个<form>的action属性,比如<form action=xxx.asp?wci=ddd>,那么就会调用属于名为'xxx'的这个webclass的'ddd'项目(item);当然这个'xxx'可以是你刚才操作的webclass本身,即"test1",同样,这个"ddd"可以是一个html模板或者一个webitem。
e.触发属于"xxx"这个webclass的项目"ddd"将会激活"ddd"本身的ddd_respond()事件,你就可以在这里进行一些处理了,比如检索数据库资料;然后可以再调用其它html模板的writetemplate方法,比如就调用本身的ddd.writetemplate方法
f.然后将会调用ddd的processtag事件,进行卷标的处理过程,当然你的这个叫ddd的html模板中就要有相应的wc@卷标了。
我们再来看看webclass中的事件响应。
1. .webclass中预定义的事件有3个 : response , processtag , userevent
.response 事件响应用户端请求。
.processtag 事件是作为 writetemplate 方法处理的一部分自动发生的。不能单独被触发或用来处理响应。
.userevent 事件: 一个 userevent 过程处理 webitem 的所有用户事件。userevent 事件是由urlfor 方法在运行时产生的。所以只有使用了urlfor 方法动态产生的超链接才会触发userevent 事件。
2. webclass_start() 事件类似于vb中的sub main()。
所以可以指定一个project 开始的webclass。也可在model 模块中用sub main() 来启动。
3. 发送html 到浏览器: 将页面反馈回浏览器有两种方法。
a.对html模板使用 "writetemplate" 方法。此方法激活"processtag"事件,从而对模板中相应的内容(用wc@符号标记的部分) 进行替换。
b.在customwebitem 事件中动态生成反馈页面。
如: with response
.write "<html">
.write"<head>"
.write"</head>"
.write"<body>"
.write"<p>hello! universe!</p>"
.write"</body></html>"
end with
4. 从html 的<form>中获取信息:
使用request 对象在一个 html <form>中获取用户输入的信息。但必须将 <form action...> 标记属性和webclass中的一个事件连接,提交一个form 就可以激发 webclass 中的这个事件。因此,就可以使用这个事件搜集和操作信息。
5. 动态替换html 模板文件中的内容:使用3中的writetemplate 方法。
6. 自定义webitem 事件。
两种方法和自定义webitem 事件关联起来:
a.用action=webclass.asp?wci=webitem&wce='自定义事件'的方法。
b.用urlfor (webitem,自定义事件)方法。
7. 其他使用方法(如: cookie,session对象等) 和 asp 应用程序中相同。
webclass中在传回给用户的html中可以使用两种方法建立超级链接,很容易造成混淆,这里我就详细讲解一下这两种方法:
方法一.
一种是直接使用类似于这样的格式<a href="xxx.asp?wci=sss&wce=ddd">,这样当用户点击这个超级连接的时候,就会传跳到xxx这个webclass的sss项目的sss_userevent事件当中来,你就可以在这个事件中进行一些处理,而且这种生成超级连接的方法可以在自己的后面带许多的自定义的参数,比如<a href="xxx.asp?wci=sss&wce=ddd&test=www&me=rrr...">其中的test,me都是我们自定义的参数,可以在转跳之后页面中使用request("test")方法取出其中的值,这样就提供了一种在页面之间传递值的解决方法;