补充3:ASP编程
Microsoft公司的ASP(Active Server Pages)是服务器端的脚本编写环境,可以创建和运行动态的、可以交互的Web服务器端应用程序,是实现网络数据库发布的、容易使用的开发工具。使用ASP可以方便地使用ADO对象,结合ActiveX组件、脚本命令和HTML语言,可以制作出交互式的网页和应用程序。
9.1 ASP概述
ASP扩展了标准的HTML,ASP文件可以包含在服务器端运行的脚本,根据脚本执行的不同结果向客户端输出不同的HTML页面。在ASP中使用内置对象,可以从用户浏览器表单取得检索信息,经过ASP处理后,生成响应后的HTML页面,发送后显示在请求信息响应的用户浏览器中。ASP可以和几个服务器的ActiveX组件捆绑在一起,访问数据库、访问文件系统或传送E-mail。
9.1.3 ASP运行环境
1,安装IIS 5.O
如果操作系统是Windows 2000 Server或者是Windows 2000 Advanced Server的话,IIS 5.0已经是默认安装上的。如果是Windows 2000 Professional,则需要安装IIS 5.0。从操作系统“控制面板”中找到并双击“添加/删除程序”,单击“添加/删除Windows组件”,选择“Internet信息服务(IIS)”,然后选择详细信息,如图9-1所示。

图9-1 安装IIS 5.0
选中“World Wide Web服务器”,这就是需要安装的Web服务器,如图9—2所示。

图9-2 选择World Wide Web服务器单击两次“确定”以后,放入Windows 2000的安装盘,出现安装界面,进行安装。最后点击“完成”按钮,完成安装。
安装完毕后,可以测试一下是否安装成功。打开浏览器,在浏览器的地址栏中输入HTTP://localhost或者http://127.0.0.1,如果安装成功的话,将会出现欢迎界面,如图9-3所示。

图9-3测试IIS 5.0的安装
进入IIS的管理界面可以在“控制面板”的“管理工具”中打开“Internet服务管理器”。IIS的管理界面如图9-4所示。

图9-4 IIS 5.0的管理界面现在IIS 5.0的环境就建立好了,这个时候其实也已经建立了ASP的运行环境。
2.配置IIS 5.O
如图9-3所示,在浏览器中输入http://localhost后,自动打开一个页面文件,这个文件其实是某一个目录下的一个文件。http://localhost取的是网站的根目录,这个目录对应本地的一个目录,这个目录是可以改变的。首先打开IIS5.0管理界面,右击“默认Web站点”,选择“属性”菜单项,在出现的对话框中选择“主目录”选项卡,如图9-5。

图9-5配置主目录
当前网站的本地路径是“c:\inetpub\wwwroot”,一般,操作系统安装在哪个盘,该路径就在哪个盘上。可以单击“浏览”按钮将网站指到本地的任何路径。下面有几个选项,一般同时程序时选择“目录浏览” 选项。该选项的意义是:如果IIS找不到默认打开的文件,就将该目录下的所有文件列出。
单击“文档”卡,设置默认打开的文件,如图9-6。

图9-6配置默认打开的文档
可以看到,当浏览网站时,IIS 5.0自动在网站的主目录下寻找这些文件,从前到后依次寻找,如果找到了,就显示该文件。如果找不到这几个文件,判断是否可以目录浏览,如果可以目录浏览,则将该目录下所有文件列出来。
首先在C盘根目录下建立一个名为“asproot”的文件夹,将网站的主目录设置到该目录下,并将“目录浏览”打开,如图9-7所示。

图9-7设置主目录在C:\asproot目录下新建一个文件“test.txt”,依然可以在浏览器地址栏中输入 http://localhost看到该文件。这时可以在IIS 5.0中看到该文件,首先刷新IIS 5.0,如图9-8所示。

图9-8 查看文件右击“默认Web站点”选择“浏览” 选项卡,IIS5.0自动打开浏览器,如图9-9。

图9-9目录浏览
从图中可以看到,浏览器地址栏的地址也是http://localhost,将ASP文件放在该目录下就可以执行ASP文件了。
3.测试ASP运行环境第一个程序依然是经典的“Hello World”的例子,让程序输出字符串“你好,中国!我的祖国”,如程序9-01.asp所示。
例9.1测试ASP运行环境,程序名称:9-01.asp
<html>
<body>
<% Response.Write "你好,中国!我的祖国!"
%>
</body>
</html>
利用Windows自带的记事本编辑上面的文件。把文件命名为9-01.asp,并保存到c:\asproot目录下。在浏览器中输入http://localhost,可以看到程序列表,如图9-10所示。

图9-10程序列表单击该ASP文件,如果程序没有输入错误的话,就可以看到输出的字符串,如图9-11所示。

图9-11测试ASP运行环境
9.1.4 ASP运行模型
浏览器从Web服务器上请求.asp文件时,ASP脚本开始运行。然后Web服务器调用ASP引擎,ASP引擎会全面读取请求的文件,执行所有脚本命令,并将Web页传送给浏览器。
由于脚本在服务器上而不是在客户端运行,传送到浏览器上的Web页是在Web服务器上生成的。所以不必担心浏览器能否处理脚本,也就是说ASP程序的运行是与浏览器无关的。由于只有脚本的结果返回到浏览器,所以服务器端的脚本不易被复制,用户看不到 ASP页的程序源代码。
9.1.5 ASP的工作原理
先看看Web Server是如何处理对静态页面的请求的:
(1)当一个用户从浏览器网址栏中输入所要浏览的Web页面的地址并按“Enter”键后,这个页面请求便通过浏览器送到对应的Web服务器。
(2)服务器接到这个请求并根据.htm或者.html的扩展名判断出被请求的页面是一个 HTML文件。
(3)服务器从目前内存或硬盘上读取相对的HTML文件并将其传回给用户端浏览器。
(4)浏览器将接收到的HTML程序解释运行并将结果提供给用户。
这是一个简化后的例子,实际情况可能会复杂一些。但这个例子基本上概括了静态页面的处理流程。
如图9-12所示为ASP的运行过程。
图9-12 ASP运行过程下面我们来说明ASP动态页面的处理过程:
用户向Web服务器传送一个.asp的页面请求。
服务器在接到请求后根据其.asp的扩展名判断出用户要浏览的是一个ASP文件。
服务器从内存或硬盘上读取相对的ASP文件。
这个ASP程序被传送给服务器上的asp.dll并被编译运行,产生标准HTML文件。
(5)产生的HTML文件作为用户请求的响应传回给用户端浏览器并由浏览器解释运行。
由此看来,Web服务器处理ASP页面比处理静态HTML页面多了一个程序编译的步骤,而对于用户端来说,浏览HTML页面与浏览ASP页面几乎没有任何区别。因为传回客户端的程序都是标准的HTML文件,因此完全没有必要担心用户的浏览器是否支持你编写的ASP持续——ASP适合于任何浏览器。
需要注意的是,上面ASP的处理过程也是经过简化的,实际应用中可能还会涉及到诸如FORM消息提交、ASP页面的动态产生、数据库操作等一系列复杂的问题。此外,Web服务器并不是在接到每一个ASP页面请求后都会重新编译该页面,如果某个页面再次接收到和前面完全相同的请求时,服务器会直接去缓冲区中读取编译的结果,而不是重新运行。
为什么ASP可以为用户提供动态的Web页面了,其原因正是 ASP程序需要首先在服务器上编译运行,而每次运行会因为一些变量或条件的不同而产生不同的结果,这就是不同的HTML文件。这样,对于用户来说,这个Web页面总是在不断变化。
9.1.6 ASP页的创建
ASP文件是以.asp为扩展名的文本文件,这个文件可以是文本、HTML代码和ASP脚本命令的任意组合。
创建.asp文件非常容易。如果要在HTML文件中添加脚本,只需将该文件的扩展名.htm或.html替换为.asp就可以了。要使.asp文件可用于Web用户,可以将这个新文件保存在 Web站点上的目录中。使用浏览器察看该文件时,可以看到ASP处理并返回了HTML页面。现在我们就使用在HTML文件中添加脚本的方法创建一个.asp文件。
脚本是一系列的命令和指令,它可以指示Web服务器执行操作,可以在变量中存储用户名,在返回到浏览器的页面中显示用户名或将用户名存储在数据库中等等。脚本命令通过定界符与文本区别开来。ASP使用定界符<%和%>括入脚本命令。用户可以在定界符中括入任何命令,只要这些命令对正在使用的脚本语言有效。
下面的这个例子展示了包含脚本命令的一个简单的HTML页。
例9.2在一个HTML页上显示该页被访问的时间,文件名为9-02.asp。
<html>
<body>
This paqe was last refreshed on <%=now %>
</body>
</html>
VBScript函数Now返回当前的日期和时间。Web服务器处理该页时,会使用当前的日期和时间替换<%=Now%>并且将该页返回到浏览器:

定界符括入的命令被称为主脚本命令。这些命令被主脚本语言处理。在脚本定界符中使用的任何命令都必须对主脚本语言有效。默认情况下,主脚本语言是VBScript。
在ASP定界符中可以包含任何在主脚本语言中合法的语句、表达式、过程或操作符。在VBScript和其他脚本语言中,语句是语法完整的单元,该单元表达某项活动、声明或定义。下面的条件语句If..Then...Else是一条常见的VBScript语句。
例9.3根据访问网页的时间返回相应的问候语。文件名为9-03.asp
<%
if time>=#12:00:00 AM# And time<#12:00:00 PM# Then
Greeting="Good Morning!"
else
Greeting="Hello!"
end if
%>
<%=Greeting
%>
这条语句将值“Good Moming!”或值“Hello!”存储在变量greeting中。<%=Greeting%>命令将当前的变量值发送到浏览器中。
这样,在(Web服务器所在时区的)正午12点前浏览该脚本的用户将看到:Good
Morning!在正午12点或以后浏览此脚本的用户将看到:Hello!

9.1.7 ASP的指令
ASP为用户提供了脚本语言以外的指令,这是一些输出指令和处理指令。
ASP的输出指令<%=expression%>显示表达式的值。例如,输出表达式<%=sport%>可以将文字climbing(sport变量的当前值)传送到浏览器。
ASP处理指令<%@keyword%>为ASP提供处理.asp文件所需的信息。例如,下面的指令将VBScript设为该页的主脚本语言:
<%@LANGUAGE=VBScript%>
处理指令必须出现在.asp文件的第一行。不要将处理指令放在包含#include语句的文件中。必须在at标记(@)和关键字之间加入一个空格。处理指令有下列关键字:
·LANGUAGE关键字:设置页的脚本语言。
·CODEPAGE关键字:设置页的代码页(字符编码)。
·LCID关键字:设置页的现场标识符。
·TRANSACTION关键字:指定将在事务处理环境下运行的页。
· ENABLESESSIONSTATE关键字:指定ASP页是否使用会话状态。
可以在单个指令中包含多个关键字;关键字/值对之间必须由空格分开。不要在等号(=)左右加入空格。下面的例子中设置了脚本语言和代码页:
<%@LANGUAGE=JScript CODEPAGE=932%>
例9.4 下面是一个典型的在同一,asp 文件中使用两种脚本语言的例子,
<HTML>
<BODY>
<TABLE>
<%Call Callme%>
</TABLE>
<%Call ViewDate%>
</BODY>
</HTML>
//VBScript脚本
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
Sub Callme
Response.Write "<TR><TD>Call</TD><TD>Me</TD></TR>"
End Sub
</SCRIPT>
//JavaScript脚本
<SCRIPT LANGUAGE=JavaScript RUNAT=Server>
function ViewDate()
{
 var x
 x=new Date()
 Response.Write(x.toString())
}
</SCRIPT> 
< % %>,符号是标准的 ASP 定界符,而,< SCRIPT>< /SCRIPT>,之间的就是脚本语言。 ASP 不同于脚本语言,它有自己特定的语法,所有的 ASP 命令都必须包含在 < % 和 %> 之内,如,< % test=“English” %>,ASP 通过包含在 < % 和 %> 中的表达式将执行结果输出到客户浏览器。
9.2 ASP的语句结构
9.2.1 选择结构
1.If...Then...Else 语句
(1)第一种是单分支格式,
If 条件 Then [语句块]
End If
(2) 第二种是双分支格式
I f 条件 Then
[语句块]
[Else]
[语句] End If
(3) 第三种语法格式为:
If 条件1 Then
[语句块1]
[else If 条件2 Then
语句块2]
……
[Else
语句块n ]
End If
例9.5   
<html>
<head>
<title>ifrespond.asp</title>
</head>
<body>
<% fname=request.querystring("Firstname")
lname=request.querystring("Lastname")
  If fname="George" and lname="Washington" then %>
  Hi.You must be the first president!
