各位大人快快近来,超级报酬300000w悬赏(发帖人MP:876722)

浏览量:107 回复数:20
悬赏帖:本贴悬赏 0 MP
由于我在这里发现了我所需要得文章,http://www.happycampus.com.cn/pages/2004/11/30/D155776.html,由于小弟的HP〈9,所以不能下载文章,故在这里求购HappyCampus 帐号,要求HP>9,〉或者你下载下来传给我,报酬是全给我的MOP,当然可以联系我qq:94788759具体洽谈。
  • 猫(1) 牧风子
  • HP什么意思啊?
  • 2005-05-02 11:32:28
  • HP相当与这里的MP,楼主最好小心,因为这个网站蛮多人知道的,建议去清华大学资料库找论文
  • 2005-05-02 11:43:53
  • 帮顶也要分钱才索王道
  • 2005-05-02 11:47:51
  • 猫(5) 夏日紫雨
  • 楼上的有理啊
  • 2005-05-02 13:01:32
  • 扑(6) headstream
  • 就是,那就一起帮顶了
  • 2005-05-02 13:05:39
  • 4楼正解

    楼猪要厚道
  • 2005-05-02 13:11:53
  • 没有帐号只能帮顶一下了
  • 2005-05-02 14:50:36
  • 猫(9) 达人小晕
  • 只能帮顶了.希望有达人看见.呵呵~
  • 2005-05-02 15:16:29
  • 扑(10) 120742699
  • 我也帮搂主顶下哦!!!偶索新猫,能不能来点mop阿!
  • 2005-05-02 15:21:46
  • 猫(11) 弹珠汽水
  • 只能帮楼主顶了!~
  • 2005-05-02 16:03:53
  • 猫(13) lilith_liu
  • 帮顶也有MP分哦?
    那我也顶。。。
  • 2005-05-02 16:29:12
  • 扑(14) heicao731
  • 帮顶有份我也顶了。
  • 2005-05-02 16:36:43
  • 猫(15) 反过来念
  • 先拿一部分MP出来砸先
  • 2005-05-02 16:44:28
  • 顶一下,楼猪也给点MP吧,太穷 了。。
  • 2005-05-02 16:51:10
  • 猫(17) 吃喝嫖抽
  • 木有办法.顶一下
  • 2005-05-02 17:14:31
  • 扑(18) linfei105
  • 俺有HP,虽不多,但好像够你要的那个论文,QQ 加你了
  • 2005-05-02 17:34:45
  • 猫(19) linfei105
  • 联系你了,但没回音。不会要我贴出来吧,用WORD打开足有45页
  • 2005-05-02 17:52:34
  • 扑(20) linfei105
  • 摘 要

    INTERNET/INTRANET技术的日益发展,使人们认识到了INTENET/INTERNETR 优势,更使得数据库与WEB的连成为数据库开发方面的热门技术之一。
    ASP即ACTIVC SERVER PAGES (动态服务器页面),是微软公司新一代开发动态网页的技术,具有开发简单、功能强大等优点,可以非常简单直观地实现复杂的WEB应用。ASP实际上不是一种语言,而是一种应用程序环境。
    利用网络和数据库技术,结合目前硬件价格普遍下跌与宽带网大力建设的有利优势,基于B/S模式研究开发了在线考试系统这一ASP应用程序。它运用方便、操作简单,效率很高,现阶段虽只实现了试卷的客观题部分,但已具有试题(卷)录入、修改和查询,手工组卷与自动组卷以及进行在线考试等重要功能,也就是说实现了真正的无纸化考试,满足任何授权的考生随时随地考试并迅速获得成绩,并给出其详细的成绩分析与试卷评估,同时也大大减轻了教师出题、组卷和改卷等繁重的工作量。












    前 言

    现阶段,学校与社会上的各种考试大都采用传统的考试方式,在此方式下,组织一次考试至少要经过五个步骤,即人工出卷、考生考试、人工阅卷、成绩评估和试卷分析。显然,随着考试类型的不断增加及考试要求的不断提高,教师的工作量将会越来越大,并且其工作将是一件十分烦琐和非常容易出错的事情,可以说传统的考试方式已经不能适应现代考试的需要。随着计算机应用的迅猛发展,网络应用不断扩大,如远程教育和虚拟大学的出现等等,且这些应用正逐步深入到千家万户。人们迫切要求利用这些技术来进行在线考试,以减轻教师的工作负担及提高工作效率,与此同时也提高了考试的质量,从而使考试更趋于公证!客观!更加激发学生的学习兴趣。例如目前许多国际著名的计算机公司所举办的各种认证考试绝大部分采用这种方式。为了适应新形势的发展,我们推出了这一系统,使其尽快在各类考试中发挥高效、便捷的作用,把老师从繁重的工作中解脱出来!













    目 录
    第一章ASP内建对象…………………………………………1
    1.1 ASP内建对象概述………………………………………… 1
    1.2深入研究Application和Session对象 …………………2
    1.3 ASP 内建对象Request和Respones …………………5
    1.4 Server 对象 ……………………………………………7
    第二章 ASP服务器端组件 …………………………………10
    2.1 常用的 ASP ActiveX组件 ……………………………10
    2.2 浏览器性能组件 ………………………………………11
    2.3 Ad Rotator 组件 ……………………………………12
    2.4 Counters 组件 ………………………………………17
    第三章 在ASP中使用Oracle数据库 ……………………21
    3.1开发环境和工具 ………………………………………21
    3.2数据的访问和存取 ………………………………………22
    3.3编辑数据记录 ………………………………………23
    3.4删除数据记录 ………………………………………24
    3.5使用存储过程 ………………………………………27
    第四章ASP安全与性能优化 ………………………………28
    4.1 配置IIS4实现应用程序隔离 ………………………28
    4.2增强ASP程序性能 ……………………………………28
    第五章 ASP实例设计开发在线考试系统 ……… ……35
    5.1基本简介 ……………………………………………35
    5.2 运行环境与系统结构 ………………………………35
    5.3 系统特点 ………………………………………………35
    5.4 详细设计 …………………………………36
    5.5 ADO--ActiveX Data Object操作数据库的几个步骤 …42
    5.6数据的安全与保密 …………………………………43
    5.7 源程序列表 ………………………………………44
    第一章 ASP内建对象
    1.1 ASP内建对象概述
    Active Server Pages 提供内建对象,这些对象使用户更容易收集通过浏览器请求发送的信息、响应浏览器以及存储用户信息(如用户首选项)。
    Application 对象
    可以使用 Application对象使给定应用程序的所有用户共享信息。
    Request 对象
    可以使用 Request 对象访问任何用 HTTP 请求传递的信息,包括从 HTML 表格用 POST 方法或 GET 方法传递的参数、小甜饼 和用户认证。Request 对象使您能 够访问发送给服务器的二进制数据,如上载的文件。
    Response 对象
      可以使用 Response 对象控制发送给用户的信息。包括直接发送信息给浏览器、 重定向浏览器到另一个 URL 或设置 小甜饼 的值。
    Server 对象
      Server 对象提供对服务器上的方法和属性进行的访问。最常用的方法是创建 Ac tiveX 组件的实例 (Server.CreateObject)。其他方法用于将 URL 或 HTML 编码 成字符串,将虚拟路径映射到物理路径以及设置脚本的超时期限。
    Session 对象
      可以使用 Session 对象存储特定的用户会话所需的信息。当用户在应用程序的页 之间跳转时,存储在 Session 对象中的变量不会清除;而用户在应用程序中访问 页时,这些变量始终存在。也可以使用 Session 方法显式地结束一个会话和设置 空闲会话的超时期限。
    ObjectContext 对象
      可以使用 ObjectContext 对象提交或撤消由 ASP 脚本初始化的事务。
    1.2深入研究Application和Session对象
    用ASP编写虚拟社区、网上购物等程序时,Application和Session对象具有举足轻重的作用,能够灵活合理地运用这两个对象是提高程序质量的关键。
      一、Application对象的成员概述

      Application对象成员包括Application对象的集合、方法和事件。

      ⒈Application对象的集合

      Contents集合:没有使用元素定义的存储于Applicaiton对象中的所有变量的集合

      StaticObjects:使用元素定义的存储于Application对象中的所有变量 的集合

       ⒉Application对象的方法

      Contents.Remove("变量名"):从Application.Contents集合中删除指定的变量

      Contents.RemoveAll() :把Application.Contents集合中的所有变量删除

      Lock() :锁定Application对象,使得只有当前的ASP页对内容能进行访问

      Unlock() :解除对Application对象的锁定

       ⒊Application对象事件

      OnStart:第一个访问服务器的用户第一次访问某一页面时发生

      OnEnd :当最后一个用户的会话已经结束并且该会话的OnEnd事件所有代码已经执行完毕后发生,或最后一个用户访问服务器一段时间(一般为20分钟)后仍然没有人访问该服务器产生。

      想要定义application对象的OnStart和OnEnd事件里做什么需要将代码写在Global.asa这个文件里(下文有举例),并且将该文件放在站点的根目录下(一般是Inetpub\wwwroot\)

      二、Session对象的成员概述

      Session对象的成员比Application对象多一项属性,即:集合、属性、方法、事件

      ⒈Session对象的集合

      Contents :没有使用元素定义的存储于特定Session对象的所有变量的集合。

      StaticObject:使用元素定义的、存储于Session对象中的所有变量的集合。
      ⒉Session对象的属性

      CodePage: 可读/可写。整型。定义用于在浏览器中显示页内容的代码页。代码页是字符集的数字值,不同的语言使用不同的代码页。
      LCID : 可读/可写。整型。定义发送给浏览器的页面地区标识。LCID是唯一地标识地区的一个国际标准缩写,例如,2057定义当前地区的货币符号是"£"。

      SessionID: 只读。长整型。返回本会话的会话标识符。每创建一个会话,由服务器自动分配一个标识符。可以根据它的值判断两个用户是谁先访问服务器。

      Timeout : 可读/可写。整型。为会话定义以分钟为单位的超时限定。如果用户在这个时间内没有刷新或请求任何一个网页,则该用户产生的会话自动结束。缺省值是20。


      ⒊Session对象的方法

      Contents.Remove("变量名"): 从Session.contents集合中删除指定的变量

      Contents.Removeall() : 删除Session.contents集合中的所有变量

      Abandon() : 结束当前用户会话并且撤消当前Session对象。

      Session对象的Contents.Remove("变量名")和Contents.Removeall()方法与Application对象的基本上没什么区别,为帮助理解,大家可以参照上面的例子将Application改为Session。这里要说明一下的是Contents.Removeall()和Abandon()的区别,执行这两个方法都会释放当前

      用户会话的所有Session变量,不同的是Contents.Removeall()单纯地释放Session变量的值而不终止当前的会话,而Abandon()除了释放Session变量外还会终止会话引发Session_OnEnd事件,希望大家注意两者的区别。

      ⒋Session对象的事件

      OnStart: 当ASP用户会话产生时触发,一旦有任一用户对本服务器请求任一页面即产生该事件。

      OnEnd : 当ASP用户会话结束时触发,当使用Abandon()方法或超时也会触发该事件。

      三、Global.asa

      ASP的Application和Session对象体现了其他ASP内置对象所没有的特征--事件。每一个访客访问服务器时都会触发一个OnStart事件(第一个访客会同时触发Application和Session的OnStart事件,但Application先于Session),每个访客的会话结束时都会触发一个OnEnd事件(最后一个访客会话结束时会同时触发Application和Session的OnEnd事件,但Session先于Application)。

      OnStart和OnEnd这两个事件一般应用在虚拟社区中统计在线人数、修改用户的在线离线状态等。要具体定义这两个事件,需要将代码写在Global.asa文件,并将该文件放在站点的根目录下(缺省是\Inetpub\wwwroot\)。另外,Application和Session对象规定了在OnEnd事件里除了Application对象外其他ASP内置对象(Response、Request、Server、Session...)一概不能使用。
    1.3 ASP 内建对象Request和Respones
    一、Request
    语法:request.方法名称("参数")|request("参数")
       如果采用后者,系统会自动选择相应的方法。
       Form
        这里再重新强调Form的一些属性:
        Enc无效=资料传送的MIME形态
        Method=传送资料的方式Get/Post
        Onrest=按下rest键调用的程序
        onsubmit=按下sumit键调用程序
        Target=输出内容的frame窗口>
        使用Form传送信息一般有三种方式:由html网页内的Form传信息给其他Asp;由Asp内的Form传信息给另外一个Asp;Asp内的信息传送给自身。
       语法:Request.Form(参数)[(索引)]
       其中参数表示Form中元素的名称,索引表示相同名称元素的顺序号。
    2、QueryString
       语法:Request.QueryString(参数)[(索引)]
       除了用Form传输资料外,还可通过在超链接后接“?”的方式传输信息,如:,这时可通过Request.QueryString("user")读取传输的信息;如果出现多个重名的参数,如:,则第一次
      Resquest.QueryString("user")=abc,第二次
      Resquest.QueryString("user")=bcd,第三次
      Resquest.QueryString("user")=cde。
    3、ServerVariables
      语法:ServerVariables(参数名称)
      我们知道Web/Browse的传输协议是http,http的报头会有一些客户端的信息,如 客户IP地址、浏览器的语言系统等。这时可通过Request.ServerVariables("***")获取相关信息,如Request.ServerVariables("Accept_Language")可获取客户端浏览器 的语系。其他系统参数见下表:
      SERVER_NAME server的机器名称或IP地址。
      SERVER_PORT server正在运行的端口号
      REQUEST_METHOD 发出request的方法(GET/POST/HEAD
      脚本_NAME 程序被调用的路径,如:cgi-bin/a.pl。
      REMOTE_HOST 发出request请求的远端机器(client)的名称。
      REMOTE_ADDR 发出request请求的远端机器(client)的IP地址。
    REMOTE_IDENT 发出request的使用者名称(如是拨号上网,则为用户ID),当NCSA IdentityCheck为enabled,而且client机器支持RFC 931时,该变量有效。
    CONTENT_无效 数据的MIME类型,如:“text/html”。
    HTTP_ACCEPT client可以接受的MIME类型列表。
    HTTP_USER_AGENT client发出request的浏览器类型。
    HTTP_REFERER 在读取CGI程序之前,client所指的文本URL。
    4、小甜饼s
    在客户端,小甜饼s记录了客户端浏览器很多的信息,我们可通过Request.小甜饼s("名称")命令获取它的值,也可通过Response.小甜饼s("名称")="值"在客户端记录一些信息,以便控制访问者。设置多重小甜饼s的方法为Response.小甜饼s("名称")("名称")="值"。
    5、Cache
      我们可以在浏览器上设置从Cache中抽取已经访问过的页面的信息,同样,在Asp程序中也可进行类似的设置。其中Response.Clear为清空客户端的内存。Response.Buffer=True设置可从Cache中读取资料(缺省时为False)。
    6、ClientCertificate
      ClientCertificate用于获取客户端浏览器的身份确认信息(符合X.509标准),但客户端浏览器必须支持SSL3.0或PCT1协议。这里需做两步工作,第一步:web server必须启动用户端认证选项;第二步:对客户端浏览器进行相应设置,这样,该方法才会生效,否则,传回empty值。
    二、Response
    当要从服务器传送资料到客户端时,可通过下面的方法:
    1、Response.Write直接输出信息,如Response.write ""。
    2、Response.Redirect引导客户端到另一个url位置,如Response.Redirect "http://zyr.yeah.net",但这里有一个问题需要注意,就是该语句一定要放在标记前执行,也就是说在服务器未向客户端送出html文本报头前就要被执行,否则会出现传输错误信息。
    3、Response.Content无效控制输出的文件类型,服务器送给客户端的数据包类型可以是text/html文本,也可以是gif/jpeg图形文件,所以每次传输前,我们都必须告知客户端将要传输的文件类型,一般默认情况下为“Text/Html”类型。
    4、Response.小甜饼s 用于设置小甜饼s的值,语法为:Response.小甜饼s(变量名称)[(key)|属性]=写入的信息。(key的用法前面已作说明,这里不在叙述)小甜饼s系统默认有五个属性,包括Expires(时间)、Domain(域名)、Path(路径)、Secure(安全性)、Haskeys(判断小甜饼s下是否还有其它小甜饼s文本)。
    5、Response.Buffer用于确定是否把信息传输到缓冲区。因为有时候我们希望把部分中间信息送到缓冲区,然后继续工作。当所有处理工作都完成后,才把信息输出到客户端。但当在处理过程中Flush或End方法被调用,则缓冲区内容将被输出。
      Response的其它属性:
      Expires:设定网页保留在客户端浏览器的时间长度。
      ExpiresAbsolute:设定网页保留在客户端浏览器的日期与时间。
      Response的其它方法:
      AddHeader:设定HTML文件的HTTP报头。
      AppendToLog:在Web Server记录档案末尾,添加字串。
      Clear:清除在缓冲区中的HTML输出资料。
      End:停止处理asp档案,并回传当时状态。
      Flush:立刻送出缓冲区的HTML资料。
    1.4 Server 对象
    Server 对象提供对服务器上的方法和属性的访问 , 其中大多数方法和属性是作为实用程序的功能服务的。有了 Server 对象,你就可以在服务器上启动 ActiveX 对象例程,并使用 Active Server 服务提供象 HTML 和 URL 编码这样的函数。
       一、语法
       Server.property|method
       二、属性
       脚本Timeout 超时值,在脚本运行超过这一时间之后即作超时处理。如下代码指定服务器处理脚本在 100 秒后超时。
       $#@60; % Server.脚本Timeout=100 %$#@62;
       这里需要注意的是,通过使用元数据库中的 Asp脚本Timeout 属性可以为 Web 服务或 Web 服务器设置缺省的 脚本Timeout 值。脚本Timeout 属性不能设置为小于在元数据库中指定的值。
       三、方法
       1、HTMLEncode 方法
       HTMLEncode 方法允许你对特定的字符串进行 HTML 编码,虽然 HTML 可以显示大部分你写入 ASP 文件中的文本,但是当你需要实际包含 HTML 标记中所使用的字符,就会遇到问题。这是因为,当浏览器读到这样的字符串时,会试图进行解释。
       为了避免此类问题,我们就需要使用 Server 对象的 HTMLEncode 方法,采用对应的不由浏览器解释的 HTML Character Code 替代 HTML 标记字符。所以,用下面的代码才能显示正确的 HTMLEncode 字符串,从而在浏览器中按你的需要输出文本。
      $#@60; %
      Response.write Server.htmlEncode(" 这是对 HTMLEncode 方法的测试。$#@60; br$#@62; 这里应该不会另起一行。")%$#@62;
       2、URLEncode 方法
       就象 HTMLEncode 方法使客户可以将字符串翻译成可接受的 HTML 格式一样,Server 对象的 URLEncode 方法可以根据 URL 规则对字符串进行正确编码,当字符串数据以 URL 的形式传递到服务器时,在字符串中不允许出现空格,也不允许出现特殊字符。为此,如果你希望在发送字符串之前进行 URL 编码,可以使用 Server.URLEncode 方法。
       3、MapPath 方法
       MapPath 方法将指定的相对或虚拟路径映射到服务器上相应的物理目录上。
       语法如下 :Server.MapPath(Path)
       Path 指定要映射物理目录的相对或虚拟路径。若 Path 以一个正斜杠 (/) 或反斜杠 (\) 开始,则 MapPath 方法返回路径时将 Path 视为完整的虚拟路径。若 Path 不是以斜杠开始,则 MapPath 方法返回同 .asp 文件中已有的路径相对的路径。这里需要注意的是 MapPath 方法不检查返回的路径是否正确或在服务器上是否存在。

       4、CreateObject 方法
       Server.CreateObject 恐怕是 ASP 中最为实用,也是最强劲的功能了。它用于创建已经注册到服务器上的 ActiveX 组件实例。这是一个非常重要的特性,因为通过使用 ActiveX 组件能够使你轻松地扩展 ActiveX 的能力,正是使用了 ActiveX 组件,你可以实现至关重要的功能,譬如数据库连接、文件访问、广告显示和其他 VB脚本 不能提供或不能简单地依靠单独使用 ActiveX 所能完成的功能。正是因为这些组件才使得 ASP 具有了强大的生命力。
       其语法如下:
       Server.CreateObject("Component Name")
    默认情况下,由 Server.CreateObject 方法创建的对象具有页作用域。这就是说,再当前 ASP 页处理完成之后,服务器将自动破坏这些对象。如果要创建有会话或应用程序作用域的对象,可以使用 $#@60; OBJECT$#@62; 标记并设置 SESSION 或 APPLICATION 的 SCOPE 属性,也可以在对话及应用程序变量中存储该对象。








    第二章 ASP服务器端组件
    2.1 常用的 ASP ActiveX组件
    ASP 编写服务器端应用程序时,必须依靠 ActiveX 组件来强大 Web 应用程序的功能。要在非 NT 平台上开发并运行 ASP 应用程序我们可以依赖于一套名为 Instant ASP 的第三方软件,它的广告标语非常吸引人“ASP Anytime, Anywhere”,我想所有 ASP 的开发者们看到如此的标语必然兴奋不已。这套由 Halcyon 软件公司开发的软件使得你无需重复开发原有 ASP 应用程序即可以将它运行在任何操作平台上 ! 这样非但节省了大量的开发时间,而且使得 ASP 真正成为了一种跨平台的 Internet、 Intranet 或 Extranet 应用程序。 Instant ASP 本身其实是一套基于 Java 的应用程序,因此通过它你可以将基于 WEB 的 ASP 应用程序运行在任何平台上。
       一、 Database Access 组件
      我们在 WEB 服务器上运用 WEB 应用程序进行的最常见和最实用的任务就是访问服务器端的数据库。而 ASP 内建的 Database Access 组件使得我们能够轻而易举地通过 ActiveX Data Objects (ADO) 访问存储在服务器端的数据库或其他表格化数据结构中的信息。 ADO 是对当前微软所支持的数据库进行操作的最有效和最简单直接的方法,它是一种功能强大的数据访问编程模式,从而使得大部分数据源可编程的属性得以直接扩展到你的 Active Server 页面上。可以使用 ADO 去编写紧凑简明的脚本以便连接到 Open Database Connectivity (ODBC) 兼容的数据库和 OLE DB 兼容的数据源,这样 ASP 程序员就可以访问任何与 ODBC 兼容的数据库,包括 MS SQL SERVER、 Access、 Oracle 等等。如果您是一个对数据库连接有一定了解的脚本编写人员,那么您将发现 ADO 命令语句并不复杂而且容易掌握。同样地,如果您是一个经验丰富的数据库编程人员,您将会正确认识 ADO 的先进的与语言无关性和查询处理功能。熟悉 VB 数据库编程的朋友会发现 ADO 与 RDO (Remote Data Objects) 有某种类似的地方。但据说 ADO 的访问的速度更快,内存需要更小。
      二、 Content Linking 组件
    Content Linking 组件创建管理 URL 列表的 Nextlink 对象,要使用 Content Linking 组件,必须需要先创建 Content Linking List 文件。 Content Linking 组件正是通过读取这个文件来获得处理我们希望链接的所有页面的信息。
    2.2 浏览器性能组件
    Browser Capabilities Component——浏览器性能组件
      浏览器性能组件创建一个浏览器类型(Browser无效)对象用以向你的脚本描述客户端浏览器能力。
      一旦一个浏览器连接到Web服务器,浏览器会自动将一串用户代理HTTP报头(User Agent HTTP Header)传送到服务器。该报头为一ASCII字符串用以识别该浏览器及其版本号。浏览器类型(Browser无效)对象将该报头与Browsercap.ini文件中的条目进行比较。
      如果找到匹配的条目,浏览器类型(Browser无效)对象假设该浏览器具备Browsercap.ini文件中所描述的属性。
      如果对象没有在Browsercap.ini文件中找到与报头匹配的条目,浏览器类型(Browser无效)对象假设该浏览器具备默认浏览器的属性。如果没有匹配条目并且Browsercap.ini文件没有定义默认浏览器的各项设置,则浏览器类型(Browser无效)对象将该浏览器的各项属性值赋为“Unkown”。
      通过升级Browsercap.ini文件,你可以方便的把浏览器属性或者对新浏览器的描述加入到这个组件(稍候介绍如何升级Browsercap.ini文件)。
      Browsercap.dll 浏览器性能组件
    Browsercap.ini 一个用以描述浏览器属性的文本文件,该文件必须和Brwosercap.dll文件处于同一目录下

      语法

      Set Browser无效 = Server.CreateObject("MSWC.Browser无效")

      参数

      Browser无效——用Server.CreateObject语句创建的浏览器类型(Browser无效)对象的名字

     
      Browscap.ini文件

      你可以在Browscap.ini文件中描述任意多个浏览器的属性。你也可以设置一套默认属性,当浏览器发送的报头无法和Browscap.ini中的任何条目匹配时,浏览器类型(Brower无效)对象会假设该浏览器具备默认的属性。

      附录——浏览器属性列表
    属性名 描述
    ActiveXControls 指定浏览器是否支持ActiveX控件
    backgroundsounds 指定浏览器是否支持背景音乐
    beta 指定浏览器是否是测试版
    browser 指定浏览器的名字
    cdf 指定浏览器是否支持Web发布的频道解释定义(Channel Definition Format)
    小甜饼s 指定浏览器是否支持小甜饼s
    frames 指定浏览器是否支持帧显示
    Javaapplets 指定浏览器是否支持Java applets
    java脚本 指定浏览器是否支持Java脚本
    platform 指定浏览器运行所需的操作系统
    tables 指定浏览器是否支持表格
    vb脚本 指定浏览器是否支持vb脚本
    version 指定浏览器的版本

    注:以上解释内容为“指定浏览器是否支持”开头的属性,其属性值应为True/False,其余为字符串。
    2.3 Ad Rotator 组件
    Ad Rotator组件创建一个Ad Rotator对象,该对象在Web页上自动轮换显示广告图像。当用户每次打开或重新加载Web页时,Ad Rotator组件将根据在Rotator Schedule文件中指定的信息显示一个新广告。
      可以记录每个广告被多少个用户单击访问,方法是在Rotator Schedule文件中设置一个URL参数,将用户定向到重定向文件中。如果指定了此参数,那么当每次跳转到一个广告客户的URL时,都会在Web服务器的活动日志中作相应的记录。关于活动日志的详细信息,请参阅记录Web站点活动。

      文件名

      adrot.dll Ad Rotator组件。

      重定向文件 可选文件,用于实现重定向并允许Ad Rotator组件记录每个广告被多少个用户单击访问。

      Rotator Schedule文件文本文件,包含广告的显示计划和文件信息。此文件必须在Web服务器的某个虚拟路径上可用。
      
      语法

      Set AdRotator = Server.CreateObject("MSWC.AdRotator")

      参数

      AdRotator 指定AdRotator对象的名称,此对象通过调用Server.CreateObject创建。

      Border指定广告边框的大小。

      Clickable指定广告是否为超链接。

      TargetFrame 指定显示广告的框架的名称。

      方法

      GetAdvertisement从数据文件中获取下一个计划广告的详细说明并将其格式化为HTML格式。

      Rotator Schedule文件包含的Ad Rotator组件用于管理和显示各种广告图象的信息。在该文件中,用户可以指定广告的细节,例如广告的空间大小、使用的图象文件以及每个文件的显示时间所占百分比。

      Rotator Schedule文件由两部分组成。第一部分设置应用于轮换安排中所有广告图象的参数;第二部分指定每个单独广告的文件和位置信息以及应当接收的每个广告的显示时间所占百分比。这两部分由全是星号(*)的一行隔开。

      在第一部分中有四个全局参数,每个参数都由一个关键字和值组成。所有的参数都是可选的。如果用户未指定全局参数的值,则Ad Rotator将使用默认的值。在这种情况下,文件的第一行必须只有一个星号(*)。

     
      参数

      URL

      指定动态链接库(.dll)或执行重定向的应用程序(.asp)文件的路径。该路径必须是完整的(http://MyServer/MyDir/redirect.asp)或相对的虚拟目录(/MyDir/redirect.asp)。

      numWidth

      以像素为单位指定网页上广告的宽度。默认值是440个像素。

      numHeight

      以像素为单位指定网页上广告的高度。默认值是60个像素。

      numBorder

      以像素为单位指定广告四周超链接的边框宽度。默认值是1个像素。如果将该参数设置为0,将没有边框。

      adURL


      广告图象文件的位置。

      adHomePageURL

      广告主页的位置。如果广告客户没有主页,请在该行写上一个连字符(-),指出该广告没有链接。

      Text

      在浏览器不支持图形或关闭图象功能的情况下显示的替代文字。

      impressions

      从0到4,294,967,295的数,指出广告的相对权值。

        
      重定向文件是用户创建的文件。它通常包含用来解析由 AdRotator 对象发送的查询字符串的脚本并将用户重定向到与用户所单击的广告所相关的URL。

      用户也可以将脚本包含进重定向文件中,以便统计单击某一特定广告的用户的数目并将这一信息保存到服务器上的某一文件中。

      AdRotator 对象有下列属性:

      一.Border

      二.Clickable

      三.TargetFrame

      1.Border 属性允许用户指定显示广告时四周是否带边框。

      语法

      Border = size

      参数

      size

      指定显示的广告四周的边框宽度。其默认值在 Rotator Schedule 文件的文件头中设置。

      2.Clickable

      Clickable 属性允许用户指定是否将广告作为超链接显示。

      语法

      Clickable = value

      参数

      value

      指定广告是否为超链接。此参数可为下列值之一。默认值是TRUE。值意义:TRUE 将广告作为超链接显示。

      FALSE 将广告不作为超链接显示。

      3.目标框架

      TargetFrame 属性指定链接将被装入的目标框架。该属性完成的功能等价于 HTML 语句中的 TARGET 参数。

      语法

      TargetFrame = frame

      参数

      frame

      指定用来显示广告框架的名称。该参数也可以是一个 HTML 框架关键字, 例如 _TOP、_NEW、_CHILD、_SELF、_PARENT 或 _BLANK。默认值是 NO FRAME。

      AdRotator 对象只有一个方法.GetAdvertisement

      GetAdvertisement 方法从 Rotator Schedule 文件中获取下一个广告。每次运行脚本时,例如当用户打开或刷新一页时,此方法会获取下一个安排的广告。

      语法

      GetAdvertisement(rotationSchedulePath)

      参数

      rotationSchedulePath

      指定 Rotator Schedule 文件相对于虚拟目录的位置。例如,若物理路径为 C:\Inetpub\Wwwroot\Ads\Adrot.txt(其中Wwwroot 是 "/" 虚拟目录)则应指定路径 \Ads\Adrot.txt。

      返回值

      返回在当前页中显示广告的 HTML。

    2.4 Counters 组件
    Counter 组件创建一个可创建、存储、增长和检索任何数量的独立计数器的 Counters 对象。

      计数器是一个包含整数的持续值。可以使用 Counters 对象的 Get、Increment、Set 和 Remove 方法控制计数器。一旦您创建了计数器,它将一直持续下去直到被删除为止。

      计数器不会在一个事件比如访问一页时自动增加。您必须使用 Set 和 Increment 方法人工的设置或增长计数器。

      计数器不受作用域限制。一旦您创建了一个计数器,那么您的站点上的任何页都可以检索和控制它的值。例如,若您在一个名为 Page1.asp 的页上显示和增加一个叫做 hits 的计数器的值,而又在另一个叫做 Page2.asp 的页上增加 hits 的值,则两页将增加同一计数器。若您访问 Page1.asp 时,计数器的值增加到 34,则访问 Page2.asp 会将 hits 增加到 35。下一次访问 Page1.asp,hits 将增加到 36。

      所有计数器都存储在一个单独的名为 counters.txt 的文本文件中,它同 counters.dll 文件存储在同一目录下。

      文件名

      counters.dll Counters 组件。

      counters.txt 该文件在一个站点上存储所有独立的计数器。counters.txt 是一个 UTF8 编码文件。您可以在计数器名称中使用任何 Unicode 字符。

      语法

      将下列内容加入到 global.asa 文件中在您的服务器上可一次性创建 Counters 对象:
    <OBJECT
    RUNAT=Server
    SCOPE=Application
    ID=Counter
    PROGID="MSWC.Counters">
    </OBJECT>

      
      在您的站点上仅创建一个 Counters 对象。这一单个 Counters 对象可以创建任意数量的独立计数器。


      方法

      Get 返回计数器的值。

      Increment 计数器的值加一。

      Remove 从 counters.txt 文件中删除计数器。

      Set 将计数器的值设为一个特定的整数。

      Get方法

      Get 方法根据计数器的名称返回此计数器的当前值。若此计数器不存在,则该方法创建它并将其置为 0。

      语法

      Counters.Get(CounterName)

      参数

      CounterName

      包含计数器名称的字符串。

      Increment方法

      Increment 方法根据计数器的名称,将该计数器的值加 1,并返回计数器的新值。若计数器不存在,此方法将创建该计数器并将其值设为 1。

      语法

      Counters.Increment(CounterName)

      参数

      CounterName

      包含计数器值的字符串。

      
      Remove方法

      Remove 方法根据计数器的名称,从 Counters 对象和 counters.txt 文件中删除计数器。

      语法

      Counters.Remove(CounterName)

      参数

      CounterName

      包含计数器名称的字符串。

      Set方法

      Set 方法根据计数器的名称和一个整数参数,将计数器设置为该整数值,并返回此新值。若该计数器不存在,则 Counters.Set 创建计数器并将其值设为这一整数。

      要获取计数器的值,可使用 Counters.Get。要使计数器的值加一,可使用 Counters.Increment。

      语法

      Counters.Set(CounterName, int)

      参数

      CounterName

      包含计数器名称的字符串。

      int

      CounterName 的新的整数值。












    第三章 在ASP中使用Oracle数据库
    Oracle是世界上用得最多的数据库之一,活动服务器网页(ASP)是一种被广泛用于创建动态网页的功能强大的服务器端脚本语言。许多ASP开发人员一直在考虑,能否在开发互联网应用、电子商务网站、互联网管理系统时结合使用ASP和Oracle数据库?这个问题的答案是肯定的,我们还可以使用VB访问Oracle数据库
      Oracle Objects for OLE就是其中之一。Oracle Objects for OLE是Oracle开发的一个中间件,它允许使用微软的OLE标准的客户端应用程序访问Oracle的数据库。也许会有读者说,我们也可以使用ODBC访问Oracle的数据库。当然,可以使用ODBC访问Oracle数据库,但我认为,Oracle Objects for OLE比ODBC更安全,而且完全支持PL/SQL。PL/SQL是Oracle对SQL命令集的扩展,开发人员能够利用它对非结构化的SQL命令块进行流控制和逻辑设计。如果安装的是Oracle8i数据库,我相信你已经在使用Oracle Objects for OLE。
      另外,我们还需要了解Oracle针对Visual Basic开发的二个对象和一个接口:OraSession、OraDynaset对象和OraDatabase接口。OraSession对象管理应用程序的OraDatabase、OraConnection和OraDynaset,它是由ASP的CreateObject而不是Oracle Objects for OLE创建的一个对象。OraDatabase接口向Oracle数据库表示表现用户对话,并为SQL、PL/SQL的执行提供方法。它们每个都有一些属性和方法。例如,OraDynaset对象有BOF、EOF、Bookmark、Connection等属性以及AddNew、更新、删除、Edit、刷新、Clone等10个方法。
    3.1 开发环境和工具
      1)我使用了Oracle8i、IIS5.0、Windows2000专业版作为应用程序的开发和运行环境。

      2)在Oracle数据库中建立一个名字为MYTABLE1或类似的表。
    ID (无效: number) User Name(无效: varchar2) Phone(无效: varchar2) Email(无效: varchar2)
    100 Colin Tong 999-999-8888 colinjavail.com
    111 John White 888-888-8888 johnw@yahoo.com
    101 Don Wod 416-333-3344 donwod@test.com
    3.2数据的访问和存取

      1) Instantiate OO4O Object, OraSession and interface OraDatabase for connecting to ORACLE.

      1)初始化Oracle Objects for OLE、OraSession对象和OraDatabase接口,为连接ORACLE数据库作准备。

      首先,使用CreateObject创建OraSession对象,然后通过打开一个与Oracle的连接创建OraDatabase对象,如下所示:
    <%
    Set OraSession = CreateObject("OracleInProcServer.XOraSession")
    Set OraDatabase = OraSession.OpenDatabase("", _
    "username/password", Cint(0))
    %>
       “username”和“password”是你所使用的关系数据库的用户名和口令。

      2)创建OraDynaset对象执行SQL命令。我们可以使用CreateDynaset或DbCreateDynaset创建记录集。
    <%
    '执行 SQL
    Set OraDynaset = OraDatabase.DbCreateDynaset( _
    "select * from mytable1", cint(0))
    %>
      3)存取数据并删除创建的对象。
    <%
    Do While(OraDynaset.EOF = FALSE)
    Response.write(OraDynaset.Fields("ID"))
    Response.write(OraDynaset.Fields("UserName"))
    ... others ...
    ... ...
    OraDynaset.MoveNext
    Loop
    'remove OraSession
    Set OraSession = Nothing
    %>
    3.3 编辑数据记录

      我们将使用OraDynaset的方法实现对数据记录的编辑。

      1)使用SQL语句创建OraDynaset对象。
    <%
    '创建ID= fID的记录的OraDynaset对象。
    Set OraDynaset = OraDatabase.CreateDynaset(_
    "select * from MYTABLE1 where ID= "& fID, cint(0))
    %>
      fID是想插入更更新的记录的ID值。

      2)执行OraDynaset更新或添加数据记录。
    <%
    '使用Edit方法更新ID=fID记录的域。
    '或使用AddNew插入一个新记录
    OraDynaset.Edit
    OraDynaset.Fields("Phone").Value = fPhone
    OraDynaset.更新
    ' 删除创建的对话
    Set OraSession = Nothing
    %>
    3.4删除数据记录

      如果已经真正地理解了我们在上面讨论的一些方法(Edit、更新和AddNew),也许有的读者已经知道该如何在Oracle数据库中删除记录了。
    <%
    '删除所有符合上面条件的记录
    OraDynaset.删除
    %>
      在Oracle8i中搜索和更新数据记录的代码
      1)搜索
    <%
    'RetriveRecProc.asp -使用ASP的Oracle Objects for OLE更新数据记录
    %>
    <%
    '定义作为OLE对象的变量
    Dim OraSession
    Dim OraDatabase
    Dim OraDynaset
    '创建OraSession对象
    Set OraSession = CreateObject("OracleInProcServer.XOraSession")
    '通过打开Oracle数据库的一个连接创建OraDatabase对象
    '一定要使用自己的用户名和口令访问Oracle数据库
    Set OraDatabase = OraSession.OpenDatabase("", "user/password", _
    Cint(0))

    '创建OraDynaset对象执行SQL语句
    Set OraDynaset = OraDatabase.DbCreateDynaset(_
    "select * from mytable1", cint(0))
    %>
    <html><body>
    <H3>Retrieve All Records in MYTABLE1 Table ( in Oracle)
    Using oo4o</H3>
    <table border=1 ID="Table1">
    <%
    Do While(OraDynaset.EOF = FALSE)
    Response.Write("<tr><td>")
    Response.write(OraDynaset.Fields("ID"))
    Response.Write("</td><td>")
    Response.write(OraDynaset.Fields("UserName"))
    Response.Write("</td><td>")
    Response.write(OraDynaset.Fields("Phone"))
    Response.Write("</td><td>")
    Response.write(OraDynaset.Fields("Email"))
    Response.Write("</td></tr>")
    OraDynaset.MoveNext
    Loop

    '删除OraSession
    Set OraSession = Nothing
    %>
    </table>
    <a href="java脚本:window.history.go(-1)">
    Back previous Page</a> |
    <a href="index.html"> Back home Page</a>
    </body></html>
      2)更新
    <%
    '更新RecProc.asp -使用ASP的Oracle Objects for OLE更新数据记录
    %>
    <%
    '定义作为OLE对象的变量。
    Dim OraSession
    Dim OraDatabase
    Dim OraDynaset

    '从提交的表格中获取字段值
    fID = request.form("ID")
    fUserName = request.form("UserName")
    fPhone = request.form("Phone")
    fEmail = request.form("Email")

    '创建OraSession对象
    Set OraSession = CreateObject("OracleInProcServer.XOraSession")

    '通过打开Oracle数据库的一个连接创建OraDatabase对象
    Set OraDatabase = OraSession.OpenDatabase("", "user/password", _
    Cint(0))

    '创建ID= fID的记录的OraDynaset对象
    Set OraDynaset = OraDatabase.CreateDynaset(_
    "select * from MYTABLE1 where ID= "& fID, cint(0))
    '使用Edit方法更新ID=fID记录的字段
    Do While(OraDynaset.EOF = FALSE)
    OraDynaset.Edit
    OraDynaset.Fields("UserName").Value = fUserName
    OraDynaset.Fields("Phone").Value = fPhone
    OraDynaset.Fields("Email").Value = fEmail
    OraDynaset.更新
    OraDynaset.MoveNext
    Loop
    %>
    <html><body>
    <H3>更新 A Record in MYTABLE1 Table (Oracle) Using oo4o</H3>
    The record (ID=<%=fID%>) has been 更新d successfully!<br>
    You can view the result <a href="RetrieveAllRec.asp"> here</a>
    <p>
    <a href="java脚本:window.history.go(-1)"> Back previous Page</a>
    &bnsp;&bnsp;
    <a href="java脚本:window.history.go(-2)"> Back home Page</a>
    <%
    '删除OraSession对象
    Set OraSession = Nothing
    %>
    </body></html>
    至此,我们已经讨论了如何在ASP代码中使用Oracle Objects for OLE来处理Oracle数据库中的数据。
    3.5使用存储过程
      我们已经讨论了如何在ASP中访问Oracle数据库,所有的SQL语句都可以嵌入在ASP网页中。如果在ASP中使用存储过程,将更能够更有效地处理数据。我建议读者除在ASP中嵌入SQL语句外,还应当使用PL/SQL存储过程。在Oracle数据库中创建存储过程已经超出了本文章的范围,在这里就不再进行介绍了。

      ASP和Oracle数据库是二种比较流行的技术,都有相当广泛的用户群,如果能够有机地将二者结合起来,将能够给工作带来许多方便,希望这篇文章能够起到抛砖引玉的作用,使读者能够更好地探索将这二种技术结合使用的途径。






    第四章ASP安全与性能优化
    4.1 配置IIS4实现应用程序隔离
    如果不对IIS4进行应用程序的隔离,那么我们运行ASP程序时将可能发生奇怪的现象,两个应用程序,比如说聊天室,在不同的聊天室里的朋友竟可以相互对话,这就是因为没有进行应用程序隔离的缘故,因为两个聊天室共用了同一个Session和Application对象。所以混在一起了。
    隔离应用程序空间,一般来说有两种方法,一个就是采用多端口虚拟主机的办法隔离应用程序,在每个端口上开设一个WEB站点。这样每个应用程序占用了不同的端口。另一种方法是设置IIS4的应用程序启动点,把应用程序隔离开,现在主要介绍第二种方法,假设WWW服务的发行路径为C:\Inetpub\wwwroot,在这个目录下有一个叫realchat的目录,realchat主目录下有一个user的目录,里面有一个叫user_1的文件夹,这里需要运行一个独立的ASP应用程序。现需对user_1这个文件夹进行配置。为它创建应用程序启动点。
    配置的方法如下:运行Internet服务管理器,选中web站点,展开右边的那堆目录,realchat-$#@62;user-$#@62;user_1,选中user_1按右键选属性,选中“主目录”标签,在中间的位置有一个“应用程序设置”的标签,那个EDITBOX本来是灰色的,按一下EDITBOX旁的那个“创建”按建,在EDITBOX中输入user_1作为应用程序的标识,暂时不需要复选了"在不同的内存空间运行应用程序",最后保存设置,停止WEB服务,再重新启动服务,设置就生效了。
    对任何多个ASP程序均可以用此方法来进行应用程序隔离。
    4.2增强ASP程序性能
    性能是一个很重要的特征。你需要事先设计好性能指标,否则日后就要为此重新编写程序。就是说:要设想好怎样最佳化地执行ASP程序?
    1:在Web服务器上缓存经常使用的数据
      典型的情况是:ASP页面从后台存储中取回数据,然后以超文本标记语言(HTML)的形式形成结果。不管数据库的速度如何,从内存中取回数据要比从后台存储设备中快得多。从本地硬盘读取数据通常也非常快。所以,提高性能可以通过缓存服务器上的数据来实现,无论是将数据缓存在内存中,或者本地硬盘中。
      缓存是经典的“空间换时间”的折中方式。如果缓存得恰当,就可以看到显著的性能提升。为了让缓存有效,必须保证缓存数据是经常要重用的,而且也是计算起来繁琐的。装满陈旧数据的缓存是对内存的浪费。
      不经常改变的数据是缓存的较好对象,因为不需要随时考虑这些数据更新后的同步操作。组合框、参考表格、DHTML代码、扩展标记语言串、菜单以及站点配置变量(包括数据源名字DSNS,Internet协议地址IP以及Web路径)都是很好的缓存对象。注意:要缓存数据表达式而不是数据本身。如果一个ASP页面经常变化并且很费力去缓存(比如整个产品目录),就要考虑预产生HTML,而不是每次发生请求时再描述它。
    2:在Application或Session对象中缓存经常使用的数据
      ASP中的Application和Session对象是在内存中缓存数据的便利容器。你可以将数据赋值给Application和Session对象,这些数据在HTTP调用期间将一直保持在内存中。Session中的数据是? 一个用户服务的,Application中的数据是所有用户共享的。

      何时需要在Application和Session中装入数据?通常,当应用程序启动或者会话开始时,数据就被装入了。为了在这时装入数据,在Application OnStart()或者Session OnStart()中分别添加适当的代码。这些函数位于文件Global.asa中,如果原来不存在,就添加上。也可以在数据首次需要的时候调入,在ASP页面中添加代码,检查数据是否存在,如果没有发现,就调入它。这里有一个例子,它代表了被称为“lazy 执行ution”的经典性能处理技术:直到需要时,再去计算。例子如下:
    $#@60;%
    Function GetEmploymentStatusList
    Dim d
    d = Application("EmploymentStatusList")
    If d = "" Then
    FetchEmploymentStatusList function (not shown)
    fetches data from DB, returns an Array
    d = FetchEmploymentStatusList()
    Application("EmploymentStatusList") = d
    End If
    GetEmploymentStatusList = d
    End Function
    %$#@62;
    对于不同的数据,可以编写类似的函数代码。
      数据应该按什么格式保存?任何变量类型都可以,因为所有的脚本变量都是不同的。比如说,可以保存为字符串、整型或者数据。通常,将ADO记录集的内容存储到这些变量类型中一个。为了从ADO记录集中取出数据,需要手工地拷贝数据到VB脚本变量中,每次一个字段。使用任意一个ADO记录集的函数functions GetRows(),GetString() 或者 Save() (ADO 2.5)都非常得快速而且简单,这里有个函数,描述了如何使用GetRows()返回记录集数据的数组:
    Get Recordset, return as an Array
    Function FetchEmploymentStatusList
    Dim rs
    Set rs = CreateObject("ADODB.Recordset")
    rs.Open "select StatusName, StatusID from EmployeeStatus", _
    "dsn=employees;uid=sa;pwd=;"
    FetchEmploymentStatusList = rs.GetRows() " Return data as an Array
    rs.Close
    Set rs = Nothing
    End Function
    上述代码的一个更深的技巧是为列表缓存了HTML。下面是个简单的例子:
    Get Recordset, return as HTML Option list
    Function FetchEmploymentStatusList
    Dim rs, fldName, s
    Set rs = CreateObject("ADODB.Recordset")
    rs.Open "select StatusName, StatusID from EmployeeStatus", _
    "dsn=employees;uid=sa;pwd=;"
    s = "$#@60;select name=""EmploymentStatus"$#@62;" & vbCrLf
    Set fldName = rs.Fields("StatusName") ADO Field Binding
    Do Until rs.EOF
    Next line violates Dont Do String Concats,
    but its OK because we are building a cache
    s = s & " $#@60;option$#@62;" & fldName & "$#@60;/option$#@62;" & vbCrLf
    rs.MoveNext
    Loop
    s = s & "$#@60;/select$#@62;" & vbCrLf
    rs.Close
    Set rs = Nothing See Release Early
    FetchEmploymentStatusList = s Return data as a String
    End Function
    在合适的环境下,可以在Application或者Session中缓存ADO记录集本身,但是有2点提示:
    • ADO必须是自由线程标记的
    • 需要使用disconnected recordset方式
      如果不能保证上述2个条件,就不要缓存ADO记录集,因为这会产生很大的危险性。
      当在Application或Session中保存数据后,数据将一直保持,除非程序改变它、Session变量到期或者Web应用程序重新启动。如果数据需要更新,怎么办?可以调用只有管理员才能访问的ASP页面来更新数据,或者,通过函数周期性的自动更新数据。下面的例子中,与缓存数据一起保存了时钟标记,过一段时间后,就刷新数据。
    $#@60;%
    error handing not shown...
    Const 更新_INTERVAL = 300 刷新 interval, in seconds

    Function to return the employment status list
    Function GetEmploymentStatusList
    更新EmploymentStatus
    GetEmploymentStatusList = Application("EmploymentStatusList")
    End Function

    Periodically 更新 the cached data
    Sub 更新EmploymentStatusList
    Dim d, strLast更新
    strLast更新 = Application("Last更新")
    If (strLast更新 = "") Or _
    (更新_INTERVAL $#@60; DateDiff("s", strLast更新, Now)) Then

    Note: two or more calls might get in here. This is okay and will simply
    result in a few unnecessary fetches (there is a workaround for this)

    FetchEmploymentStatusList function (not shown)
    fetches data from DB, returns an Array
    d = FetchEmploymentStatusList()

    更新 the Application object. Use Application.Lock()
    to ensure consistent data
    Application.Lock
    Application("EmploymentStatusList") = d
    Application("Last更新") = CStr(Now)
    Application.Unlock
    End If
    End Sub
    3:在Web服务器磁盘上缓存数据和HTML页面
      有时候,有“许多”数据要在内存中缓存。“许多”是相对而言的,它取决于能消耗多少内存、缓存项目的数量以及取回数据的频度。任何情况下,如果需要在内存中缓存大量的数据,请考虑以text或者XML文件格式在Web服务器硬盘上做缓存。当然,也可以混合使用硬盘缓存数据以及内存缓存数据,从而达到最佳缓存。
      注意:当测试一个单一ASP页面的性能时,从磁盘取回数据不一定比从网络数据库中取回数据快,但是缓存减少了网络数据库的调用。在大规模调用时,这将明显地提高网络的吞吐能力。缓存一个费时的查询结果是非常有用的,比如对于一个复杂的存储过程,或者大量的结果数据。
      ASP和COM提供了几种建立基于磁盘缓冲配置的工具。ADO记录集的Save()和 Open()函数负责保存和调入磁盘上的记录集。另外还有一些组件:
    • 脚本ing.FileSystemObject 允许你创建、读取和写文件
    • MSXML,Microsoft XML 解析器随Internet Explorer而来,支持保存和装入XML文档
    • LookupTable对象(比如在MSN上使用)是从磁盘调入简单列表的很好选择。
      最后,考虑缓存磁盘数据的表达式,而不是数据本身。预处理的HTML可以存储为.htm或者.asp文件,链接直接指向它们。使用诸如XBuilder或者Microsoft SQL Server Internet发布类的商业工具,能够自动处理这些过程。而且,也可以在.asp文件中包含HTML程序片断。同样,也可使用FileSystemObject从磁盘上读取HTML文件,或者使用XML for early rendering来做这个工作。
    4:避免在Application或Session对象中缓存非轻快型组件
      在Application或Session对象中缓存数据是一个很好的方法,但是,缓存COM对象却有严重的缺陷。在Application或Session对象中缓存经常使用的COM对象这个工作是非常吸引人的,但是很不幸,许多COM对象,包括用Visual Basic 6.0或者以前版本编写的对象组件,当存储在Application或Session对象中后,都会产生严重的瓶颈问题。
      特别地,当组件编写得不是很轻巧时,就极可能产生瓶颈问题。一个轻型组件就是标记了ThreadingModel=Both的组件,其中合计了自由线程的排列(FTM),或者标记了ThreadingModel=Neutral(Neutral模式是Windows2000和COM+中的新特征)。下面的组件不是轻型的:
    • Free-threaded组件(除非被集合成FTM)
    • Apartment-threaded组件
    • Single-threaded组件
      Configured components不是轻型组件,除非它们是Neutral-threaded的。Apartment-threaded组件和其他非轻型组件在页范围内工作得很好,就是说,它们是在一个单一ASP页面中创建并释放的。
      如果缓存了非轻型组件,将会发生什么错误?在Session对象中缓存的非轻型组件将会“锁住”会话。ASP维护着一个响应请求的工作线程池,通常,新的请求被第一个可用的工作线程控制。如果一个会话被锁在一个线程中,那么请求就被迫等待到相关的线程变为可用。这里有一个类比:你前往一个超级市场,挑选了一些食品,并在3号付款台付款。从那以后,只要在那个超级市场买食品付款,你就会经常到3号付款台去,虽然其他的付款台人少些甚至没有人。
    5:不要在Application或Session对象中缓存数据库连接
      缓存ADO连接通常不是一个好的策略。如果一个连接对象被存储在Application对象中,并在所有的页面使用,那么所有页面将会争夺该连接的使用。如果存储在ASP Session对象中,那么将要为每一个用户都打开数据库连接。这将挫败连接池的使用意图,并且在Web服务器和数据库上都施加了不必要的高代价压力。
      为了替代缓存数据库连接,可以在使用ADO的每个ASP页面中创建并释放ADO对象。这将非常有效,因为IIS拥有内建的数据库连接池。更准确地说,IIS自动处理OLEDB和ODBC连接池,这将保证在每个页面创建并且释放连接的工作高效进行。
      由于连接的记录集存储了数据库连接的参考,所以,不要在Application或Session对象中缓存连接的记录集。然而,可以安全地缓存disconnected类型的记录集,它们并不保存相应数据库连接的参考。为了断开记录集,执行下面2步:
    Set rs = Server.CreateObject("ADODB.RecordSet")
    rs.Cursor本地 = adUseClient step 1

    Populate the recordset with data
    rs.Open strQuery, strProv

    Now disconnect the recordset from the data provider and data source
    rs.ActiveConnection = Nothing step 2




























    第五章 ASP实例设计开发在线考试系统
    5.1基本简介
      试题库与在线考试系统采用ASP、HTML、Frontpage2000/98、Java脚本、VB脚本、Java编程语言、图形编辑与数据库等工具,通过基于WEB服务器访问纯WEB页面,实现在线组卷与考试等各项相关的功能。
      它是专门用于试题(卷)录入、查询、修改、删除、组卷和参加在线考试的ASP应用程序。其最大的特点是开放性、方便性和灵活性。主要是指一般的用户不仅可以轻松地向题库添加、修改和查询试题(卷),而且还可以自动新增科目并建立相应的数据表;它还允许用户根据自己的需求,从现有的试题库中灵活地抽取各类试题,以组建适合于自身所需的试卷。而且,自测试卷的难易程度和形式以及各大题分数等都由用户根据需要确定。考生通过浏览器进行有效的身份验证登录后,输入正确的试卷编号,并要求在规定的时间内进行答题,当达到规定的时间后,系统将自动予以提交。一旦考生做完后便能立即看到预先记录在库中的标准答案和自己的平时成绩(正规考试试卷不得随意更改以及答案将不及时提供),并且其答案和分数将被记入库中以供审核和查阅,并作为成绩评估和试卷分析的历史数据;另外,还可完全由计算机自动按照"难度系数"灵活、随机的抽取试题库中的各类试题组成各种形式的试卷,其内容会随着库中试题的改变而改变,不妨把它称之为实时的互动的试卷。
      用户对象主要是大、中、小学及职业学校等单位的教师及学生和企事业单位的教育部门(因企事业单位每年要对员工进行素质、安全教育与技能等方面的培训及考试等)。
    5.2 运行环境与系统结构
      此应用程序可广泛运行于国际互联网即Internet,也可适用于内部的局域网。其运行要求和逻辑结构分别如下:
      客户端:Windows95/98,Internet Explorer(IE)等
      服务器端:Windows NT/Windows2000,Internet Information Server (IIS)4.0及其以上版本,IE等;或者Windows98,Personal Web Server(PWS),IE等。
      数据库:采用SQL Server,运行于服务器端。
    5.3 系统特点
      系统联为一体,界面整齐、美观,操作简单、方便。另外,支持按权限对系统进行操作,即不同类型的用户拥有相异的权限对题库执行不同的操作。主要是在首页通过两种不同的方式进入相异的操作界面,以确保整个数据库中数据的安全性及完整性。其主要特点体现在以下三个方面:
      (1) 自主设计数据库 ⑵ 自主调用数据库 ⑶ 自主管理数据库
      自主设计数据库是指用户能够根据自己的需要创建新科目数据库(即系统实现了自动建表的功能),让数据库真正成为用户自己的数据库。不过,只要库中已存在该科目名称及表名,则不予重建,这样就保证了数据的统一性;自主调用数据库即允许用户能自由地从数据库中抽取试题组成试卷,试卷中有几道大题和小题以及是否提供查看答案均由用户自行设置并选题。通常来说,一份高质量的试卷,需要用户反复推敲、比较和琢磨,用户就象进超市买东西一样能方便地把看中的取出来,也可反悔把不需要的退回去,并且在形成一份完整的试卷之前,允许任意调整该试题的次序。在组卷时,还可以多份试卷选取同一试题或同一知识点的试题,但严禁一套试卷中出现知识点相同(似)且难度一致的试题。不过,其最大的缺陷在于目前只实现了试卷中的客观题部分,即包括判断、单选和多选题。而且,还没有实现客观题部分和真正的多媒体试卷;自主管理数据库指一般用户具有添加、修改和检索数据的权力,实现数据库的可扩充性和开放性。而管理员则另具有删除数据的权力,从而达到了系统数据统一性和一致性的目的,具体情况请见系统演示。
    5.4 详细设计
      5.4.1试题(客观题部分)设计
      在以往的考试中,判断题常常是通过画" ╳ "," "来判断;而单选题往往在四个供选的答案A、B、C、D中选择唯一正确的答案;另外,多选题跟单选题在根本上没什么区别,只是供选的答案和标准答案多一些。因而,本系统中所涉及的单选题和多选题跟过去的大体相同,主要不同在于把判断题巧妙地转化为只有两个选项的单选题,并且假设多选题一般情况下也是最多提供六个备选答案,标准答案至少有一个。故各题型的样题设计如下:
    判断题-->如:重发器也叫中继器: (A)错 (B)对
    单选题-->如:HUB是指: (A)网桥 (B)集线器 (C)网关 (D)路由器
    多选题-->如; Internet上使用的网络协议是: (A)IPX/SPX兼容协议 (B)TCP/IP协议 (C)NetBEUI协议 (D)X.25协议 (E)ATM LAN仿真用户 (F)快速红外线协议

      5.4.2数据库设计
      5.4.2.1试题结构
      通常,每一类型的试题都应有一个表结构。但考虑到目前系统存贮空间已经不受物理空间的限制。因此,我们采用按科目而不按试题类型方案来建立数据表,更不把所有科目的全部试题集中在一起,只是每道客观题均有六个备选答案项,还有一个表用来记录各科目数据表的相关属性。这样,查询起来较方便,可能会节约时间,也不致于造成数据十分杂乱等。详细设计如下表所示:
    说明:
      1. 按科目(一般以1个学期为标准)分别定义各表,表名一律由中文名汉字拼音首字母构成。例如,软件工程---RJGC;计算机网络---JSJWL;小学二年级上期数学---XXENJSQSX

      2.字段名是指该字段的中文名

      3.字符标识一般由中文名拼音首字母构成,外键字段最好与主表对应字段同名

      4.若该字段为字符型,则对应的长度栏填最大允许长度,若为固定长度则加'定'字

      5.若该字段可以为空,则对应的NULL栏填Y,否则不填

      6.若该字段为主键,则对应的主键栏填Y,否则不填
      
      科目数据信息表
    字段名 字符标识 类型 长度 NULL 主键 说明
    科目中文详细名称 KMMC CHAR 50 以中文为准,例如"计算机网络"
    科目表名 KMBM CHAR 50 Y 一律由上面中文名拼音首字母构成,如"JSJWL"
    录 入 者 LRZ CHAR 15 默认为录入员登入帐号
    录入日期 LR_DATE DATE 10 默认为录入时的系统日期
    备 注 MEMO CHAR 50 Y
    5.4.2.2试卷结构
      试卷一般包括客观题(判断题、单选题或多选题)和主观题(填空题、短文字题或长文字题),即一套试卷包括若干大题,每道大题包含若干小题。但是,本系统的试卷目前只涉及客观题部分。故大题数暂定为最多3道,小题数总和若干,而且,在此表中只存贮该科目试卷相应的试题编号,其试题内容则在调用时到相应科目中查询获得。
      5.4.2.3用户、留言信息结构
      A、超级用户:在此系统中有且仅有一个,即系统管理员。他具有一般用户所没有的至高无上的权力,即具有删除用户、留言、试题以及试卷等信息的权力。它不需注册,在数据库没有它的任何相关信息,但可由管理员自己更改用户名和密码。确保万一数据泄密而造成系统的危害。
      B、一般用户:主要是指学校的教师及学生和企事业单位的教育部门等。另外,所有用户可能会对我们的系统发表意见或相互之间答疑。
      5.4.2.4考生答案成绩表结构
    实际考试日期可能因某种原因推迟考试而与试卷表中的考试日期有所不同。因而,此表应与用户、试卷及试题库等多表相关联,关系比较复杂。
      5.4.3功能模块详细设计
      下面,按照录入试题-出卷-进行考试等流程就各个模块分别进行详细讨论,具体情况见系统源程序及演示。考虑到数据的保密与安全问题,凡进入系统的用户,必须先注册,然后通过验证才能进入。否则,进入"SORRY"页面。
      5.4.3.1录入模块
      许可的用户根据自身教学目的和要求,可以向库中添加各种类型且符合要求(对不符合的将给出提示和警告,并且不予保存!)的试题和试卷以及各自的意见与疑难问题等。一旦添加成功,只有管理员才能删除。
      ①试题录入
      首先,用户选择试题所属科目。若下拉菜单中没有该科目,则点击右边的新增科目,即进入这一页面,只要输入新增科目详细名称(一般以一个学期修完为标准)和表名(最好由汉语拼音首字母组成),即可由系统根据已设定好的字段自动建立新的科目试题表。返回、刷新一次页面,即可看到新增的科目名称。而且,在本系统中其它需要选择科目的地方也会自动更新。
      其次,每道试题有类型、难度系数、选自书籍及章节、试题内容与答案和标准答案等栏目。用户一一输入完(对于该试题不需要的答案项,则默认为"不填"),按"提交"后,即可看到预览效果。如果输入不合法,或者该科题库中已有该试题编号和内容等,则系统给出相应的提示或警告,以待更正。
      ②试卷录入
      此子模块包括两个部分,即标识试卷的基本信息录入和手工组卷部分。其基本信息有试卷编号、标题、套数、难度、科目名称、考试性质与日期等,而卷中试题将通过后面的手工组卷模块予以实现。对于用户输入的不符合系统要求的数据,系统仍旧给出提示或警告。
      ③用户留言
      凡使用此系统的用户可能对我们的工作有许多良好的建议和意见,或者有一些疑难问题需要大家共同探讨的话,可以在此提出。
    5.4.3.2查询模块
      系统中的所有用户均可检索试题、试卷、用户及留言等信息。只是试题检索界面较复杂,但它已实现了多种条件的组合查询,非常适合于数量繁大的试题库。而后三者相对来说比较简单,"默认"或"空白"的情况下,则按该表中的系统默认的字段显示其全部信息。使用起来比较灵活、方便。
      5.4.3.3修改模块
      用户除了只修改自己的部分资料(包括用户帐号、密码和E-Mail)外,还可修改试题及试卷,而留言则不许修改。只要用户选择科目和输入编号,即可进行修改。不过,对于各表中的主键不准修改,避免了造成系统中的数据混乱,或者覆盖其它有用数据的现象。如果用户执行了非法操作,则必须重新操作。
      5.4.3.4组卷模块
      在组卷过程中,我们肯定会遇到有许多题目是关于同一个教学内容的,这里称之为关于同一考核点的试题。因此,在组装一份试卷时,对于同一考核点的试题只能出一道题。这里设计一种快速选题算法,该算法只需经一次比较,便可判定是否已选过该考核点的试题,且又可以有针对性地重点选取某个考核点的试题。即每一道题都设有一个相关码,对于同一章、同一节、同一考核点的题,则相关码相同,显然,前面章节的相关码都要小于后面章节的相关码。故在组卷时,同一试卷中不允许出现相关码相同的试题。所以,在选题过程中每选出一题,就要与已经选出的题的相关码逐一进行比较,若该题的相关码与已选各题的相关码均不相同,则可将该题加入到试卷中,否则,放弃该题,重新进行选题。
      下面,在只考虑最佳情况下,即每次选出的题都恰好是尚未选过的,每选一道题就要与已选出的各题逐一比较,假设已选出了M题,再选下一题时,则需比较M次,不妨设一份试卷的总题数为N,在最佳情况下,则总的比较次数为:
       0,1, 2,…N-2,N-1
      即时间复杂度为O(N),这样,就可保证下面算法中选择出来的试题编号都合法。
    基本算法:
    {定义参数,获得整套试卷的共同限制参数,即包括输入必要条件得到必要参数和 输入任选条件得到任选参数}

    必要参数组合= A1 AND A2 ~~AND An;任选参数组合= B1 OR B2 ~~OR Bn;
    大题数dts =3 '默认为3道大题;小题数xts=0 '默认为50道小题;
    IF 无判断题 THEN dts=dts - 1 END IF '开始计算大题数
    IF 无单选题 THEN dts=dts - 1 END IF
    IF 无多选题 THEN dts=dts - 1 END IF

      开始扫描相应科目的试题库,获得临时所有符合条件的试题预览,接着开始手工细选试题以生成试卷或计算机自动组卷。
    IF 符合必要参数组合 THEN
     SELCECT 任选参数
      B1:显示符合必要参数+B1的试题编号及内容
      B2:显示符合必要参数+B2的试题编号及内容
        ┋ ┋ ┋
      Bn:显示符合必要参数+Bn的试题编号及内容
     END SELCECT
    END IF
    IF dts>= 1 THEN
     IF 试题编号合法THEN xts=xts + 1
     ELSE 请输入合法的试题编号!
     END IF
     IF dts>xts THEN xts必须大于或等于dts!
     ELSE
      IF 某已存在的题型中小题数为0 THEN 该题型至少要有1道试题!
      END IF
     END IF
     IF 判断题存在且分数<= 0 OR分数>100 THEN 请修改!
     ELSE TOTALFEN= TOTALFEN +PDTF
     END IF
     IF 单选题存在且分数<= 0 OR分数>100 THEN 请修改!
     ELSE TOTALFEN= TOTALFEN +DXTF
     END IF
     IF 多选题存在且分数<= 0 OR分数>100 THEN 请修改!
     ELSE TOTALFEN= TOTALFEN +TSTF
     END IF
     IF TOTALFEN <= 0 OR TOTALFEN > 100 THEN
      总分在1---100分之内!
     END IF
    ELSE 试卷大题数不得为0!
     IF testtime<= 0 OR testtime>= 4 (hour) THEN
      考试时间必须满足0 <testtime< 4 (hour)!
     END IF
    END IF
    IF所有数据均合法 THEN 则将该试卷的相关信息存盘
    END IF

      主要有下面两个子模块:
      其一:手工组卷模块
      用户提交相关限制条件,由系统根据这些条件先从大的范围内调出试题,稍后再手工通过复选按钮细选以生成自己所需的试卷,即利用现有的试题库,可编制出多份试卷。在组卷时,可以对所选的每一试题进行增删,顺序进行调整,并可自行规定各大(小)题分数和试卷的考试时间(默认值前已述及)。总之,能作出用户完全满意的试卷,以供在线考试或测试使用。
      其好处关键在于---选题随机性强、成卷速度较快、试卷质量高;知识考核点分布均匀,且内容覆盖面容易控制。例如,期中考试时,只考前一半内容时,只要选取章节码小于或等于某个指定的值,则一定不会出现后一半内容的试题。
      其二:计算机自动卷模块
      完全由系统自动按照"易-中-难"顺序和根据用户选择的信息,灵活、随机的抽取试题库中的各类试题组成试卷,试卷内容会随着库中试题的改变而改变,试卷库中没有保存试卷的基本信息及相应的试题编号,不妨称之为活动的互动的试卷。不过,其试卷质量不高,难易程度把握不当,知识考核点分布不均,一般只作在线练习使用。
      5.4.3.5进入在线考场模块
      进入在线考场是本系统非常重要的部分之一。因为一个系统如果涉及到现实的话,就必须考虑得十分周到、完善。考生登录后,只要输入已编辑好的试卷编号,就可以调出其试卷进行在线考试或测试,其答题信息通过单、复选按钮选择答案来反映。为了防止考生多次提交试卷和规范考场纪律,采取自愿交卷和到了规定的时间自动收卷两者有机结合的方式、限制考试时间和期限以及禁用鼠标等办法予以实现。但真正的无人监视的考试好象不能用软件实现,而且其安全性在系统设计中也很重要。因此,在设计过程中注意了以下几个问题:
      1、只有考生自己才能参加考试!2、考试时间到了将自动交卷!
      3、限制提交次数,暂只提供一次机会!4、禁止用户联网作弊!
    上图为此模块程序设计详细流程图
      5.4.3.6在线练习模块
      计算机自动组卷模块组成的互动的试卷(卷库中没有保存此类试卷的任何信息!)是通过单复选按钮来反映用户的做题信息。它主要用于平时的在线练习等,让用户了解自身的不足,并有针对性地进行复习和训练。因此,用户做完后,只要点击"查看答案",就可以与相应试题的标准答案对比,以便及时反馈情况,而没有提供成绩判定与分析和时间限制等。
      5.4.3.7成绩分析与试卷评估模块
      考生每参加一次考试,系统根据已有的标准答案很快得出其分数,再根据不同的分数段给出相异的评语。一方面与其它同科考生进行横向对比,得出各个考生之间的差别;另一方面,也通过用户一段时期内参加同科考试的成绩来做纵向比较,用以说明其掌握该科目内容的实际程度,以便做出相应的决定。另外,管理员先给出一套完整试卷的预先评估,然后由系统自动根据同一试卷编号的所有用户成绩给出其实际的评估,并且都有一个难度等级,把两次评估进行比较得出该卷的难易程度以及更详细的评估情况。
      5.4.3.8删除模块
      在整个系统中,只有系统管理员具有此权限。管理员通过复选按钮选择要删除的用户、留言、试卷及科目,而对于数量较大的试题库则通过输入或选择条件,就可达到删除那些过时的无用的试题,当然,对于那些恶意破坏系统的用户,管理员有权删除他,以示惩罚。这样就可确保数据库不至于十分庞大和其安全性。
    5.5 ADO--ActiveX Data Object操作数据库的几个步骤
      第一步 数据库数据来源设定。若要访问数据库,需在"控制面板"中的"ODBC Data Sources",建立数据库名称(选择Users DSN),点击"Add"按钮,选定数据库所用的驱动程序和文件等。
      第二步 使用"Server.CreateObject"建立连接的对象,并使用"Open"打开待访问的数据库。set adocon=Server.CreateObject("ADODB.Connection");adocon.Open "zxtest"
      第三步 设定SQL命令,使用"执行"命令,即可开始执行访问数据库的动作。
    sqlstr ="select * from jsjwl where stbh like 'PD' order by stbh ASC"
    set rs = adocon.执行(sqlstr) ′adocon为第二步所设定的对象名称

      第四步 使用Recordset对象的命令,显示结果,其中rs为第三步所定义。
    rs.fields.count:记录的字段数;
    rs(i).name:第i(指针)个字段名,i由0算起到rs.fields.count-1;
    rs(i):读取第i(指针)个字段的记录,i由0算起到rs.fields.count-1;
    rs("字段名"):读取指定的字段的记录;rs.eof:是否已指定最末条;
    rs.movenext:将指针移到下一条;rs.moveprev:将指针移到上一条;
    rs.movefirst:将指针移到第一条;rs.movelast:将指针移到最末条;

      第五步 使用后关闭数据库:
    rs.close;adocon.close

    5.6数据的安全与保密
      由于此系统的特殊性,数据的安全与保密显得尤为重要。保密性是指用户在网上的所有信息应有一定的保密度,不同类型的用户之间的内容是互相保密的。安全性是指用户参加一次活动是一个安全的过程,对于所有用户的动作,服务器都加以跟踪。为了确保其安全与保密性,一要确保考生不能联网作弊;二要在试卷上实时加以监控;三要在时间上加以严格的控制等。主要通过下列两种途径予以实现:
      其一,凡进入在线考试的用户,都要通过用户身份验证(见下图)才能进入。而且,不同用户具有不同的操作权限,支持按权限进行操作,确保数据的公共性与私有性。不允许用户执行非法的操作,防止用户无意或有意的破坏。
      其二,禁止用户查看所有试卷的源文件及拷贝功能,方法有二:
      1、禁止使用鼠标右键等功能;
      2、试卷库中的试卷将以无下拉菜单及工具栏等的页面方式呈现在浏览者面前。
    5.7 源程序列表
      由于源代码繁多,限于篇幅,无法一一列举,现只公布部分代码,具体以系统实物为准。下面是录入试题.asp文件:
    <脚本 language="VB脚本">
    <!-- 'Written by HeKai 2001
    Function datacheck()'确保前台输入数据合法
     dim errflag, msg
     errflag = True
     if Len(Trim(luru.xzsj.value)) = 0 Then
      focusto(1); errflag = false; msg="请输入 '选自书籍名称'"
     ElseIf Len(Trim(luru.stnr.value)) = 0 Then
      focusto(9); errflag = false; msg=" '试题内容' 呢"
     ElseIf Len(Trim(luru.A.value)) = 0 Then
      focusto(10); errflag = false; msg=" '答案_A' 呢"
       ┋ ┋ ┋
     ElseIf Len(Trim(luru.F.value)) = 0 Then
      focusto(15); errflag = false; msg="请还原成默认值"
     End if
     If (errflag = false) then
      msg = msg & vbCRLF
      MsgBox msg, 64, "提示"
      Exit Function
     End if
      datacheck = errflag; luru.Submit
    End Function

    Sub focusto(x)'将鼠标定位在出错处
    文档.luru.elements(x).focus()
    End Sub
    --></脚本>

      以下是录入试题.inc文件:
    <脚本 Language="VB脚本" RunAt="Server">
     Function check_Pass()'检查库中是否已有此数据
      kmxxmc = Request.Form("kmxxmc")
      stbh = Request.Form("stbh") stnr = Request.Form("stnr")
      SQLstr = "select * from " & kmxxmc & " where stbh=" & "'" & stbh & "'"
      SQLstr = SQLstr & " or tmnr=" & "'" & stnr & "'"
      set adocon=Server.CreateObject("ADODB.Connection")
      adocon.Open "zxtest"
      set sa1=adocon.执行(SQLstr)
      If sa1.EOF Then
       check_Pass = False
      Else
       check_Pass = True
      End If
      sa1.Close adocon.Close
    End Function

    Sub Add_Comment()'开始插入数据并显示出来
     Dim kmxxmc,xzsj,tmlx,nycd,jxyq,stbh,stnr
     Dim A,B,C,D,E,F,bzda,lrz,Picstr,SQLstr,lr_date,zhang,jie
     kmxxmc = Request.Form("kmxxmc") xzsj = Request.Form("xzsj")
      ┋ ┋ ┋
     bzda = Request.Form("bzda") zhang = Request.form("zhang")
     set adocon=Server.CreateObject("ADODB.Connection")
     adocon.Open "zxtest"
     SQLstr = "insert into " & kmxxmc & " (xzsj,tmlx,tmnd,jxyq,stbh,tmnr,  bxda_a,"
     SQLstr = SQLstr & ",jie,lrz) values (" & "'" & xzsj & "'," & "'" & tmlx & "',"
      ┋ ┋ ┋
     SQLstr = SQLstr & "'," & "'" & date & "'," & "'" & zhang & "'," & "'" & jie & "'," SQLstr = SQLstr & "'" & lrz & "')"
     set sa1 = adocon.执行(SQLstr)
     Picstr="<img src='/images/hekai.jpg'>"
     Response.Write "恭喜!此为<i> " & lrz & "</i> 刚才录入的试题"
     Response.Write Picstr & " 试题编号:" & stbh
     Response.Write "试题内容:" & stnr & "<br>"
     Response.Write "答案_A:" & A & "<br>"
      ┋ ┋ ┋
     adocon.Close
    End Sub

    Sub Register()
     If check_Pass() Then '如果库中已有的话,则给出提示信息
      Show_Warning()
     Else '否则添加进去
      Add_Comment()
     End If
    End Sub

    Sub Show_Warning()'给出提示信息的函数
     Response.Write("<p>")
     Response.Write("<center>很抱歉<p>")
     Response.Write("库中已有此试题编号或试题内容,请返回前页修改!")
     Response.Write("</center>")
     Response.Write("Made by hekai himself in 2001")
    End Sub
    </脚本>

    此为"检索试题"的程序代码:
    <脚本 Language="VB脚本" RunAt="Server">
    Function adjust_sql(adj_str)
     '目的---转换查询字符串中的特殊字符至SQL指令
     Dim final_str, i 'WRITE BY HEKAI2001
     adj_str = Trim(adj_str)
     final_str = "" '每次从传进来的字符串中取出一个字符,并判断是否为下述三个字符之一: DOS的Filter符号"|"、左中括号"["以及单引号"'"
     If Len(adj_str) > 0 Then
      For i = 1 To Len(adj_str)
       Select Case Mid(adj_str, i, 1)
         Case "[": final_str = final_str & "[[]"
         Case "|": final_str = final_str & "[{-}]"
         Case "'": final_str = final_str & "[&-()"
         Case Else: '以上皆非则什么事都不做!
         final_str = final_str & Mid(adj_str, i, 1)
       End Select
      Next
     End If
     adjust_sql = final_str
    End Function

    Sub Output_sh iti()
     Dim kmxxmc,xzsj,stbh,zhang,jie,tmlx,nycd,jxyq,lrz,stnr,cond_count, Picstr
     Dim SQLstr,mf,zhangfw,jiefw,stbhfw,nycdfw,lr_datefw,lr_date
     '记录指定条件的栏位总数
     cond_count = 10; mf = "%"
     Picstr="<img src='/images/hk.gif'>"
     '取得表单栏位内容
     kmxxmc = Request.Form("kmxxmc")
     stbh = Request.Form("stbh")
      ┋ ┋ ┋
     stnr = Request.Form("stnr")
     '调整SQL指令中的特定字元
     kmxxmc = adjust_sql(kmxxmc)
     stbh = adjust_sql(stbh)
      ┋ ┋ ┋
     stnr = adjust_sql(stnr)
     If Len(xzsj) = 0 Then cond_count = cond_count - 1
      If Len(stbh) = 0 Then cond_count = cond_count - 1
      ┋ ┋ ┋
      If Len(stnr) = 0 Then cond_count = cond_count - 1
       SQLstr = "select * from " & kmxxmc & " where "
      If Len(stbh) > 0 Then
       SQLstr = SQLstr & " stbh " & stbhfw & "'" & stbh & "'"
      If cond_count > 1 Then
       SQLstr = SQLstr & " and "
       cond_count = cond_count - 1
      End If
     End If
      ┋ ┋ ┋
     If Len(stnr) > 0 Then
      SQLstr = SQLstr & " tmnr like " & "'" & mf & stnr & mf & "'"
      If cond_count > 1 Then
       SQLstr = SQLstr & " and "
       cond_count = cond_count - 1
      End If
     End If
     SQLstr = SQLstr & " order by lr_date DESC "
     set adocon=Server.CreateObject("ADODB.Connection")
     adocon.Open "zxtest"
     set sa1 = adocon.执行(SQLstr)
     If sa1.EOF Then
      Response.Write "<br><center><h1>"
      Response.Write "Sorry!<p>"
      Response.Write "没有找到试题,"
      esponse.Write "请重试一次!</center><p>"
      Response.Write "<hr></h1>"
     Else
      i = 0
      Response.Write "<h2>"
      Response.Write "符合条件的试题相关内容如下:"
      Response.Write "</h2>"
      While Not sa1.EOF
       i = i + 1
       Response.Write "第 <i>" & i & "</i>题 题编号:<i>" & sa1("stbh") & "</i><br>"
       Response.Write "试题内容:" & sa1("tmnr") & "<br>"
        ┋ ┋ ┋
      Response.Write "答案A:" & sa1("bxda_a") & "<br>"
      sa1.MoveNext
      WEnd
      adocon.Close
     End If
    End Sub
    </脚本>

    <% '"检索试卷"的查询方式源代码
     mf="%"
     select case request("findfs")
      case "sjbh"
       sqlstr="SELECT * FROM tbsjxx WHERE " & " sjbh LIKE"
       sqlstr=sqlstr & "'" & mf & request("findfsz") & mf & "'order by ksrq DESC"
       ┋ ┋ ┋
      case "lr_date"
       sqlstr="SELECT * FROM tbsjxx WHERE " & " lr_date LIKE"
       sqlstr=sqlstr & "'" & mf & request("findfsz") & mf & "'order by ksrq DESC"
      case else
       sqlstr="SELECT * FROM tbsjxx order by ksrq DESC"
    end select %>

      下面是考试的时间自动控制程序(便于演示只设了60秒钟,实际应用应以系统调出试卷的考试时间为准。
    <脚本 language=Java脚本>
    <!-- Write by HEKAI for TestTimeContorl
    var timerID = null;var timerRunning = false
    var stardate = new Date();var startime = gettotalsecond(stardate)
    var totaltime = 60; var lasttime;var facetime
    function Stepclock(){
    // hk made by himself
    if(timerRunning)
    clearTimeout(timerID)
    timerRunning = false }
    function startclock(){
    Stepclock();showtime() }
    function gettotalsecond(getdate){
    var hours = getdate.getHours()
    var minutes = getdate.getMinutes();var seconds = getdate.getSeconds()
    var gettotalsecond = seconds + minutes * 60 + hours * 3600
    return(gettotalsecond) }
    function showtime(){
    var now = new Date();var tim执行ue = gettotalsecond(now)
    文档.clock.face.value = tim执行ue - startime
    facetime = 文档.clock.face.value;lasttime = totaltime - facetime
    文档.clock.sytime.value = lasttime
    timerID = setTimeout("showtime()",1000)
    timerRunning = true
    if (lasttime == 20){
    for(i=1;i<=3;i++){
    alert('考试时间只剩下最后20秒!')}}
    if (lasttime == 0){
    for(i=1;i<=5;i++){
    alert('时间完毕!请迅速交卷!!')}}
    if (lasttime == -10){
    for(i=1;i<=10;i++){
    alert('考试时间超过10秒,关闭此窗口!')}}
    }//-->
    </脚本>





    结束语
    此系统通过多次细致的测试及鉴定,证明系统完全具有可行性与可扩充性,但是系统还有待于进一步升级,并将实现试卷的主观题部分和多媒体试卷。因此,仍有大量的工作需要开展。若有不详或不妥之处,请您提出良好的意见与建议。















    参考文献
    ASP程序设计教程 作者: 张景峰 苏英如 金桂兰 出版社: 中国水利水电出版社 出版日期:2003-7-1ISBN: 7-5084-1541-8
    ASP与相关数据库技术高级指南 作者: 宋颜浩 费文华 出版社:中国水利水电出版社 出版日期:2002-4-1ISBN: 7508410130
    精通 ASP.NET 程序设计 作者: 高清和 出版社: 中国铁道出版社 出版日期:2001-12-1ISBN: 7113044301
    ASP.NET编程实例与技巧集粹 作者: 肖建 出版社: 北京希望电子出版社 出版日期:2003-5-1ISBN: 7-89498-146-X
  • 2005-05-02 17:54:55