本章已经讨论了两个asp对象:application对象和session对象,因此能够访问application对象和session对象提供的集合、方法、属性和事件。本节将从程序设计的角度对这两个对象进行研究。
· 当载入asp dll并响应对一个asp网页的第一个请求时,创建application对象。该对象提供一个存储场所,用来存储对于所有访问者打开的所有网页都可用的变量和对象。
· 当访问者首次从站点请求一个asp页面时,为他创建一个session对象,并保持有效直到缺省的超时周期(或由脚本确定的超时周期)。该对象提供一个存储场所,用来存储仅仅对该访问者在会话的活动期间打开的网页可用的变量和对象。
图3-12(即图1-20)给出了用户的请求和服务器的响应在会话中的分布情况。所有的会话都在asp应用程序中。 
3.3.1 asp的application对象成员概述
本节说明application对象的集合、方法和事件(application对象没有属性)。在下一节对session对象(具有属性)进行同样的说明。然后将继续探讨使用这些对象所完成的任务,更详细地说明每个对象的各成员如何进行工作。
1. application对象的集合
application对象提供了两个集合,可以用来访问存储于全局应用程序空间中的变量和对象。集合及说明如表3-3所示:
表3-3 application对象的集合及说明
集 合
说 明
contents
没有使用<object>元素定义的存储于application对象中的所有变量(及它们的值)的一个集合。包括variant数组和variant类型对象实例的引用
staticobjects
使用<object>元素定义的存储于application对象中的所有变量(及它们的值)的一个集合
2. application对象的方法
application对象的方法允许删除全局应用程序空间中的值,控制在该空间内对变量的并发访问。方法及说明如表3-4所示:
表3-4 application对象的方法及说明
方 法
说 明
contents.remove(“variable_name”)
从application.content集合中删除一个名为variable_name的变量
contents.removeall()
从application.content集合中删除所有变量
lock()
锁定application对象,使得只有当前的asp页面对内容能够进行访问。用于确保通过允许两个用户同时地读取和修改该值的方法而进行的并发操作不会破坏内容
unlock()
解除对在application对象上的asp网页的锁定
注意,在运行期间不能从application.staticobjects集合中删除变量。
3. application对象的事件
application对象提供了在它启动和结束时触发的两个事件,如表3-5所示:
表3-5 application对象的事件及说明
事 件
说 明
onstart
当asp启动时触发,在用户请求的网页执行之前和任何用户创建session对象之前。用于初始化变量、创建对象或运行其他代码
onend
当asp应用程序结束时触发。在最后一个用户会话已经结束并且该会话的onend事件中的所有代码已经执行之后发生。其结束时,应用程序中存在的所有变量被取消
3.3.2 asp的session对象成员概述
本节概述session对象的所有成员。
1. session对象的集合
session对象提供了两个集合,可以用来访问存储于用户的局部会话空间中的变量和对象。这些集合及说明如表3-6所示:
表3-6 session对象的集合及说明
集 合
说 明
contents
存储于这个特定session对象中的所有变量和其值的一个集合,并且这些变量和值没有使用<object>元素进行定义。包括variant数组和variant类型对象实例的引用
staticobjects
通过使用<object>元素定义的、存储于这个session对象中的所有变量的一个集合
2. session对象的特性
session对象提供了四个属性。这些属性及说明如表3-7所示:
表3-7 session对象的属性及说明
属 性
说 明
codepage
读/写。整型。定义用于在浏览器中显示页内容的代码页(code page)。代码页是字符集的数字值,不同的语言和场所可能使用不同的代码页。例如,ansi代码页1252用于美国英语和大多数欧洲语言。代码页932用于日文字
lcid
读/写。整型。定义发送给浏览器的页面地区标识(lcid)。lcid是唯一地标识地区的一个国际标准缩写,例如,2057定义当前地区的货币符号是'£'。lcid也可用于formatcurrency等语句中,只要其中有一个可选的lcid参数。lcid也可在asp处理指令<%…%>中设置,并优先于会话的lcid属性中的设置。本章后面提供一个asp处理指令的列表
sessionid
只读。长整型。返回这个会话的会话标识符,创建会话时,该标识符由服务器产生。只在父application对象的生存期内是唯一的,因此当一个新的应用程序启动时可重新使用
timeout
读/写。整型。为这个会话定义以分钟为单位的超时周期。如果用户在超时周期内没有进行刷新或请求一个网页,该会话结束。在各网页中根据需要可以修改。缺省值是10min。在使用率高的站点上该时间应更短
3. session对象的方法
session对象允许从用户级的会话空间删除指定值,并根据需要终止会话。seesion对象的方法及说明如表3-8所示:
表3-8 session对象的方法及说明
方 法
说 明
contents.remove(“variable_name”)
从session.content集合中删除一个名为variable_name的变量
contents.removeall()
从session.content集合中删除所有变量
abandon()
当网页的执行完成时,结束当前用户会话并撤消当前session对象。但即使在调用该方法以后,仍可访问该页中的当前会话的变量。当用户请求下一个页面时将启动一个新的会话,并建立一个新的session对象(如果存在的话)
注意,在运行期间不能从session.staticobjects集合中删除变量。
4. session对象的事件
session对象提供了在启动和结束时触发的两个事件,如表3-9所示:
表3-9 session对象的事件及说明
事 件
说 明
onstart
当asp用户会话启动时触发,在用户请求的网页执行之前。用于初始化变量、创建对象或运行其他代码。
onend
当asp用户会话结束时触发。从用户对应用程序的最后一个页面请求开始,如果已经超出预定的会话超时周期则触发该事件。当会话结束时,取消该会话中的所有变量。在代码中使用abandon方法结束asp用户会话时,也触发该事件
3.3.3 使用application和session的事件
asp的application和session对象体现了其他asp内置对象所没有的特征——事件。然而,正像在前面的对象成员表中看到的那样,这些都是asp会话和应用程序的工作相联系的事件。
1. application和session的事件处理器
每当一个应用程序或会话启动或结束时,asp触发一个事件。可以通过在一个特殊的文件中编写普通的脚本代码来检测和应答这些事件,这个文件名为global.asa,位于一个应用程序的根目录中(对于缺省的web网站是inetpubwwwroot目录,或是作为一个实际应用程序定义的一个文件夹)。这个文件可以包含一个或多个html的<object>元素,用于创建将在该应用程序或用户会话内使用的组件实例。
在第4章中将详细地介绍如何创建组件实例。下面的代码是global.asa文件的一个例子。我们只关注<object>元素以及以set关键字开始的那些代码行:
<!-- declare instance of the aspcounter component
with application-level scope //-->
<object id=”aspcounter” runat=”server” scope=”application”
progid=”mswc.counters”>
</object>
<!-- declare instance of the aspcontentlimk component
with session-level scope //-->
<object id=”aspcontentlink” runat=”server” scope=”session”
progid=”mswc.nextlink”>
</object>
<script language=”vbscript” runat=”server”>
sub application_onstart()
‘create an instance of an ado recordset with application-level scope
set application(“adoconnection”) _
= server.createobject(“adodb.connection”)
dim vararray(3) ‘create a variant array and fill it
vararray(0) = “this is a”
vararray(1) = “variant array”
vararray(2) = “stored in the”
vararray(3) = “application object”
application(“variant_array”) = vararray‘store it in the application
application(“start_time”) = cstr(now) ‘store the date/time as a string
application(“visit_count”) = 0 ‘set counter variable to zero
end sub
sub application_onend()
set application(“adoconnection”) = nothing
end sub
sub sesson_onstart()
‘create an instance of the adrotator component with session-level scope
set session(“aspadrotator”) = server.createobject(“mswc.adrotator”)
dim vararray(3) ‘create a variant arry and fill it
vararray(0) = “this is a”
vararray(1) = “variant array”
vararray(2) = “stored in the”
vararray(3) = “session object”
session(“variant_array”) = vararray ‘store it in the session
session(“start_time”) = cstr(now) ‘store the date/time as a string
‘we can access the contents of the request and response in a session_onstart
‘event handler for the page that initiated the session. this is the *only*
‘place that the asp page context is available like this.
‘as an example, we can get the ip address of the user:
session(“your_ip_address”) = request.servervariables(“remote_addr”)
application.lock
intvisits = application(“visit_count”) +1
application(“visit_count”) = intvisits
application.unlock
end sub
sub session_onend()
set session(“aspadrotator”) = nothing
end sub
</script>
因为这个global.asa文件用于本章中的示例页面,所以将需要将该文件放到web网站的根目录中,或者放到已配置为一个虚拟应用程序的目录中,并且在该目录中包含有其他示例文件。
读取和存储值
注意上面的例子怎样读取application和session的变量,与在request和response对象的集合中所采取的方式相同。设置这些变量的值:
application(“variable_name”) = variable_value
application(“variable_name”) = variant_array_variable_name
set application(“variable_name”) = object_reference
获取这些变量的值:
variable_value = application(“variable_name”)
variant_array_variable = application(“variable_name”)
set object_reference = application(“variable_name”)
当然,对于session对象可采取同样的方法。
可以看到,当从一个session事件处理器访问时,怎样“锁定”(lock)和“解锁”(unlock)该application对象;当从一个asp网页访问时,需要进行相同的处理。用application事件内的代码访问application对象中的值时,不要求这么做。这是因为在任何应用程序中只有一个application对象的实例,并且其事件处理器的代码只在没有活动的用户会话时进行。
也可以看到一个基本的用户会话计数器是如何实现的。这里使用一个应用程序级的变量visit_count,当新的会话启动时它就自动增加。 一般也不限制简单地把值保存到application或session对象中。例如,web开发者的web站点在http://webdev.wrox.co.uk上,有相应的一个global.asa文件,当一个新的会话启动时该文件就在服务器上的数据库中写入相应的条目,数据细节从request.servervariables集合中获取。这提供了一个基本的方法统计访问者的数量,并收集访问者的一些基本信息。
2. 创建variant数组
在session和application对象中创建和使用一个variant数组来存储值的方法目前尚未讨论,在这里作为一个非常有用的技术进行讨论。正如已经看到的那样,一个variant数据类型可以包含一个数组,而不仅仅是一个值。
一个数组只是在内存的一个连续区域中以指定的次序存储二进制值的一个长行。要安排variant,需要指向首项,并给出有关大小和结构的信息,脚本引擎可以做余下的事情。
可在一个variant变量中创建一维、二维或多维数组,然后把该数组分配给一个应用程序层或用户会话层的变量,并保证整个数组可在相应的地方使用。下面代码演示了一个简单的一维数组的使用技术:
dim vararray(3)
vararray(0) = “this is a”
vararray(1) = “variant array”
vararray(2) = “stored in the”
vararray(3) = “session object”
session(“variant_array”) = vararray
3. 应用程序和会话在何时启动和结束
在介绍asp应用程序和会话如何进行工作时提到过这个内容。以最基本的术语概述如下:
· 当第一个用户请求应用程序作用域内(即web网站的缺省根目录内),或者在该网站的一个子目录内的一个用户定义的虚拟应用程序的一个asp网页时,启动该应用程序。在任何用户会话启动之前发生。
· 当任意用户第一次请求在缺省应用程序或一个虚拟应用程序内的一个asp网页时,启动一个会话(如果还没一个活动的会话)。
· 当用户在会话指定的超时周期内没有下载一个asp网页时,会话结束。超时时间可以在脚本代码中使用session.timeout属性进行设置,可在properties对话框中对各个应用程序单独设置,或者通过active directory的iis:部分修改iis元数据库中的缺省值进行设置。调用session.abandon方法的一个网页完成执行以后,会话也会结束。
· 在一个应用程序中的最后一个活动会话结束以后,该应用程序立即结束。
4. asp处理指令
正如在第1章中所看到的,可以把一条处理指令增加到一个asp网页。处理指令可以根据需要包含一个以上的条目。可以在语句中使用的关键字及其说明如表3-10所示:
表3-10 asp指令关键字及说明
指令关键字
说 明
language=”language_name”
设置该网页的缺省的脚本语言,如:<% @ language=”vbscript” %>
enablesessionstate=”true”|”fasle”
当设置为“true”时,防止一个会话的cookie发送到浏览器,因此将不会创建新的session对象,任何现有会话的内容将不再可用
codepage=”code_page”
设置该网页的代码页,如<% @codepage=”1252” %>
lcid=”locale_identifier”
设置该网页的位置标识符,如<% @lcid=”2057” %>
transaction=”transaction_type”
指明该网页文件在一个事务环境下运行。有效值是:
“required”:如果已有可用的事务,脚本将在其中运行;如果没有可用的事务,启动一个新的事务。
“requires_new”:脚本将初始化一个新的事务。
“supported”:如果已有可用的事务,脚本将在其中运行;而且不启动一个新的事务。
“not_supported”:脚本将不运行于任何已有的事务中,并且不初始化一个新的事务。
在第18章中详细介绍事务。
在一个网页上只能允许有一条处理指令,并且应该放在第一行。在处理指令中可以包含不止一个这样的条目,但必须用空格进行分隔,等号两端不能有空格,例如:
<% @language=”vbscript” codepage=”1252” lcid=”2057” %>
3.3.4 活动的asp application对象
我们提供一些简单的网页,这些网页示范了使用过程中的asp application和session对象。为了能够正常使用,必须把它们放到服务器上的一个虚拟应用程序内,并且把所提供的global.asa文件放到该应用程序的根目录中。最简单的办法是把global.asa文件放到缺省web网站的根目录(缺省情况下是c:/inetpub/wwwroot)中。
对任何已有的global.asa文件重命名是一个好办法,可以在以后对该文件进行恢复。
本书的所有例子文件都可以从我们的web网站上得到,在例子的chapter03子目录中还有本章的所有其余示例网页。
在chapter03子目录中,default.asp网页是一个简单的菜单,该菜单允许运行application和session示例网页,运行屏幕如图3-13所示: 
1. 显示application集合的内容
单击第一个链接,打开名为show_application.asp的application对象示例页面。它显示了虚拟应用程序当前的application对象的内容,如图3-14所示: 
注意到aspcounter对象是staticobjects集合的一个成员(通过<object>元素进行定义),但是其余部份(由server.createobject实例化)是contents集合的成员。
可以看到使用global.asa例子网页放到这些集合中的值,这在前面已经看到:
<!-- declare instance of the aspcounter component with
application-level scope //-->
<object id=”aspcounter” runat=”server” scope=”applicatoin”
progid=”mswc.counters”>
</object>
...
...
<script language=”vbscript” runat=”server”>
sub application_onstart()
‘create an instance of an ado connection with application-level scope
set application(“adoconnection”) = server.createobject(“adodb.connection”)
dim vararray(3) ‘create a variant array and fill it
vararray(0) = “this is a”
vararray(1) = “variant array”
vararray(2) = “stored in the”
vararray(3) = “application object”
application(“variant_array”) = vararray ‘store it in thd application
application(“start_time”) = cstr(now) ‘store the date/time as a string
application(“visit_count”) = 0 ‘set counter variable to zero
end sub
...
...
</script>
(1) 遍历contents集合的代码
为了遍历contents集合,可使用一个for each ... next结构。集合中的每一项可以是一个简单的variant类型变量、一个variant数组或者一个对象的引用。因为需要对每种类型的值进行不同的处理,所以就不得不对每一个进行检查来判别其类型。
在vbscript中可使用vartype函数完成这个工作。这里使用isobject和isarray函数代替:
for each objitem in application.contents
if isobject(application.contents(objitem)) then
response.write “object reference: ‘” & objitem & “'
”
elseif isarray(application.contents(objitem)) then
response.write “array: ‘” & objitem & “' contents are:
”
vararray = application.contents(objitem)
‘note: the following only works with a one-dimensional array
for intloop = 0 to ubound(vararray)
response.write “ index(“ & intloop & “) = “ & _
vararray(intloop) & “
”
next
else
response.write “variable: ‘” & objitem & “' = “ _
& application.contents(objitem) & “
”
end if
next
注意程序如何从application对象检索该数组。将其分配给一个局部(variant)变量,使用下面的语句:
vararray = application.contents(objitem)
使用ubound函数可以查找出数组的大小(元素的数量),这个值可以作为遍历的终止条件:
for intloop = 0 ubound(vararray)
这个例子是一维数组,并将只显示这样的一个数组的内容。可根据需要编辑代码以处理多维数组,例如:
for intloop = 0 to ubound(vararray)
intnumberofdimensions = ubound(vararray, 1)
for intdimension = 0 to intnumberofdimensions
response.write “ index(“ & intloop & “) = “ _
& vararray(intloop, intdimension)
next
response.write “
”
next
(2) 遍历staticobjects集合的代码
staticobjects集合包含了所有在global.asa中使用<object>元素声明的对象引用。因为每个条目都是一个对象变量,可用简单些的代码对这个数组进行遍历。我们将输出对象的名字(在id属性中原有的定义):
for each objitem in application.staticobjects
if isobject(application.staticobjects(objitem)) then
response.write “<object> element: id='” & objitem & “'
”
end if
next
(1) 遍历contents集合的代码
为了遍历contents集合,可使用一个for each ... next结构。集合中的每一项可以是一个简单的variant类型变量、一个variant数组或者一个对象的引用。因为需要对每种类型的值进行不同的处理,所以就不得不对每一个进行检查来判别其类型。
在vbscript中可使用vartype函数完成这个工作。这里使用isobject和isarray函数代替:
for each objitem in application.contents
if isobject(application.contents(objitem)) then
response.write “object reference: ‘” & objitem & “'
”
elseif isarray(application.contents(objitem)) then
response.write “array: ‘” & objitem & “' contents are:
”
vararray = application.contents(objitem)
‘note: the following only works with a one-dimensional array
for intloop = 0 to ubound(vararray)
response.write “ index(“ & intloop & “) = “ & _
vararray(intloop) & “
”
next
else
response.write “variable: ‘” & objitem & “' = “ _
& application.contents(objitem) & “
”
end if
next
注意程序如何从application对象检索该数组。将其分配给一个局部(variant)变量,使用下面的语句:
vararray = application.contents(objitem)
使用ubound函数可以查找出数组的大小(元素的数量),这个值可以作为遍历的终止条件:
for intloop = 0 ubound(vararray)
这个例子是一维数组,并将只显示这样的一个数组的内容。可根据需要编辑代码以处理多维数组,例如:
for intloop = 0 to ubound(vararray)
intnumberofdimensions = ubound(vararray, 1)
for intdimension = 0 to intnumberofdimensions
response.write “ index(“ & intloop & “) = “ _
& vararray(intloop, intdimension)
next
response.write “
”
next
(2) 遍历staticobjects集合的代码
staticobjects集合包含了所有在global.asa中使用<object>元素声明的对象引用。因为每个条目都是一个对象变量,可用简单些的代码对这个数组进行遍历。我们将输出对象的名字(在id属性中原有的定义):
for each objitem in application.staticobjects
if isobject(application.staticobjects(objitem)) then
response.write “<object> element: id='” & objitem & “'
”
end if
next
1. 增加值到contents集合
增加值到contents集合的方法,与在global.asa网页的脚本代码中使用过的方法相同。示例网页允许把一个新的variant值增加到application对象中,并已有建议的名字和值(可根据需要进行编辑),如图3-15所示: 
单击按钮,重新载入这个网页,把值增加到application.contents集合中,并且在列表中显示,如图3-16所示: 
增加新的contents条目的代码
所有的按钮和其他html控件放置在示例网页中的一个窗体上。action设置了当前网页的路径,提交该窗体时,重新装入。method属性为“post”,所以控件中的值出现在request.form集合中。在以前的章节中采用过这两种技术:
<form action=”<% = request.servervariables(“script_name”) %>” method=”post”>
该窗体上的按钮都是普通的html input控件,具有相同的标题(三个空格)但名字不同。例如,创建第一个按钮(把值增加到application对象中)的代码是:
<input type=”submit” name=”cmdadd” value=” ”>
重新载入该网页时,检查request.form集合,判定单击的是哪个submit按钮,并进行相应的处理。如果是增加一个值到application对象的按钮(该按钮在html的<input>元素中被命名为cmdadd),使用下面的程序段:
if len(request.form("cmdadd")) then
strvarname = request.form("txtvarname")
strvarvalue = request.form("txtvarvalue")
application.lock
application("strvarname") = strvarvalue
application.unlock
end if
注意程序如何使用application.lock和application.unlock方法,确保这些值不会因两个用户并发地访问而产生混乱。如果只是对一个特定的值进行设置,一般不可能发生这种情况。但一直使用lock和unlock方法是明智的。
2. contents集合中删除值
在例子网页的底部有两个按钮,如图3-17所示: 
这两个按钮允许从application.contents集合中删除值。第一个按钮从集合中删除单个的指定值,下拉列表框显示的是contents集合值的名字的列表(记住,不能从staticobjects集合中删除值,因为它们是静态的)。
通过遍历contents集合(如前面我们所做的)执行asp网页时,创建该列表。但是,我们仅收集每项的名字并把它们放到<select>列表元素内的<option>元素中:
…
<select name=”lstremove” size=”1”>
<%
for each objitem in application.contents
response.write “<option>” & objitem & “</option>”
next
&>
</select>
…
该asp代码执行以后,在浏览器中看到的结果是:
<select name=”lstremove” size=”1”>
<option>adoconnection</option>
<option>variant_array</option>
<option>start_time</option>
<option>visit_count</option>
<option>my_new_value</option>
</select>
(1) 删除单个值
当单击按钮删除单个值时,该窗体再次提交给相同的网页,但是这一次将查找名为cmdremovethis的submit按钮。如果存在(即单击了这个按钮),则使用列表框的值,调用application.contents集合的remove方法:
if len(request.form("cmdremovethis")) then
strtoremove = request.form("lstremove")
response.write "strtoremove = " & strtoremove
application.lock
application.contents.remove(strtoremove)
application.unlock
end if
注意这是contents集合的一个方法,而不是application对象的。语法是application.contents.remove,而不是application.remove。
从contents集合中删除start_time值的结果如图3-18所示: 
(2) 删除所有的值
如果单击三个submit类型按钮中的最后一个(如图3-18所示),该网页中的代码将检测到单击的按钮为cmdremoveall,将执行application.contents集合的removeall方法:
if len(request.form("cmdremoveall")) then
application.lock
application.contents.removeall
application.unlock
end if
再次提醒,这是contents集合的一个方法,而不是application。语法是application.contents.removeall,而不是application.removeall。
图3-19所示的是从contents集合中删除所有值的结果(记住在运行时间不能从staticobjects集合删除项): 
3.3.5 活动中的asp session对象
示例网页的第二个示例页面show_session.asp,示范了如何使用session对象。可在chapter03子目录中的开始菜单(default.asp)中打开它。
1. 显示和更新session集合
session对象示例页面看起来与刚刚使用过的application对象示例页面相似。它遍历session对象的contents和staticobjects集合,显示其名字和(可能的话)相应的值。如果把这些值与application对象页面进行比较,将会看到不同之处。
这里还能够看到客户端ip地址的一些其他值。这是当会话启动时global.asa中的代码从request.servervariables集合中得到的。这个页面还显示四个会话属性的值,如图3-20所示: 
![]()
下面是例子中使用的golbal.asa文件的相关段落,它把缺省值增加到图3-20所示的屏幕上所看到的会话中:
...
<!-- declare instance of the aspcontentlink component
with session-level scope //-->
<object id="aspcontentlink" runat="server" scope="session"
progid="mswc.nextlink">
</object>
<script language="vbscript" runat="server">
...
...
sub session_onstart()
'create an instance of the adrotator component with session-level scope
set session("aspadrotator") = server.createobject("mswc.adrotator")
dim vararray(3) 'create a variant array and fill it
vararray(0) = "this is a"
vararray(1) = "variant array"
vararray(2) = "stored in the"
vararray(3) = "session object"
session("variant_array") = vararray 'store it in the session
session("start_time") = cstr(now) 'store the date/time as a string
'we can access the contents of the request and response in a session_onstart
'event handler for the page that initiated the session. this is the *only*
'place that the asp page context is available like this.
'as an example, we can get the ip address of the user:
session("your_ip_address") = request.servervariables("remote_addr")
application.lock 'prevent concurrent updates
intvisits = application("visit_count") + 1 'increment counter variable
application("visit_count") = intvisits 'store back in application
application.unlock 'release lock on application
end sub
...
...
</script>
遍历contents和staticobjects集合的代码与前面在application对象示例中使用的代码一样,只不过这里引用了session.contents和session.staticobjects集合,而不是application.contents和appliction.staticobjects集合。
靠近页面底部的按钮的功能是把值增加到session.contents集合和从session.contents集合删除值。这些按钮与在application对象示例页面中相应的按钮工作方式相同,这里访问的是session.contents集合,以及相应的remove和removeall方法。我们不再重复解释。
2. 终止一个用户会话
在session对象页面的底部有一个按钮,该按钮终止当前的用户会话,这通过调用session对象的abandon方法实现。它与其余的html控件在相同的窗体上,名为cmdabandon。当该窗体再次被提交给这个网页时,在request.form集合中查找这个值(如同在application对象例子中做的一样)。如发现这个值,则将该用户重定向到另一个网页:
if len(request.form("cmdabandon")) then
response.clear
response.redirect "abandon.asp"
response.end
end if
新的页面名为abandon.asp,十分简单,除了创建消息的文本和html以外只有如下的代码:
<% session.abandon %>
该网页的其余部分只是一个包含单个submit按钮的窗体。注意如何使用来自request.servervariables集合的引用网页(http_referer)的url的值,以确保重新载入前一个网页(session对象例子网页):
<form action="<% = request.servervariables("http_referer") %>" method="post">
<div class="subhead">your session has been terminated</div>
a new <b>session</b> will be started when you load another
asp page. it will contain any values that are defined in
the <b>global.asa</b> file for this application.
<input type="submit" name="cmdok" value=" ">
return to the previous page
</form>
结果如图3-21所示。这时,当前的用户会话已经被终止(放弃),并且该用户不能引用原先的session集合或属性的内容: 
然而,记住这一切是在调用abandon方法的网页执行时,甚至在对该方法的调用已经完成以后,仍能够从session对象中获得用户的会话内容。当此网页结束时,会话才结束。
当然,当返回到显示会话内容的session对象示例网页时,将启动一个新的asp会话。它将有一个不同的start_time值和通过执行global.asa中的代码创建的其他缺省的会话值,如图3-22所示: 
注意,session.sessionid属性值没有改变。asp试图重新分配相同的会话id,因此不能依靠该值来判定一个新的会话已经启动。
3.4 小结
本章介绍了两个asp内置对象:application和session对象。这些对象引入了asp的应用程序和用户会话的概念(两者都是特定的术语,并且不是通常谈话时的意义)。asp应用程序允许分配专门的属性给页面集,定义了iis和asp如何管理这些网页及所使用的其他组件。
然而,使用asp应用程序和会话的主要原因是需要自动地获得状态。换句话说,存储信息和变量引用的能力,要么对用户装载的所有网页是全局和可用的(即在一个应用程序中),要么仅仅对一个指定的用户的所有网页是可用的(在一个会话中)。这使建立web应用程序变得非常简单(即应用程序在web上工作,但能够像传统的编译的应用程序一样能完成指定的任务)。
本章通过一些示例页面,详细介绍如何使用asp的application和session对象。这些页面示范了这两个对象可用的所有技术。