<% else %>
Hi!Nice to Meet You
<%end if %>
</body>
</html>
例9.6
<%
fname=lcase(request.querystring("Firstname"))
lname=lcase(request.querystring("Lastname"))
If fname="george" and lname="washington" then %>
Hi.You must be the first president!<p>
 <% elseif fname="ronald" and lname="reagan" then %>
Hi.You must be the actor president!<p>
 <% elseIf fname="jimmy" and lname="carter" then %>
Hi.You must be the peanut farmer president!<p>
 <% elseIf fname="naoko" or fname="charles" then %>
Hi.Your name reminds me of someone,but I am not sure who! <p>
 <% else %>
Hi!Nice to Meet You
<% end if %>
例9.7
<html>
<body>
<FONT COLOR="Green">
<% If Time < #12:00:00# And Time >= #00:00:00# Then %>
早上好,今天天气不赖啊 !
<% ElseIf Time < #19:00:00# And Time >= #12:00:00# Then %>
下午好 !
<% Else %>
哈喽 ! 今晚你有没有去 IRC 聊天 !
<% End If %>
</body>
</html>
2.Select Case语句
Select Case语句很适合多重条件判断。它的书写格式为:
Select case 表达式
Case 表达式结果1
[语句块1]
[Case 表达式结果2
语句块2]
……
[Case else
语句块n]
End Select
在这种结构中,只有一个用于判断的表达式,根据此表达式的不同计算结果,执行不同的语句块。
例9.8
<%
fname=lcase(request.querystring("Firstname"))
lname=lcase(request.querystring("Lastname"))
name=fname+lname
Select case name
case "georgewashington"
   response.write "Hi.You must be the first president!<p>"
case "ronaldreagan"
response.write "Hi.You must be the actor president!<p>"
case "jimmycarter"
response.write "Hi.You must be the peanut farmer president!<p>"
case "naokocharles"
response.write "Hi.Your name reminds me of someone,but I am not sure who!<p>"
case else
response.write "Hi!Nice to Meet You"
End Select
%>
9.2.2循环结构
1.当型循环结构
(1) Do while...Loop 语句
Do while,.,Loop的语法格式如下:
Do while 条件语句
[Exit Do] '用于在特定条件下退出循环
[语句]
Loop
(2)Do..,Loop While
Do..,Loop While的语法格式如下:
Do
语句
[Exit Do] '用于在特定条件下退出循环
[语句]
Loop While 条件
2.直到型循环结构:
Do Until,.,Loop
Do Until,.,Loop的语法格式如下:
Do Until 条件语句
[Eixt Do] '用于在特定条件下退出循环
[语句]
Loop
Do..,Loop Until
Do..,Loop Until的语法格式如下:
Do
语句
[Eixt Do] '用于在特定条件下退出循环
[语句]
Loop Until 条件
例9.9
<html>
<head>
<title>DoLoop.asp</title>
</head>
<body>
<p> 请将今年到本月为止的每个月份的销售结算记录填写在本页之上。<P>
<%
counter=1
thismonth=month(now( ))
Do while counter<thismonth+1
response.write " " & counter & " 月份,"
response.write "______________________________" & "<BR><br>"
If counter>13 then
exit do
end if
counter = counter+1
Loop
%>
<hr>
</body>
</html>
3.For…Next语句
For…Next语句的语法格式如下:
For 计数器=初值 To 终值 [Step步长]
[语句体]
[Exit For] '用于在特定条件下退出循环
[语句体]
Next [计数器]
此语法格式中使用了以下几个参数:
计数器:用于统计循环次数的变量,该变量为数值型变量。
初值:用于设置循环变量的初始取值,为数值型变量。
终值:用于设置循环变量的最后取值,为数值型变量。
步长:用于决定循环变量每次增加的数值,步长为数值型变量。一般默认值为1,此时省略了步长部分。若初值大于终值,步长应设为负值;若初值小于终值,步长应设为正值。
例9.10
<% Sub DoMyProc50Times()
dim x
For x = 1 To 50
MyProc
Next
End Sub
%>
例9.11
<% for i=1 to 6%>
<p><center><img src="smile.gif" width="32" height="32" alt="晚上好"></p>
<% next %>
4.For Each…Next语句该语句对集合中的每个元素进行一次循环,直到集合中无更多元素时,执行Next下面的语句。其语法格式为:
For Each 集合中元素 in 集合
[语句]
[Exit For]
[语句]
Next [元素]
例9.12
<%
For Each i in d
Request.querystring("hobby")
Response.Write i & "<BR>"
Next
%>
9.3 ASP的内置对象
ASP提供了可在脚本中使用的内置对象,这些对象使用户更容易收集通过浏览器请求发送的信息、响应浏览器以及存储用户信息,从而使对象开发者摆脱了很多繁琐的工作。
ASP提供了5大内置对象:Application对象、Request对象、Response对象、Server对象和Session对象。
9.3.1 Request对象可使用Request对象访问任何基于HTTP请求传递的信息,包括从HTML表格用Post方法或Get方法传递的参数、Cookie和用户认证。Request对象使用户能够访问客户端发送给服务器的二进制数据。Request对象的语法如下:
Request[.集合|属性|方法](变量)
在这里我们将挑选一些常用的对象语法进行分析。
1.Form
Form集合通过使用POST方法的表格检索邮送到HTTP请求正文中的表格元素的值。
语法格式如下:
Request.Form(element){(index)|.count}
参数说明:
· element:指定集合要检索的表格元素的名称。
· index:可选参数,使用该参数可以访问某参数中多个值中的一个。它可以是1到Request.Form(parameter).Count之间的任意整数。
· Count:集合中元素的个数。
例9.13 本例将示范如何利用Request对象的Form属性来取得用户在表单中填写的信息。文件名为9-13.asp和test9-13.htm。
test9-13.htm内容如下:
<html>
<body bgcolor="#FFFFFF">
<form method="post" action="9-13.asp">
姓名,<input type="text" name="yourname"><br>
性别,<select name="gender">
<option>男</option>
<option>女</option>
</select> <br>
留言,<textarea name="message">你好!
注意多行文本的处理</textarea> <br>
爱好(按住Ctrl键可多选),
<select name="hobby" multiple size="4">
<option>电脑</option>
<option>购物</option>
<option>电影</option>
<option>读书</option>
</select> <br>
<input type="submit" name="Submit" value="提交">
<input type="reset" name="Submit2" value="Reset">
</form>
</body>
</html>
9-13.asp内容如下:
<%@ Language=VBScript %>
<%
Option Explicit
Response.Expires=0
Dim StrName,StrGender,StrM,StrMsg
'Trim函数用来除首尾空格
StrName = Trim(Request.Form("yourname"))
StrGender = Trim(Request.Form("gender"))
StrM = Trim(Request.Form("message"))
StrMsg = Replace(StrM,vbcrlf,"<Br>" & vbcrlf)
' vbcrlf相当于回车符和换行符的组合。至于Replace函数,其作用就是将字符串StrM中的vbcrlf替换为"<Br>" & vbcrlf。
%>
<HTML><BODY>
姓名,<%= StrName%><Br><Br>
性别,<%= StrGender%><Br><Br>
留言,<Br><Br>
<%= StrM%><Br><Br>
<%= StrMsg%><Br><Br>
实际上,"提交"按钮的值也被传递,<Br>
<%= Request.Form("Submit")%><Br><Br>
<% '先把上面看懂,有兴趣再看看如何读取多个选项
Response.Write "共选择爱好项数:" & Request.Form("hobby").Count & "<Br>"
Dim I
For I = 1 to Request.Form("hobby").Count
Response.Write Request.Form("hobby")(I) & "<Br>"
Next
%>
</BODY>
</HTML>
本例的运行结果如图9-13所示。

图9.13例9.13运行结果
2.QueryString
在Web页面上,客户端的信息传送除了使用form之外,还有一种很常见的方式,就是使用Querystring。
QueryString集合检索HTTP查询字符串中变量的值,HTTP查询字符串由问号(?)后的值指定。如:
<A HREF=”example.asp?string=this is a sample">string sample</A>
生成值为“this is a sample”的变量名字符串。通过发送表格或由用户在其浏览器的地址框中键入查询也可以生成查询字符串。
语法格式如下:
Request.QueryString(variable)[(index)I.Count]
QueryString集合可以以名称检索QUERY_STRING变量。Request.QueryString(参数)的值是出现在QUERY_STRING中所有参数的值的数组。通过调用quest.QueryString(parameter).Count可以确定参数有多少个值。
例9.14本例示范如何通过Request对象的QueeryString数据集合来获取用户数据。文件名为9-14.asp和test9-14.htm。
test9-14.htm内容如下:
<html>
<body bgcolor="#FFFFFF">
<form method="get" action="9-14.asp">
英文姓名,<input type="text" name="Ename"> <br>
中文姓名,<input type="text" name="Cname"><br>
性别,<select name="gender">
<option>男</option>
<option>女</option>
</select> <br>
<input type="submit" name="Submit" value="提交">
<input type="reset" name="Submit2" value="Reset">
</form>
</body>
</html>
9-14.asp内容如下:
<%@ Language=VBScript %>
<%
Option Explicit
Response.Expires=0
Dim StrCname,StrEname,StrGender
'Trim函数用来删除首尾空格
StrEname = Trim(Request.QueryString("Ename"))
StrCname = Trim(Request.QueryString("Cname"))
StrGender = Trim(Request.QueryString("gender"))
%>
<HTML>
<BODY>
英文姓名,<%= StrEname%><Br><Br>
中文姓名,<%= StrCname%><Br><Br>
性别,<%= StrGender%><Br><Br>
看看提交的字符串,<Br>
<%= Request.ServerVariables("Query_String")%>
</BODY>
</HTML>
本例的运行结果如图9.14所示。
 
图9.14例9.14运行结果例9.15处理相应单一值的Query字段。
这里的链接中包含了一个Query字段“choice”。文件名为9-15.asp和test9-15.htm。
test9-15.htm内容如下:
<html>
<body>
<p><font size="5">您需要的服务是:</font></p>
<p><a href="9-15.asp?choice=1">硬件服务</a></p>
<p><a href="9-15.asp?choice=2">软件服务</a></p>
<p><a href="9-15.asp?choice=3">其它服务</a> </p>
</body>
</html>
9-15.asp内容如下:
<html>
<body>
<% select case request.QueryString("choice")
case "1"
response.Write("你选择了硬件服务")
case "2"
response.Write("你选择了软件服务")
case "3"
response.Write("你选择了其它服务")
end select
%>
</body>
</html>
当用户在页面中单击任意一个链接时,该链接相应的Query字段就被提交给服务器,服务器根据保存在Request.Querystring(“choice”)中的值判断出用户的选择,并做出正确的响应。运行结果如图9-15所示。
 
图9.15例9.15运行结果
上例中,Query字段的值不包含空格或其他特殊字符。如果情况特殊,例如说需要传递的字符串是“I am mickey”,又该如何处理呢?这时,就必须使用我们前面讲到的 Server.URLEncode方法了(对传递的地址进行编码),例如:
这样,传递到服务器的字段值就被转换为“I+am+mickey”了,可以直接用<%Request,Querystring%>查看它的结果。但是,如果使用Request.Querystring(”choice”)查看的话,所看到的会是“I am mickey”,这是因为这里面保存的是经过解析的字段值,也就是我们真正需要的显示方式。
例9.16 验证表格输入。验证方法一是将信息提交到web服务器之前,先将用户信息进行验证;验证方法二是创建一个向自身传递信息的表格。此例验证“age”中是否为数字,文件名为9-16-1.asp和9-16-2.asp。
9-16-1.asp内容如下:
<SCRIPT LANGUAGE="VBScript">
Sub btnEnter_OnClick
Dim TheForm
Set TheForm = Document.MyForm
If IsNumeric(TheForm.Age.Value) Then
TheForm.submit
Else
Msgbox "Please enter a numerical age."
End if
End Sub
</SCRIPT>
<html>
<head>
<title>test</title>
<body>
<FORM METHOD= "POST" NAME= MyForm ACTION="9-16-1.asp" >
Name,<INPUT TYPE="text" NAME="Name" >
Age,<INPUT TYPE="text" NAME="Age" >
<INPUT TYPE="button" NAME="btnEnter" VALUE="Enter">
</FORM>
</body>
</html>
9-16-2.asp内容如下:
<% If Isnumeric(Request.QueryString("Age")) then %>
<p>Hello,your age is <%=Request.QueryString("age")%>
<%Else %>
<p>Please enter a numerical age.
<%End If %>
<html>
<title>test</title>
<body>
<FORM METHOD="GET" ACTION="9-16-2.asp" >
Name,<INPUT TYPE="text" NAME="Name" >
Age,<INPUT TYPE="text" NAME="Age" >
<INPUT TYPE="submit" VALUE="Enter">
</FORM>
</body>
</html>

图9.16例9-16-2运行结果
3.Cookies
cookie其实就是一个标签,当用户访问一个需要惟一标识用户地址的Web站点时,它会在用户的硬盘上留下一个标记,下一次你访问同一个站点时,站点的页面会查找这个标记。每个Web站点都有自己的标记,标记的内容可以随时读取,但只能由该站点的页面完成。每个站点的Cookie与其他所有站点的Cookie存在同一文件夹中的不同文件内(可以在 Windows的目录下的Cookie文件夹中找到它们)。一个Cookie就是一个惟一标识客户的标记,Cookie可以包含在一个对话期或几个对话期之间某个Web站点的所有页面共享的信息,使用Cookie还可以在页面之间交换信息。Request提供的Cookies集合允许用户检索在 HTTP请求中发送的cookie的值。这项功能经常被使用在要求认证客户密码以及电子公告板、Web聊天室等ASP程序中。
语法格式如下:
Request.Cookies(cookie){(key)|.attribute}
参数说明:
· cookie:指定要检索其值的cookie。
· Key:可选参数,用于从cookie字典中检索子关键字的值。
· Attribute:指定cookie自身的有关信息。如:HasKeys只读,指定cookie是否包含关键字。
例9.17 cookie应用实例。
文件名为9-17.asp。
<%
nickname=request.form("nick")
response.cookies("nick")=nickname
'用response对象将用户名写入Cookie之中
response.write "欢迎"&request.cookies("nick") & "光临小站!"
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
<title>cookie</title>
<meta name="GENERATOR" content="MicrosoftFrontPage3.0">
</head>
<body>
<form method="POST" action="9-17.asp">
<p>
<input type="text" name="nick" size="20">
<input type="submit" value="发送" name="B1">
<input type="reset" value="重填" name="B2">
</p></form>
</body>
</html>
本例的运行结果如图9.17所示。

图9.17例9.17运行结果
4.ServerVirables
大家都知道在浏览器中浏览网页的时候使用的传输协议是HTTP,在HTTP的标题文件中会记录一些客户端的信息,如客户的IP地址等等,有时服务器端需要根据不同的客户端信息做出不同的反映,这时候就需要用ServerVables集合获取所需信息。语法格式为:
Request.ServerVariables(服务器环境变量)
由于服务器环境变量较多,在此仅将一些常用的变量在表9.1中列出。
表9.1
服务器环境变量
描述
ALL_HTTP
客户端发送的所有HTTP标题文件
CONTENT_LENGTH
客户端发出内容的长度
CONTENT_TYPE
内容的数据类型。如:“text/html”。同附加信息的查询一起使用,如 HTTP查询GET、POST和PUT
LOCAL_ADDR
返回接受请求的服务器地址。如果在绑定多个IP地址的多宿主机器上查找请求所使用的地址时,这条变量非常重要用
LOGON_USER
户登录Windows NT的账号
QUERY_STRING
查询HTTP请求中问号(?)后的信息
REMOTE_ADDR
发出请求的远程主机(client)的IP地址
REMOTE_HOST
发出请求的主机(client)名称。如果服务器无此信息,它将设置为空的 REMOTE_ADDR变量
REQUEST_METHOD
该方法用于提出请求。相当于用于HTTP的GET、HEAD、POST等等
SERVER_NAME
出现在自引用URL中的服务器主机名、DNS化名或IP地址
SERVER_PORT
发送请求的端口号
我们可以使用以下脚本打印出所有的服务器环境变量。
例9.18
文件名为9-18.asp。
<HTML>
<BODY>
<%
Response.Write "运行ASP文件的路径," & _
Request.ServerVariables("Script_Name") & "<Br>"
Response.Write "返回content的数据长度," & _
Request.ServerVariables("Content_Length") & "<Br>"
Response.Write "返回客户的IP地址," & _
Request.ServerVariables("Remote_Addr") & "<Br>"
Response.Write "浏览器名," & _
Request.ServerVariables("HTTP_USER_AGENT") & "<Br>"
Response.Write "返回主页实际物理路径," &_
Request.ServerVariables("APPL_PHYSICAL_PATH") & "<Br>"
%>
<table colspan=8 cellpadding=5 border=0>
<tr>
<td align=CENTER bgcolor="#800000" width="109">
<font style="ARIAL NARROW" color="#ffffff" size="2">环境变量名</font></td>
<td align=CENTER width=459 bgcolor="#800000">
<font style="ARIAL NARROW" color="#ffffff" size="2">内容</font></td>
</tr>
<tr>
<td bgcolor="f7efde" align=CENTER> <font style="ARIAL NARROW" size="2">
result1
</font></td>
<td bgcolor="f7efde" align=CENTER> <font style="ARIAL NARROW" size="2">
result2
</font></td></tr>
</table>
</BODY>
</HTML>

图9.18例9.18运行结果
9.3.2 Response对象
Response对象是用来控制发送给用户的信息,包括直接发送信息给浏览器、重定向浏览器到另一个URL或设置Cookie的值。语法格式如下:
Response.collection|property|method
1.属性
Buffer属性指示是否缓冲页输出。 当缓冲页输出时,只有当前页的所有服务器脚本处理完毕或者调用了Flush或End方法后,服务器才将响应发送给客户端浏览器,服务器将输出发送给客户端浏览器后就不能再设置Buffer属性。因此应该在.asp文件的第一行调用Response.Buffer。
Charset属性将字符集名称附加到Response对象中content-type标题的后面。对于不包含Response.Charset属性的ASP页,content-type标题将为content-type:text/html。我们可以在.asp文件中指定content-type标题,如<%Response.Charset=”gb2312")%>,将产生以下结果:content-type:text/html;Charset=gb2312。
ContentType属性指定服务器响应的HTTP内容类型。如果未指定ContemType,默认为text/HTML。
Expires属性指定了在浏览器上缓冲存储的页距过期还有多少时间。如果用户在某个页过期之前又回到此页,就会显示缓冲区中的页面。如果设置response.expires=0,则可使缓存的页面立即过期。
ExpiresAbsolute属性指定缓存于浏览器中的页面的确切到期日期和时间。在未到期之前,若用户返回到该页,该缓存中的页面就显示。如果未指定时间,该主页在当天午夜到期。如果未指定日期,则该主页在脚本运行当天的指定时间到期。如下示例指定页面在2005年12月10日上午9点00分30秒到期。
<%Response.ExpiresAbsolute=#Dec 12,2005 9:OO:30#%>
2.方法
Clear方法清除缓冲区中的所有HTML输出。但Clear方法只清除响应正文而不清除响应标题。可以用该方法处理错误情况。但是如果没有将Response.Buffer设置为 TRUE,则该方法将导致运行时错误。
End方法使Web服务器停止处理脚本并返回当前结果。文件中剩余的内容将不被处理。如果response.Buffer已设置为TRUE,则调用Response.End将缓冲输出。
Flush方法立即发送缓冲区中的输出。如果没有将Response.Buffer设置为TRUE,则该方法将导致运行时错误。
Redirect方法使浏览器立即重定向到程序指定的URL。程序员可以根据客户的不同响应,为不同的客户指定不同的页面或根据不同的情况指定不同的页面。一旦使用了Redirect方法,任何在页中显式设置的响应正文内容都将被忽略。然而,此方法不向客户端发送该页设置的其他HTTP标题,将产生一个将重定向URL作为链接包含的自动响应正文。 Redirect方法发送下列显式标题,其中URL是传递给该方法的值。如:
<%Response.redirect(“www.chinabyte.com”)%>
Write方法是我们平时最常用的方法之一,它是将指定的字符串写到当前的HTTP输出。如
< % Response.write(“欢迎进入我的个人天地!") %>
3.集合
Response对象只有一个集合:Cookie。
Cookies集合设置cookie的值。若指定的cookie不存在,则创建它。若存在,则设置新的值并且将旧值删去。语法格式为:
Response.cookies(cookie){(key)|.attribute}=value
这里的cookie是指定cookie的名称。而如果指定了key,则该cookie就是一个字典。 attribute指定cookie自身的有关信息。attribute参数可以是下列之一:
·Domain:若被指定,则cookie将被发送到对该域的请求中去。
·Expires:指定cookie的过期日期。为了在会话结束后将cookie存储在客户端磁盘上,必须设置该日期。若此项属性的设置未超过当前日期,则在任务结束后cookie将到期。
·HasKeys:指定cookie是否包含关键字。
·Path:若被指定,则cookie将只发送到对该路径的请求中。如果未设置该属性,则使用应用程序的路径。
例9.19本例将示范Request对象和Response对象中的Cookies属性的结合使用。
文件名为9-19.asp。
<%
Response.Cookies("aspCookies")("name")="fancy"
Response.Cookies("aspCookies")("sex")="girl"
Response.Cookies("aspCoolies")("Email")="kongqy@tom.com"
%>
<html>
<body>
<% For Each Cookiesname in Request.Cookies
If Request.cookies(Cookiesname).haskeys Then
For Each keyCookies In Request.Cookies(Cookiesname)
Response.Write "[DIR]" & keyCookies & "的内容是:"
Response.Write Request.Cookies(Cookiesname)(keyCookies) & "<br>"
Next
else
Response.Write Cookiesname & "的内容是:" & _
Request.Cookies(Cookiesname) & "<br>"
end if
next
%>
</body>
</html>
本例的运行结果如图9.19所示。

图9.19例9.19运行结果
例9.20文件名为9-20a.asp和9-20b.asp。
9-20a.asp内容如下:
<html>
<body>
<p>
<%
Dim user
Dim flag
Dim pwd
Dim say
Response.buffer=true ' 开启缓冲页面功能
Response.ContentType="text/HTML"
Response.Charset="gb2312"
user=Request.Form("username")
pwd=Request.Form("password")
say=Request.QueryString("say")
%>
</p>
<p><form method="POST" action="9-20b.asp"><p>
用户名,<input type="text" name="username" size="12"><br>
口 令,<input type="password" name="password" size="12"><br>
<input type="submit" value=" 提交 " name="B1">
<input type="reset" value=" 取消 " name="B2"></p> </form>
<% If say=1 then
Response.Write "欢迎书生大驾光临 !"
End If
If say>1 then
Response.Write "欢迎再次光临书生的 ASP 网站 !"
End If
If user="Adm" and pwd="shusheng" Then
Response.Expires=1 ' 设置该页面在浏览器的缓冲中存储1 分钟后过期。
flag=1
Else If user="guest" and pwd="guest" Then
Response.Expires=0 ' 使缓存的页面立即过期。
Response.Clear ' 清空存储在缓存中的页面
flag=2
Else If user="vip" and pwd="vip" Then
Response.Write "欢迎 VIP 光临书生的 ASP 网站"
flag=3
Else
flag=0
Response.end ' 立即停止脚本处理,并将缓存中的页面输出
End If
end if
end if
Response.write "<p><a href='9-20b.asp?flag=" & flag & "'>动态网站设计十八般武艺--ASP篇(7)实践练习</a></p>"
'将变量 flag 的值传送给 9-20b.asp
%>
<p> 动态网站设计十八般武艺 --ASP 篇 (7) 实践练习</p>
</body>
</html>
9-20b.asp内容如下:
<html>
<body>
<%
Dim say
say=Request.QueryString("flag")
Select case say
case "1"
Response.Redirect "9-20a.asp?say=1"
case "2"
Response.Redirect "9-20a.asp?say=2"
case "3"
Response.Redirect "9-20a.asp?say=3"
case "0"
Response.Redirect "9-20a.asp?say=0"
End Select
%>
</body>
</html>
9.3.3 Application对象
简单地说,一个Application就是用来实现某一特定功能的Web应用程序。通常情况下它是由许多文件组成的集合,这个集合中的每一个文件都可以视为该程序的子程序,而且几个处理相关内容的脚本可以构成一个功能模块,这很像在Windows下用Vc++或VB开发的应用程序。
1,Application对象的集合和方法
首先,对于Application对象来说,其最大的优势在于,网站上的不同用户可以通过Application共享信息,这一点在诸如社区、聊天室之类的网站上应用广泛。
其次,在一个Application下属的某个文件中建立的组件Instance可以被该Application中的其他所有文件调用。换句话说,可以在Application范围中建立一个组件Instance,并在整个Application中调用该Instance。尽管这样做也有一定的弊端,但在很多时候,在Application范围内建立组件Instance可以带来很多方便。
再者,和Session一样,Application也拥有两个重要的属性:Application_OnStart和Application_OnEnd。
最后,服务器上运行的所有Application都是相互独立的。如果某个Application被人为地结束或因运行错误意外终止,不会影响到其他Application。
·Contents巢合
与Session对象相似,Application对象也是利用Contents集合保存其相关内容的。因此,所有适用于Session.Contents集合的属性和方法也同样适用于Application.Contents集合。例如Count属性、Remove及RemoveAll方法。需要注意的是,对于Application对象来说,其Contents集合中的内容是被很多用户共享的,因此不会因为某个甚至全部用户的离开而自行结束,它会一直保存至该Application被卸载,或服务器重新激活,这是它和Session.Contents最大的区别。,
·Lock和UnLock方法
Application对象可以用来实现网站某一用户群体之间的信息共享,这就需要服务器不断地收集和处理需要共享的信息。当存取网站的用户不是很多时,这种工作可以有条不紊地进行;但是如果是一个日存取量数以万计的网站,假设许多用户同一时刻将信息提交给服务器处理,那么服务器究竟应该响应哪个用户呢?如果这个问题处理不好,势必会造成信息阻塞甚至遗漏。为此Application对象专门提供了Lock和UnLock方法解决这种矛盾。
当某个Application调用了Lock方法后,服务器就不再允许其他用户处理程序对该 Application的内容做修改,直到它调用UnLock方法解除锁定。
注意:当需要修改一个Application的内容时,最好先调用Lock方法,并在内容修改完毕后调用UnLock方法将其解锁,这样做可以尽可能地避免意外的信息遗失。
例9.21 用 Application 来记录页面访问次数的程序。文件名为9-21.asp。
<html>
<body>
<%
Dim NumVisits
NumVisits=0
Application.Lock
Application("NumVisits")=Application("NumVisits")+1
Application.Unlock
%>
欢迎光临本网页,你是本页的第<%=Application("NumVisits")%>位访客!
</body>
</html>
将以上脚本保存在你的,asp 文件中,就轻而易举地给你的页面添加了一个计数器。
2.处理Application对象的事件
Application对象拥有两个事件:Application_OnStart和Application_OnEnd,可以在 Global.asa文件中处理这两个事件。其中,Application_OnStart事件对应于一个Application的开始,而Application_OnEnd事件则对应于Application的结束。
Application_OnStart 事件在首次创建新的会话 ( 即 Session_OnStart 事件 ) 之前发生。当 WEB 服务器启动并允许对应用程序所包含的文件进行请求时就触发Application_OnStart 事件。Application_OnStart 事件的处理过程必须写在 Global.asa 文件之中。
Application_OnStart 事件的语法如下,
< SCRIPT LANGUAGE=ScriptLanguage RUNAT=Server>
Sub Application_OnStart
……
End Sub
< /SCRIPT>
  Application_OnEnd 事件在应用程序退出时于 Session_OnEnd 事件之后发生,Application_OnEnd 事件的处理过程也必须写在 Global.asa 文件之中。
在ASP中规定,当某个Application的文件第一次被用户调用时就意味着这个Application开始运作,相对的Application_OnStart事件被触发;而Application的结束则需要等到服务器停止服务或该Application被卸载,此时,Application_OnEnd事件将会被触发。
注意:由于Application对象的结束通常代表服务器进入关机状态,此时大多数的ASP对象和方法将失去作用。
注意,不能在 Application 对象中存储 ASP 内建对象。例如,下面的每一行都返回一个错误。
< %
Set Application("var1")=Session
Set Application("var2")=Request
Set Application("var3")=Response
Set Application("var4")=Server
Set Application("var5")=Application
Set Application("var6")=ObjectContext
%>
9.3.4 Session对象什么是Session
可以使用 Session 对象存储特定的用户会话所需的信息。当用户在应用程序的页之间跳转时,存储在 Session 对象中的变量不会清除,而用户在应用程序中访问页面时,这些变量始终存在。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。
通过向客户程序发送唯一的 Cookie 可以管理服务器上的 Session 对象。
当用户第一次请求 ASP 应用程序中的某个页面时,ASP 要检查 HTTP 头信息,查看是否有在报文中有名为 ASPSESSIONID 的 Cookie 发送过来,如果有,则服务器会启动新的会话,并为该会话生成一个全局唯一的值,在把这个值作为新 ASPSESSIONID Cookie 的值发送给客户端,正是使用这种 Cookie,可以访问存储在服务器上的属于客户程序的信息。
Session 对象最常见的作用就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在 Session 对象中。另外其还经常被用在鉴别客户身份的程序中。要注意的是,会话状态仅在支持 cookie 的浏览器中保留,如果客户关闭了 Cookie 选项,Session 也就不能发挥作用了。
Session对象就是客户端浏览器与服务器之间建立的互动信息的状态。每一个不同的用户连接得到不同的Session,也就是说Session与用户之间是一种一对一的关系。Session在用户进入网站时由服务器自动产生,并在用户正常离开站点时释放。使用Session的好处就在于,可以将很多与用户相关的信息,例如用户的账号、昵称等保存到Session中;更加有趣的是,利用Session,可以跟踪用户在网站上的活动。
下面,我们先来看看Session对象提供的一些比较常用的属性和方法。
· Contents集合
一般情况下,当将一条用户信息保存在Session中时,这条信息实际上是被保存在 Session对象的Contents集合中,因此下面两段程序代码效果是相等的:
Session(“custom_color”)=”blue”
Session,Contents (“custom_color”)=”blue”
和其他很多数据集合类似,Contents集合也有Count属性,该属性用来了解Contents集合中数据项的数目。在下面的范例中,我们先为Contents集合建立若干数据项,然后使用循环语句输出该集合的全部内容,这其中就用到了它的Count属性。
例9.23文件名为9-23.asp。
<html>
<body>
<%
dim customer_info
dim interesting(2)
interesting(0)="足球"
interesting(1)="编程"
interesting(2)="阅读"
response.write "sessionID:" & session.sessionid & "<p>"
session("爱好")=interesting
session("用户名称")="mickey"
session("年龄")="22"
session("证件号")="88567"
set objconn=server.createObject("ADODB.connection")
set session("用户数据库")=objconn
response.write "session集合有下面"&session.contents.count&"项内容:<hr>"
for each customer_info in session.contents
if isobject(session.contents(customer_info)) then
response.write(customer_info&":此项无法显示"&"<br>")
else
if isarray(session.contents(customer_info)) then
response.write "数组项目:"&customer_info&"<br>"
for each item in session.contents(customer_info)
response.write "<li>"&item&"<br>"
next
response.write "</ol>"
else
response.write customer_info&":"&session.contents(customer_info)&"<br>"
end if
end if
next
%>
</body>
</html>
运行结果如图9-19。
图9-19
Contents集合还提供了两个方法,它们分别是Remove与RemoveAll方法。利用这两个方法,可以选择性地删除Contents集合中的某个数据项或是干脆将该集合的内容全部清除,其格式分别为:
Session.contents.remove(Item/Index)
Session.contents.removeAll
前面的Item与Index分别指所要删除的数据项的名称与索引编号。
· SessionID 属性
如前所述,用户和Session是一一对应的,这种对应关系表现在什么地方呢?我们再看前面那个范例,其中有“SessionID:515543434”这一句。原来,当一个Session开始的时候,服务器会自动为其分配一个SessionID。在一段时间里,对于存取该网站的所有用户来说,SessionID都是惟一的。注意,是在一段时间内,如果Web
服务器重新激活,那么它所分配的SessionID和服务器重新激活分配的SessionID就有可能不同了。因此,在建立用户数据库时不能将SessionlD作为每个用户的标志。
·Timeout属性
Timeout属性以分钟为单位为该应用程序的Session对象指定超时时限。如果用户在该超时时限之内不刷新或请求网页,则该会话将终止。
·Abandon方法
Abandon方法就是用来手动结束一个Session并释放其占用的资源。有一点需要注意的是,服务器真正释放Session所占用资源是在它处理完该方法在页面的全部脚本命令之后。例如下面的范例中,尽管在第二行就已经调用Abandon方法,但是由于整个脚本尚未运行完毕,因此第三行还是输出了Session中保存的内容:
<%
Session("user_name")="mickey"
Session.Abandon()
response.Write(Session("user_name"))
%>
2,Session事件
Session对象有一个很特殊的地方,那就是它除了有一些集合、属性、方法之外,还拥有两个时间事件,在这方面与它相似的还有Application对象,我们将在前面已做介绍。Session对象的这两个事件分别是Session_OnStart和Session_OnEnd,它们分别在Session开始和 Session结束的时候被触发。在了解这两个事件之前,先让我们看一个与它们有着密切联系的文件——Global.asa。
在Web站点根目录或一些应用程序的虚拟目录中,通常可以看到一个Global.asa的文件,我们不仿来看看其内容:
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
sub Application_OnStart
end sub
sub Application_OnEnd
end sub
Sub Session_OnStart
if time<#9:00:00am# then
timeword="早晨"
else if time<#12:00:00am# then
timeword="上午"
else if time<#1:00:00pm# then
timeword="中午"
else if time<#5:00:00pm# then
timeword="下午"
else
timeword="晚上"
end if
session.contents("greeting")=timeword&"好!"
Application.Lock
count=application("USER_COUNT")
count=count+1
Application("USER_count")=count
Application.Unlock
End Sub
Sub Session_OnEnd
Application.Lock
count=application("USER_COUNT")
count=count-1
Application("USER_count")=count
Application.Unlock
End Sub
</SCRIPT>
该程序中,Session_OnStart和Session_OnEnd完成两个任务,根据用户进入网站时间决定欢迎词以及统计网站上人数。大型的网站,其Global.asa文件要复杂的多,但其基本功能都是处理Session对象和Application对象的这两对事件。
在编写Global.asa文件时应该注意的是,该文件中的脚本只能使用Microsoft规范的“<Script>……</script>”标记而不能使用“<%……%>’’标记;而且不能像在其他ASP文件中那样使用HTML语言,更不能在里面添加任何的输出语句,这是因为Global.asa在任何时候都不会进行内容输出。
例9.24本例将示范如何通过session对象的两个事件来记录网页被浏览的过程。相关文件为global.asa和9-24.asp。
global.asa的内容如下:
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
Sub Session_OnStart
Session("who")=Request.ServerVariables("REMOTE_ADDR")
Session("Host")=Request.ServerVariables("REMOTE_Host") Session("Server")=Request.ServerVariables("SERVER_NAME")
Session("StartTime")=NOW
End Sub
Sub Session_OnEnd
Set fs=Server.CreateObject("Scripting.FileSystemObject")
Set ts=fs.CreateTextGile("d:\zwf\zwf\asp\info.txt",True)
Str="客户" & Session("Who")
Str=Str & "从" & Session("StartTime")
Str=Str & "到" & Now & "浏览本网站"
ts.Write Str
ts.Close
Set fs=nothing
End Sub
</SCRIPT>
9-24.asp的内容如下:
<html>
<body>
<%
Session.Timeout=1
Response.write "您的计算机IP是:" & Session("Who") & "<BR>"
Response.write "您的计算机名是:" & Session("Host") & "<BR>"
Response.write "服务器的名字是:" & Session("Server") & "<BR>"
Response.write "现在的时间是:" & Session("StartTime") & "<BR>"
%>
</body>
</html>
本例的运行结果如图9-20所示。

图9-20例9-24运行结果
9.3.5 Server对象
Server对象提供对服务器上的方法和属性的访问,其中大多数方法和属性是作为实用程序的功能服务的。有了Server对象,就可以在服务器上启动AcfiveX对象例程,并使用 Active Server服务提供像HTML和URL编码这样的函数。
语法:Server.Property|method
属性
ScriptTimeout是超时值,在脚本运行超过这一时间之后即作超时处理。如下代码指定服务器处理脚本在100秒后超时:
<%Server.ScriptTimeout=100%>
方法
(1)HTMLEncode 方法
HTMLEncode 方法允许你对特定的字符串进行 HTML 编码,虽然 HTML 可以显示大部分你写入 ASP 文件中的文本,但是当你需要实际包含 HTML 标记中所使用的字符,就会遇到问题。这是因为,当浏览器读到这样的字符串时,会试图进行解释。
为了避免此类问题,就需要使用 Server 对象的 HTMLEncode 方法,采用对应的不由浏览器解释的 HTML Character Code 替代 HTML 标记字符。所以,用下面的代码才能显示正确的 HTMLEncode 字符串,从而在浏览器中按你的需要输出文本。
< % Response.write Server.HTMLEncode(" 这是对 HTMLEncode 方法的测试。< br> 这里应该不会另起一行。")%>
(2)URLEncode方法
URLEncode方法可以根据URL规则对字符串进行正确编码,当字符串数据以URL的形式传递到服务器时,在字符串中不允许出现空格,也不允许出现特殊字符。为此,如果希望在发送字符串之前进行URL编码,可以使用Server.URLEncode方法。
(3)MapPath方法
MapPath方法将指定的相对或虚拟路径映射到服务器上相应的物理目录上。语法如下:
Server.MapPath(Path)
其中Path指定要映射物理目录的相对或虚拟路径。若Path以一个正斜杠(/)或反斜杠(\)开始,则MapPath方法返回路径时将Path视为完整的虚拟路径。若Path不是以斜杠开始,则MapPath方法返回同.asp文件中已有的路径相对的路径。这里需要注意的是MapPath方法不检查返回的路径是否正确或在服务器上是否存在。
例9.25 对于下列示例,文件 data.txt 和包含下列脚本的 temp1.asp 文件都位于目录C:\Inetpub\Wwwroot\asp 下。C:\Inetpub\Wwwroot 目录被设置为服务器的宿主目录。下列示例使用服务器变量 PATH_INFO 映射当前文件的物理路径。
temp1.asp的内容为:
<%= server.mappath(Request.ServerVariables("PATH_INFO"))%>
输出结果为,
  C:\Inetpub\wwwroot\temp1.asp
由于下列示例中的路径参数不是以斜杠字符开始的,所以它们被相对映射到当前目录,此处是目录 C:\Inetpub\Wwwroot\asp。
以下脚本
< %= server.mappath("data.txt")%>
< %= server.mappath("asp/data.txt")%>
  输出
c:\inetpub\wwwroot\asp\data.txt
c:\inetpub\wwwroot\asp\asp\data.txt
(4)CreateObject方法
Server.CreateObject方法恐怕是 ASP 中最为实用,也是最强劲的功能了。它用于创建已经注册到服务器上的 ActiveX 组件实例。这是一个非常重要的特性,因为通过使用 ActiveX 组件能够使你轻松地扩展 ActiveX 的能力,正是使用了 ActiveX 组件,你可以实现至关重要的功能,譬如数据库连接、文件访问、广告显示和其他 VBScript 不能提供或不能简单地依靠单独使用 ActiveX 所能完成的功能。正是因为这些组件才使得 ASP 具有了强大的生命力。
其语法如下:
Server.CreateObject("Component Name")
9.3.6 Global.asa文件的使用
前面我们讲过Application和Session对象的两个事件OnStart和OnEnd的脚本都必须写在Global.asa文件中。本节我们就来介绍Global,asa文件的使用。
Global.asa文件其实是一个可选文件,程序编写者可以在该文件中指定事件脚本,并声明具有会话和应用程序作用域的对象。该文件的内容是用来存储事件信息和由应用程序全局使用的对象。该文件的名称必须是Global.asa且必须存放在应用程序的根目录中。每个应用程序只能有一个Global.asa文件。
Global.asa文件的结构如下:
<SCRIPT LANGUAGE=”JavaScript'’RUNAT="SERVER">
function Application OnStart()
{
}
function Session_OnStart()
{
}
function Session_OnEnd()
{
}
</SCRIPT>
注意:Application的OnStart事件肯定是在Session_OnStart事件之前。Application不会像Session那样在一个新用户登录后就触发,Application只触发一次,即是第一个用户登录网站时。
下面是一个很标准的Global.asa文样,
<SCRIPT LANGUAGE="VBScript" RUNAT="server">
'Session_OnStart当客户首次运行ASP应用程序中的任何一个页面时运行
'Session_OnEnd当一个客户的会话超时或退出应用程序时运行
'Application_OnStart当任何客户首次访问该应用程序的首页时运行
'Application_OnEnd当该站点的Web服务器关闭时运行
</SCRIPT>
<SCRIPT LANGUAGE="VBScript" RUNAT="Server">
Sub Application_OnStart
VisitorCountFilename=Server.MapPath("/ex2")+"\VisitCount.txt"
Set FileObject=Server.CreateObject("Scripting.FileSystemObject")
Set Out=FileObject.OpenTextFile(VisitorCountFilename,1,FALSE,FALSE)
Application("visitors")=Out.ReadLine
Application("VisitorCountFilename")=VisitorCountFilename
End Sub
'=======================================================================
SUB Application_OnEnd
Set FileOutObject=Server.CreateObject("Scripting.FileSystemObject")
Set Out=FileOutObject.CreateTextFile(Application("VisitorCountFilename"),TRUE,FALSE)
Out.WriteLine(application("visitors"))
End Sub
'========================================================================
Sub Session_OnStart
Session.Timeout=5
Application("visitors")=Application("visitors")+1
Session("ID")=Session.SessionID
End Sub
</SCRIPT>
这是一个ASP页面访问记数器应用程序的Global文件,首先当客户首次访问该应用程序的首页时,事件Application_ OnStart定义了在服务器上指定的虚拟目录下新建一个 VisitCount.txt的文本文件,并将文件的路径和内容保存在应用程序级的变量中。而当任何一个客户访问ASP应用程序中的任何一个页面时,事件Session _OnStart定义将应用程序级的变量visitors的值自动加1。这样,每当有客户访问页面时,变量visitors都将自动加1,以起到统计点击率的作用。由于变量visitors的值是存储在系统内存之中,所以如果服务器关闭或重新启动,存储在变量中的数据将自动丢失,所以通过定义事件 Application_ OnEnd,在服务器关闭或重启之前将数据写入事先建立的文本文件之中,这样 就能确保当服务器再次启动时,Application_OnStart过程可以从VisitCount.txt文件中读取以前的统计数。
ASP内置组件——ActiveX 组件
ActiveX 组件是一个存在于 WEB 服务器上的文件,该文件包含执行某项或一组任务的代码,组件可以执行公用任务,这样就不必自己去创建执行这些任务的代码。例如,股票行情收报机组件可以在 Web 页上显示最新的股票报价。当你在 WEB 服务器上安装完 ASP 环境后,就可以直接使用它自带的几个常用组件,如 Database Access 组件。当然你也可以从第三方开发者处获得可选的组件,也可以编写自己的组件。你可以利用组件作为脚本和基于 Web 应用程序的基本构造块,只要知道如何访问组件提供的对象,即使你是位编写脚本的新手,也可以在不了解组件运作方式的情况下编写 ASP 程序。
总而言之,ActiveX 组件使用户不用学习复杂的编程就能够写出强大的 WEB 服务器端脚本。如果是位 Web 应用程序的开发者,可以使用任何支持组件对象模型(COM)的语言来编写组件,如,C,C++,Java 或 Visual Basic。如果你熟悉 COM 编程,ActiveX 组件就是 Automation 服务器。但是要在 Web 服务器上运行,ActiveX 组件不能有图形用户接口元素,如 Visual Basic 的 MsgBox 函数。
组件是可以重复使用的。在 Web 服务器上安装了组件后,就可以从 ASP 脚本,ISAPI 应用程序、服务器上的其他组件或由另一种 COM 兼容语言编写的程序中调用该组件。
当用户用ASP编写服务器端应用程序时,必须依靠Activex组件来强大Web应用程序的功能。
组件是包含在动态链接库(.dll)或可执行文件(.exe)中的可执行代码。组件可以提供一个或多个对象以及对象的方法和属性。
表9.2列出了ASP可安装的常用组件。
表9.2常用组件的名称及功能组件名称
功能描述
Ad Rotator
(广告轮显组件)
创建一个Ad Rotator对象,该对象可按指定计划在同一页上自动轮换显示广告
Browser Capabilities
(浏览器功能组件)
创建一个BrowserType对象,该对象决定访问Web站点的每个浏览器的性能、类型及版本
Database Access(数据库访问组件)
提供用ActiveX Data 0bjects(ADO)对数据库的访问
Content Linking
(内容链接组件)
创建一个NextLink对象,该对象可生成Web页内容列表,并像书一样将各页顺续连接
File Access(文件存取组件)
提供文件的输入输出访问
Collaboration Data 0bjects for NTS(邮件收发组件)
可以快速、简便地在Web页上添加收发邮件功能。该组件只适用于IIS for Windows NT Server
MyInfo
(个人信息跟踪组件)
创建一个MyInfo对象,该对象追踪个人信息,例如站点管理员的姓名、地址及显示选择
Counters
(计数器组件)
创建一个Counters对象,该对象可以创建、保存、增加或检索任意数量的独立计数器
Content Rotator(内容轮显组件)
自动翻转Web主页上的HTML内容字符串
Page Counter(页面计数器组件)
记录并显示Web页被打开的次数
9.5 ASP实现对数据库的访问
9.5.1概述
1.Web站点使用的数据库
Microsoft Access是一个桌面数据库,不像Microsoft SQL Server那样是一个客户/服务器数据库。因为Access是一个桌面数据库,所以只能用它来规划自己的Web站点或者创建流量较少的Web站点。一般来说,Microsoft Access数据库不能支持30个以上同时访问的用户。
当使用Microsoft access创建了自己的Web站点之后,可以将其升级到Microsoft SQL Server。微软提供了一个Upsizing Tools工具,可以利用它将Microsoft Access数据库转换为Microsoft SQL Server数据库。
与Microsoft Access不同的是,Microsoft SQL Server可以支持成千上万同时访问的用户及以太字节(1012B)计算大小的数据库。实际上,Microsoft SQL Server可以支持的线上商场也是任意大的。当今Internet上的一些特大型商用Web站点使用的都是Microsoft SQL Server。
2.一些基本概念
(1)Active Server
它是随Windows NT 交付的服务器方技术的集合。这些 技术为组件应用程序管理、数据库访问、事务和消息提供一致的服务器方组件、脚本模型和一套集成的系统服务。
(2)Active Server Pages (ASP)
在服务器上运行 ActiveX 脚本和 ActiveX 组件的服务器方脚本环境。开发人员可以将脚本和组件结合在一起创建基于Web的应用程序。
(3)ActiveX
允许开发人员为 World Wide Web 创建交互式组件的内涵丰富的Microsoft 技术术语。允许用不同语言编写的软件组件在网络环境中一起工作的一组不依赖语言的互操作技术。ActiveX的关键元素是组件对象模型(COM)和分布组件对象模型(DCOM)。这些技术已得到开放组织的许可,已移植到许多平台上。
(4)ADO
Active 数据对象。为基于 Internet 以数据为中心的应用程序而优化的一组基于对象的数据访问接口。ADO基于已发布的规范并且随带在Microsoft Internet Information Server和 Microsoft Visual InterDev中。
(5)DSN 数据源名称开放式数据库接口(ODBC)用于引用访问数据所需的驱动程序或其他信息的逻辑名称。Internet信息服务器用于连接到ODBC数据源如 SQL Server数据库)的名称。
(6)event,事件由用户或ActiveX控件产生的程序响应的任何操作。一般事件包括按键盘键、通过使用鼠标单击选择按钮和其他鼠标操作。编程人员编写响应这些操作的代码。
(7)object对象在面向对象编程中,由当作完整实体的操作和数据组成的变量。对象是基于特定模型的,在对象中客户使用对象的服务通过由一组方法或相关函数 的接口访问对象的数据。然后客户端可以调用这些方法执行某中操作。
(8)ODBC
开放式数据库接口。允许应用程序从各种跨平台数据访问的已有数据源标准规格中访问数据的应用程序编程接口。SQL结构化查询语言 Structured Query Language。定义和访问关系型数据库的国际标准。
9.5.2 ASP访问数据库的步骤
ASP访问数据库的步骤如下,
1.第一步,指定想要连接的数据库,有 DSN 和 DSN-less 两种方法。
DSN(Data Source Name 数据源名称 )
DSN方法是建立一个系统数据源名称,方法如前。 然后在 ASP 程序中指定 DSN,如下,
< %connstr = "FILEDSN=MyDatabase.dsn"%>
注意:无论在等号(=)之前还是之后,DSN字符串都不能包含空格。
(2)DSN-less方法
DSN-less方法是另一种通过在 ASP 文件里直接指定数据库文件所在位置,而无需建立 DSN 的方法。由于许多公司没有自己的 WEB 服务器,他们的网站往往是存放在远端的虚拟服务器上,因此要建立和修改 DSN 的设置比较麻烦。而使用 DSN-less 方法直接指定远端数据库所在位置恰恰解决了这一问题,方法如下,
< %
connstr = "DBQ="+server.mappath("database/source.mdb")+";DefaultDir=;DRIVER={Microsoft Access Driver (*.mdb)};DriverId=25;FIL=MS Access;ImplicitCommitSync=Yes;MaxBufferSize=512;MaxScanRows=8;PageTimeout=5;SafeTransactions=0;Threads=3;UserCommitSync=Yes;"
%>
或者:
<%
connstr="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & server.mappath("data/database.mdb")
%>
或者:
<%
'如果你的服务器采用较老版本Access驱动,请用下面连接方法
connstr="driver={Microsoft Access Driver (*.mdb)};dbq=" & server.mappath("data/database.mdb")
%>
在指定了想要连接的数据库后,就可以通过以下方法连接并打开数据库,
< %
Set Conn = Server.CreateObject("ADODB.Connection")
’创建Connection对象
Conn.Open connstr ’使用Connection对象的Open方法打开数据库
%>
2.第二步,指定想要执行的 SQL 指令,可以使用 RecordSet。
当连接了数据库后就可以对数据库进行操作,比如查询、删除、更新等等,这些操作都是通过 SQL 指令来完成的。
如下例:在数据库表 datebase 中查询所有姓名中有“A”的记录,
< %
sql="select * from datebase where name like '%A%'"
Set rs = Conn.Execute(sql)
Conn.close
%>
如下例在数据库表 datebase 中插入一条记录:
<%
strSQL = "INSERT INTO Customers (FirstName,LastName) VALUES ('Jose','Lugo')"
Conn.Execute(strSQL)
%>
如下例在数据库表 datebase 中更新记录:
<%
Conn.Execute "UPDATE Customers SET FirstName = 'Jeff' WHERE LastName = 'Smith' "
%>
如下例在数据库表 datebase 中删除记录:
<%
Conn.Execute "DELETE FROM Customers WHERE LastName = 'Smith'"
%>
尽管 Connection 对象简化了连接数据库和查询任务,但 Connection 对象仍有许多不足。确切地说,检索和显示数据库信息的 Connection 对象不能用于创建脚本,编程者必须确切知道要对数据库作出的更改,然后才能使用查询实现更改。对于检索数据、检查结果、更改数据库,ADO提供了Recordset对象。正如它的名称所暗示的那样,Recordset对象有许多您可以使用的特性,根据编程者的查询限制,检索并且显示一组数据库行,即记录。
Recordset 对象保持查询返回的记录的位置,允许一次一项逐步扫描结果。根据 Recordset 对象的指针类型属性设置,可以滚动和更新记录。数据库指针可以让您在一组记录中定位到特定的项。指针还用于检索和检查记录,然后在这些记录的基础上执行操作。 Recordset 对象有一些属性,可用于精确地控制指针的行为,提高检查和更新结果的能力。
Recordset 的使用方法如下,
Set rs = Server.CreateObject("ADODB.Recordset")
’创建Recordset对象
rs.Open (SQL 指令,Conn,打开方式,锁定类型)
’利用Recordset对象open 方法打开数据库 
open 方法有四个参数,后两个参数可省略。
打开方式的四个参数如下:
adOpenForwardOnly:对应数字0,记录集只能向前移动;
adOpenKeyst:对应数字1,记录集向前或向后移动;
adOpenDynamic:对应数字2,动态游标,记录集向前或向后移动;
adOpenStatic:对应数字3,静态游标,记录集向前或向后移动
锁定类型的四个参数如下:
adLockReadOnly:对应数字1,只读;
adLockPessimistic:对应数字2,编辑记录,立即锁定;
adLockOptimistic:对应数字3,调用Update方法,才锁定;
adLockBatchOptimistic:对应数字4,记录只能成批更新
3.第三步,使用 RecordSet 属性和方法,并显示执行的结果。
通过以上指令,我们创建了一个包含数据的游标 (RecordSet)“rs”,事实上游标是存储在活动内存中的类似记录和字段的数组的东西,当通过RecordSet组件创建一个游标时,它从数据提供者的得到一个数据集,并用它来充实游标,我们可以想象ADO产生的 RecordSet 是一个象电子表格的记录,它有一行行的记录,在任何时候都有一行是它的当前行,而RecordSet的字段是用RecordSet的Field集合表示的。
RecordSet对象的一些属性和方法:
rs.Fields.Count,RecordSet 对象的字段总数。
rs(i).Name,第 i 个字段的名称,i 由 0 算起到rs.Fields.Count-1。
rs(i),读取第 i 个字段的数据,i 由 0 算起到 rs.Fields.Count-1。
rs(" 字段名称 "),读取指定字段的数据。
rs.RecordCount,游标中的数据记录总数。
rs.EOF,是否已指到最后一条记录。
rs.MoveNext,将指标移到下一笔记录。
rs.MovePrevious,将指标移到上一笔记录。
rs.MoveFirst,将指标移到第一笔记录。
rs.MoveLast,将指标移到最后一笔记录。
rs.Close,关闭 RecordSet 对象
9.5.3 ASP访问数据库的实例
1.连接数据库例26:与数据库建立连接,文件名为9-26.asp。
<% @ LANGUAGE=VBScript %>
<%
Option Explicit
Dim Cnn,StrCnn
'创建Connection 对象
Set Cnn = Server.CreateObject("ADODB.Connection")
StrCnn = "Driver={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("bbs.mdb;")
'使用 Connection 对象的 Open 方法打开数据库bbs.mdb,该数据库用户自己建立
Cnn.Open StrCnn
Response.Write Server.MapPath("bbs.mdb") & "<br>"
Response.Write "数据库连接成功," & Cnn.State & "<br>"
'使用 Connection 对象的 Close 方法关闭连接
Cnn.close
Response.Write "数据库已经关闭," & Cnn.State
'将Connection 对象从内存中删除,以释放资源
Set Cnn = Nothing
%>
运行结果如图

例9.27 循环检索记录,文件名为9-27a.asp和9-27b.asp。先注册文件数据源为Myaa.dsn,使用的数据库为northwind.mdb。
9-27a.asp的内容如下:
<%
strDSN = "FILEDSN=Myaa.dsn"
Set cn = Server.CreateObject("ADODB.Connection")
cn.Open strDSN
//初始化Recordset对象
Set rsCustomers = Server.CreateObject("ADODB.Recordset")
strSQL = "SELECT 联系人姓名,公司名称 FROM 客户 WHERE 客户ID= 'FAMIA' "
rsCustomers.Open strSQL,cn
//循环查询,并显示结果
Set objFirstName = rsCustomers("联系人姓名")
Set objLastName = rsCustomers("公司名称")
Do Until rsCustomers.EOF
Response.Write objFirstName & "-------- " & objLastName & "<BR>"
rsCustomers.MoveNext
Loop
%>
9-27b.asp的内容如下:
<%
’与9-27a.asp的区别是未建立Connection对象,但结果相同
strDSN = "FILEDSN=Myaa.dsn"
strSQL = "SELECT 联系人姓名,公司名称 FROM 客户 WHERE 客户ID= 'FAMIA' "
Set rsCustomers = Server.CreateObject("ADODB.Recordset")
rsCustomers.Open strSQL,strDSN
Set objFirstName = rsCustomers("联系人姓名")
Set objLastName = rsCustomers("公司名称")
Do Until rsCustomers.EOF
Response.Write objFirstName & "-------- " & objLastName & "<BR>"
rsCustomers.MoveNext
Loop
%>
9-27a.asp和9-27a.asp的运行结果如图:

例9.28通过Open方法和ConnectionString属性来建立与数据库的连接。文件名为9-28.asp。
<html>
<body>
<%
'用Connection对象的Open方法方式建立与数据库的连接
set conn1=Server.CreateObject("ADODB.Connection")
conn1.Open "DSN=pubs"
Response.Write "数据库连接成功," & Conn1.State & "<br>"
'使用 Connection 对象的 Close 方法关闭连接
Conn1.close
Response.Write "数据库已经关闭," & Conn1.State & "<br>"
'将Connection 对象从内存中删除,以释放资源
set conn1=nothing
'通过设定Connection对象的ConnectionString属性来建立与数据库的连接
Set conn2=Server.CreateObject("ADODB.Connection")
conn2.ConnectionString="DSN=pubs"
conn2.open
Response.Write "数据库连接成功," & Conn2.State & "<br>"
Conn2.close
Response.Write "数据库已经关闭," & Conn2.State
Set conn2=nothing
%>
</body>
</html>
9-28.asp的运行结果如图:

在使用这两种方法建立与数据库的连接之前要首先建立ODBC数据源,例子中的“pubs”就是ODBC数据源的名字。也可以采用直接指定ODBC的驱动程序名称的方法来建立与数据库的连接,但是在使用这种方法的时候要注意,必须用Driver={驱动程序名}的格式引用。ODBC驱动程序名可以通过启动ODBC Data Source Administrator获得,或者在 Odbc.ini文件中找到。例如用SQL Server建立的数据库的驱动程序名为“SQL Server”,Access建立的数据库驱动程序名为“Microsoft Access Driver(*.mdb)”。
例子中的Set connl=nothing是关闭数据库连接,也可以用connl.Close来执行同样的操作。
例9.29使用Connection对象的Execute方法在网页中执行SQL命令,查询northwind数据库“客户”表中的所有信息。
<%
Set conn=Server.CreateObject("ADODB.Connection")
Set rs=Server.CreateObject("ADODB.recordset")
conn.open "dsn=pubs"
Set rs=conn.execute ("Select * from 客户")
Response.Write "<table border=3>"
Response.Write "<tr>"
For i=0 to rs.Fields.Count-1 ’输出字段名
Response.Write "<td>"&Ucase(rs(i).Name)&"</td>"
Next
Response.Write "</tr>"
do While NOT rs.EOF
Response.Write "</tr>"
For i=0 to rs.Fields.Count-1 ’输出字段值
Response.Write "<td>"&rs(i).Value&"</td>"
Next
rs.MoveNext
Response.Write "</tr>"
Loop
Response.Write "</table>"
Set conn=nothing
%>
northwind数据库是Access自带的示例数据库,我们这里建立的ODBC数据源的名称也是pubs。
2.记录集Recordset对象以上我们学习了使用AD0的Connection对象打开一个数据库连接,并在一个打开的连接中执行SQL命令。但是如果我们要对 SQL命令执行的结果进行操作,就要用到Recordset对象的Open方法了。
Recordset对象的open方法用来执行用户向数据库提出的请求,例如执行一个SQL命令,启动一个指定的数据库表或是调动一个指定的存储过程。下面我们就来看一个例子,这个例子用只读的方式查询数据库表中的信息。
例9.30本例共有两个文件:test9-30.html和9-30.asp。test9-30.html用来产生向用户收集信息的表单,用户可以指定要查看“图书信息”或“作者信息”。 9-30.asp用来响应用户的请求。
test9-30.html的内容如下:
<html>
<body>
<form method=post action=9-30.asp>
<p>查看客户信息请点击这里
<input type=submit name=button value="客户信息">
</p>
<p>查看产品信息请点击这里
<input type=submit name=button value="产品信息">
</p>
</form>
</body>
</html>
9-30.asp的内容如下:
<%
const adOpenStatic=3
const adLockReadOnly=1
'建立Recordset对象
Set rs=Server.CreateObject("ADODB.Recordset")
'提取表单域“button”的值
button=Request.Form("button")
'设定光标类型为静态
CursorType=adOpenStatic
'设定锁定类型为只读
LockType=adLockReadOnly
'如果用户选择“客户信息”则执行下面的代码
If button="客户信息" Then
source="select * from 客户"
activeConnection="dsn=pubs"
rs.open source,activeConnection,CursorType,LockType
end if
'如果用户选择“产品信息”则执行下面的代码
If button="产品信息" Then
source="select * from 产品"
ActiveConnection="dsn=pubs"
rs.Open source,ActiveConnection,CursorType,LockType
End if
'查询结果以表格的形式输
Response.Write "<table border=3>"
Response.Write "<tr>"
For i=0 to rs.Fields.Count-1
Response.Write "<td>"&Ucase(rs(i).Name)&"</td>"
Next
Response.Write "</tr>"
'输出表格内容
While NOT rs.EOF
Response.Write "<tr>"
For i=0 to rs.Fields.Count-1
Response.Write "<td>"&rs(i).Value&"</td>"
Next
rs.MoveNext
Wend
Response.Write "</table>"
'取消连接
Set rs=nothing
%>
运行结果如图:


例9.31 Recordset访问数据库,文件名为9-31.asp,数据库为ntopsamp.mdb。
<%
Set conn1 = Server.CreateObject("ADODB.Connection")
conn1.Open "DBQ=" & Server.MapPath("ntopsamp.mdb") & _
";Driver={Microsoft Access Driver (*.mdb)};DriverId=25;FIL=MS Access;"
Set rs2 = Server.CreateObject("ADODB.Recordset")
SqlStr = "SELECT Avg(价格) As 平均 From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>Avg," & rs2("平均")
rs2.Close
SqlStr = "SELECT Count(价格) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>Count(价格)," & rs2(0)
rs2.Close
SqlStr = "SELECT Count(*) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>Count(*)," & rs2(0)
rs2.Close
SqlStr = "SELECT Sum(价格) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>Sum," & rs2(0)
rs2.Close
SqlStr = "SELECT Min(价格) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>Min," & rs2(0)
rs2.Close
SqlStr = "SELECT Max(价格) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>Max," & rs2(0)
rs2.Close
SqlStr = "SELECT First(价格) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>First(价格)," & rs2(0)
rs2.Close
SqlStr = "SELECT Last(价格) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>Last(价格)," & rs2(0)
rs2.Close
SqlStr = "SELECT First(代号) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>First(代号)," & rs2(0)
rs2.Close
SqlStr = "SELECT Last(代号) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>Last(代号)," & rs2(0)
rs2.Close
SqlStr = "SELECT StDev(价格) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>StDev," & rs2(0)
rs2.Close
SqlStr = "SELECT Var(价格) From 产品"
rs2.Open SqlStr,conn1,1,1
Response.Write "<BR>Var," & rs2(0)
rs2.Close
conn1.Close
%>
运行结果如图:

3.验证数据例9.32 用户登录验证,文件名为9-32.asp和login.asp。
使用的数据库为info.mdb,其中表:userinfo包含userid、psw、logins、pswnotice、pswanswer、email、qq、name、age、education、occupation、city、address、postnum字段。
login.asp的内容如下:
<html>
<body>
<form name="form1" method="post" action="9-32.asp">
<p>用户名
<input name="userid" type="text" id="userid">
</p>
<p> 口令
<input name="psw" type="password" id="psw">
</p>
<p>
<input type="submit" name="Submit" value="提交">
<input type="reset" name="Submit2" value="重置">
</p>
</form>
</body>
</html>
9-32.asp的内容如下:
<html>
<body>
<%
username=trim(request.Form("userid"))
password=trim(request.Form("psw"))
dim conn
Set conn = Server.CreateObject("ADODB.Connection")
set TmpRs=server.createobject("adodb.recordset")
conn.Open "DBQ=" & Server.MapPath("info.mdb") & _
";Driver={Microsoft Access Driver (*.mdb)};DriverId=25;FILe=MS Access;"
Set TmpRs = Server.CreateObject("ADODB.Recordset")
TmpRs.open "select * from userinfo Where userid='"&username&"';",conn,3,3
%>
<% if tmprs.EOF then %>
<script language="vbscript">
MsgBox "该用户不存在,请先注册!!!!"
location.href="javascript:history.back()"
</script>
<%else if password<>tmprs("psw") then %>
<script language="vbscript">
MsgBox "口令错误,请重新输入密码!!!!!"
location.href="javascript:history.back()"
</script>
<% else
session("username")=username
tmprs("logins")=tmprs("logins")+1
tmprs.update
response.Write tmprs("logins")
tmprs.close
set tmprs=nothing
conn.close
set conn=nothing
end if
end if
%>
</body>
</html>
4.数据库的添加及修改
例9.33 添加及修改数据库记录,文件名为9-33.asp和publish_tiezi.asp。
使用的数据库是info.mdb,其中表userinfo、composition、bbs,字段如下:
composition(topic,text,userid,length,time,owner)
bbs(owner,total,numnew,numtopic)
publish_tiezi.asp的内容:
<html>
<body>
<form name="form1" method="post" action="9-33.asp">
<p>topic
<input name="topic" type="text" id="topic">
</p>
<p>text
<textarea name="text" id="text"></textarea>
</p>
<p>owner
<input name="owner" type="text" id="owner">
</p>
<p>
<input type="submit" name="Submit" value="提交">
<input type="reset" name="Submit2" value="重置">
</p>
</form>
</body>
</html>
9-33.asp的内容:
<% if request("topic")="" then %>
<script language="vbscript">
MsgBox "主题不能为空!!!!!"
location.href="javascript:history.back()"
</script>
<%elseif request("text")="" then %>
<script language="vbscript">
MsgBox "论坛不允许灌水行为!!!!!"
location.href="javascript:history.back()"
</script>
<% else
owner=request("owner")
set cn=server.CreateObject("ADODB.connection")
DBPath=server.MapPath("info.mdb")
cn.open "driver={Microsoft Access Driver (*.mdb)};dbq="& DBPath
set com_rs=server.CreateObject("ADODB.recordset")
set bbs_rs=server.CreateObject("ADODB.recordset")
com_rs.open "Select * from composition;",cn,2,3
'表composition中添加新记录
com_rs.AddNew
com_rs("topic")=request("topic")
com_rs("text")=request("text")
‘com_rs("userid")=session.contents("username")
com_rs("length")=len(trim(request("text")))
com_rs("time")=now()
com_rs("owner")=request("owner")
com_rs.update
com_rs.close
'表bbs中修改记录内容
bbs_rs.open "Select * from bbs where owner='"&owner&"'",cn,3,3
if not bbs_rs then
bbs_rs("total")=bbs_rs("total")+1
bbs_rs("numnew")=bbs_rs("numnew")+1
bbs_rs("numtopic")=bbs_rs("numtopic")+1
bbs_rs.update
endif
response.Write,帖子已发表成功"
bbs_rs.close
end if
%>
此例中的com_rs("userid")=session.contents("username")通过在例9.32的login.asp中session("username")=username获得"username"。
5,ASP实现分页显示
ASP实现分页显示方法有很多,但主要有两种,
第一种方法是将数据库中所有符合查询条件的记录一次性的都读入 recordset 中,存放在内存中,然后通过 ADO Recordset 对象所提供的几个专门支持分页处理的属性,PageSize( 页大小 ),PageCount( 页数目 ) 以及 AbsolutePage( 绝对页 ) 来管理分页处理。
第二种方法是根据客户的指示,每次分别从符合查询条件的记录中将规定数目的记录数读取出来并显示。
两者的主要差别在于前者是一次性将所有记录都读入内存然后再根据指示来依次做判断分析从而达到分页显示的效果,而后者是先根据指示做出判断并将规定数目的符合查询条件的记录读入内存,从而直接达到分页显示的功能。
我们可以很明显的感觉到,当数据库中的记录数达到上万或更多时,第一种方法的执行效率将明显低于第二种方法,因为当每一个客户查询页面时都要将所有符合条件的记录存放在服务器内存中,然后在进行分页等处理,如果同时有超过 100 个的客户在线查询,那么 ASP 应用程序的执行效率将大受影响。但是,当服务器上数据库的记录数以及同时在线的人数并不是很多时,两者在执行效率上是相差无几的,此时一般就采用第一种方法,因为第一种方法的 ASP 程序编写相对第二种方法要简单明了得多。
要实现ASP的分页显示,首先必须了解 Reordset 对象的属性和方法,
BOF 属性:目前指标指到 RecordSet 的第一笔。
EOF 属性:目前指标指到 RecordSet 的最后一笔。
Move 方法:移动指标到 RecordSet 中的某一条记录。
AbsolutePage 属性:设定当前记录的位置是位于哪一页
AbsolutePosition 属性:目前指针在 RecordSet 中的位置。
PageCount 属性:显示 Recordset 对象包括多少“页”的数据。
PageSize 属性:显示 Recordset 对象每一页显示的记录数。
RecordCount 属性:显示 Recordset 对象记录的总数。
(1) BOF 与 EOF 属性
  如,< % if not rs.eof then,.,%>
< % if not (rs.bof and rs.eof) %>
BOF 与 EOF 都为 True:在 RecordSet 里没有任何记录。
(2) Move 方法
可以用 Move 方法移动指标到 RecordSet 中的某一笔记录,语法如下,
rs.Move NumRecords,Start
这里的“rs”为一个对象变量,表示一个想要移动当前记录位置的 Recordset 对象;“NumRecords”是一个正负数运算式,设定当前记录位置的移动数目;“start”是一个可选的项目,用来指定记录起始的标签。
所有的 Recordset 对象都支持 Move 方法,如果 NumRecords 参数大于零,当前记录位置向末尾的方向移动;如果其小于零,则当前记录位置向开头的方向移动;如果一个空的 Recordset 对象调用 Move 方法,将会产生一个错误。
MoveFirst 方法:将当前记录位置移至第一笔记录。
MoveLast 方法:将当前记录位置移至最后一笔记录。
MoveNext 方法:将当前记录位置移至下一笔记录。
MovePrevious 方法:将当前记录位置移至上一笔记录。
Move [n] 方法:移动指标到第 n 笔记录,n 由 0 算起。
(3) AbsolutePage 属性
AbsolutePage 属性设定当前记录的位置是位于哪一页的页数编号;使用 PageSize 属性将 Recordset 对象分割为逻辑上的页数,每一页的记录数为 PageSize( 除了最后一页可能会有少于 PageSize 的记录数 )。这里必须注意并不是所有的数据提供者都支持此项属性,因此使用时要小心。
与 AbsolutePosition 属性相同,AbsolutePage 属性是以 1 为起始的,若当前记录为 Recordset 的第一行记录,AbsolutePage 为 1。可以设定 AbsolutePage 属性,以移动到一个指定页的第一行记录位置。
(4)AbsolutePosition 属性
若您需要确定目前指针在 RecordSet 中的位置,您可以用 AbsolutePosition 属性。
  AbsolutePosition 属性的数值为目前指标相对於第一笔的位置,由 1 算起,即第一笔的 AbsolutePosition 为 1。
注意,在存取 RecordSet 时,无法保证 RecordSet 每次都以同样的顺序出现。
若要启用 AbsolutePosition,必须先设定为使用用户端 cursor( 指针 ),asp 码如下,
rs2.CursorLocation = 3
(5)PageCount 属性
使用 PageCount 属性,决定 Recordset 对象包括多少“页”的数据。这里的“页”是数据记录的集合,大小等于 PageSize 属性的设定,即使最后一页的记录数比 PageSize 的值少,最后一页也算是 PageCount 的一页。必须注意也并不是所有的数据提供者都支持此项属性。
(6)PageSize 属性
PageSize 属性是决定 ADO 存取数据库时如何分页显示的关键,使用它就可以决定多少记录组成一个逻辑上的“一页”。设定并建立一个页的大小,从而允许使用 AbsolutePage 属性移到其它逻辑页的第一条记录。 PageSize 属性能随时被设定。
(7)RecordCount 属性
这也是一个非常常用和重要的属性,我们常用 RecordCount 属性来找出一个 Recordset 对象包括多少条记录。
如,< % totle=RS.RecordCount %>
运用它们来达到分页显示的步骤如下:
首先,我们可以为 PageSize 属性设置一个值,从而指定从记录组中取出的构成一个页的行数;
然后通过 RecordCount 属性来确定记录的总数;再用记录总数除以 PageSize 就可得到所显示的页面总数;
最后通过 AbsolutePage 属性就能完成对指定页的访问。
例9.34 一个简单的BBS应用程序,文件名为bbs.asp。
它的数据库bbs.mdb中的表“meggase”分别有以下五个字段:
“ID”,每个帖子的自动编号;
“subject”,每个帖子的主题;
“name”,加帖用户的姓名;
“email”,用户的电子邮件地址;
“postdate”,加帖的时间。
数据库的DSN 为“bbs”。
程序如下,
<html>
<head>
<title>bbs</title>
<body>
<% 'Sub ShowList() %>
<%
PgSz=3 '设定开关,指定每一页显示的帖子数目,默认为3
Set Conn = Server.CreateObject("ADODB.Connection")
Set RS = Server.CreateObject("ADODB.RecordSet")
sql = "SELECT * FROM message order by ID DESC"
'查询所有帖子,并按帖子的ID倒序排列
Conn.Open "bbs"
RS.open sql,Conn,1,1
If RS.RecordCount=0 then
response.write "<P><center>对不起,数据库中没有相关信息!</center></P>"
else
RS.PageSize = Cint(PgSz) '设定PageSize属性的值
Total=INT(RS.recordcount / PgSz * -1)*-1 '计算可显示的页面的总数
PageNo=Request("pageno")
if PageNo="" Then
PageNo = 1
else
PageNo=PageNo+1
PageNo=PageNo-1
end if
ScrollAction = Request("ScrollAction")
if ScrollAction = "上一页" Then
PageNo=PageNo-1
end if
if ScrollAction = "下一页" Then
PageNo=PageNo+1
end if
if PageNo < 1 Then
PageNo = 1
end if
n=1
RS.AbsolutePage = PageNo
Response.Write "<CENTER>"
position=RS.PageSize*PageNo
pagebegin=position-RS.PageSize+1
if position < RS.RecordCount then
pagend=position
else
pagend= RS.RecordCount
end if
Response.Write "<P><font color='Navy'><B>数据库查询结果:</B>"
Response.Write "(共有” & RS.RecordCount & "条符合条件的信息,显示" & pagebegin&"-" & pagend&")</font></p>"
Response.Write "<TABLE WIDTH=600 BORDER=1 CELLPADDING=4 CELLSPACING=0 BGCOLOR=#FFFFFF>"
Response.Write "<TR BGCOLOR=#5FB5E2><FONT SIZE=2><TD><B>主题</B></TD><TD><B>用户</B></TD><TD><B>Email</B></TD><TD><B>发布日期</B></TD></FONT><TR BGCOLOR=#FFFFFF>"
'Do while not (RS is nothing)
RowCount = RS.PageSize
Do While Not RS.EOF and rowcount > 0
If n=1 then
Response.Write "<TR BGCOLOR=#FFFFFF>"
ELSE
Response.Write "<TR BGCOLOR=#EEEEEE>"
End If
n=1-n %>
<TD><span style="font-size:9pt"><A href='view.asp?key=<% =RS("ID")%>'><% =RS("subject")%></A></span></td>
<TD><span style="font-size:9pt"><% =RS("name")%></A></span></td>
<TD><span style="font-size:9pt"><a href="mailto:<% =RS("email")%>"><% =RS("email")%>
</a></span> </TD>
<TD><span style="font-size:9pt"><% =RS("postdate")%>
</span> </td>
</TR>
<%
RowCount = RowCount - 1
RS.MoveNext
Loop
'set RS = RS.NextRecordSet
'Loop
Conn.Close
set rs = nothing
set Conn = nothing
%>
</TABLE>
<FORM METHOD=GET ACTION="bbs.asp">
<INPUT TYPE="HIDDEN" NAME="pageno" VALUE="<% =PageNo %>">
<%
if PageNo > 1 Then
response.write "<INPUT TYPE=SUBMIT NAME='ScrollAction' VALUE='上一页'>"
end if
if RowCount = 0 and PageNo <>Total then
response.write "<INPUT TYPE=SUBMIT NAME='ScrollAction' VALUE='下一页'>"
end if
response.write "</FORM>"
End if
%>
<% 'End Sub %>
</body>
</html>
运行结果如图:

新增加:不分页显示数据库内容(简单应用)
文件display_db_dsn.asp如下:
<%
Set Conn = Server.CreateObject("ADODB.Connection")
Set RS = Server.CreateObject("ADODB.RecordSet")
sql = "SELECT * FROM message order by ID DESC"
Conn.Open "bbs" '用DSN数据源
RS.open sql,Conn,3,2
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<body>
<table width="75%" border="1">
<tr>
<td><div align="center"> 主题</div></td>
<td><div align="center">留言者</div></td>
<td><div align="center">时间 </div></td>
</tr>
<% i=1
while not rs.eof
%>
<tr>
<td> <%= rs("subject") %>&nbsp;</td>
<td><%= rs("name") %>&nbsp;</td>
<td><%= rs("postdate") %>&nbsp;</td>
</tr>
<% rs.movenext
i=i+1
wend
%>
</table>
<p>&nbsp;</p></body>
</html>
文件display_db_lessdsn.asp如下:
<%
Set Conn = Server.CreateObject("ADODB.Connection")
Set RS = Server.CreateObject("ADODB.RecordSet")
sql = "SELECT * FROM message order by ID DESC"
Conn.Open="DRIVER={Microsoft Access Driver (*.mdb)};DBQ="+server.MapPath("/bbs.mdb")
'用非DSN数据源
RS.open sql,Conn,3,2
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<body>
<table width="75%" border="1">
<tr>
<td><div align="center"> 主题</div></td>
<td><div align="center">留言者</div></td>
<td><div align="center">时间 </div></td>
</tr>
<% i=1
while not rs.eof
%>
<tr>
<td><%= rs("subject") %>&nbsp;</td>
<td><%= rs("name") %>&nbsp;</td>
<td><%= rs("postdate") %>&nbsp;</td>
</tr>
<% rs.movenext
i=i+1
wend
%>
</table>
<p>&nbsp;</p></body>
</html>