asp 的“处理指令” <%@ 关键字 %> 给出 asp 处理 .asp 文件所需的信息。例如,以下指令将 vbscript 设置为页面的主脚本语言:
<%@ language=vbscript %>
处理指令必须位于 .asp 文件的首行。要在页面中添加多条指令,这些指令必须位于相同的分隔符内。请勿将处理指令置于由“#include”语句包括的文件内。必须在符号 @ 和关键字之间加入空格。处理指令具有以下关键字:
△language 关键字设置用于 .asp 文件的脚本语言。请参阅使用脚本语言。
△enablesessionstate 关键字指定 .asp 文件是否使用会话语句。请参阅管理会话。
△codepage 关键字设置 .asp 文件的代码页(字符编码)。
△lcid 关键字设置文件的位置表示符。
△transaction 关键字指定 .asp 文件将在事务环境下运行。请参阅了解事务。
要点:可以在一条指令中包含多个关键字。关键字/值对必须由空格分开。等号两边不要留有空格。 以下示例既设置了脚本语言也设置了代码页:
<%@ language=”jscript” codepage=”932″ %>
在服务器上使用 vbscript 和 asp 时,将禁用两个 vbscript 特性。因为使用 active server pages 编写的脚本在服务器上执行,所以不支持用来提供用户界面元素的 vbscript 语句 inputbox 和 msgbox。另外,不要在服务器端脚本中使用 vbscript 函数 createobject 和 getobject。而应使用 server.createobject,以便 asp 可以跟踪对象例程。由 createobject 语句或 getobject 语句创建的对象既不能访问 asp 内建的对象,也不能参与事务。
因为 asp 中的所有脚本都在服务器端进行处理,所以,没有必要包含 html 注释标记,用来对不支持脚本的浏览器隐藏脚本,这是客户端脚本的通常做法。所有 asp 命令都将在内容发送到浏览器之前处理。可以使用 html 注释向 html 页中添加备注;这些注释将被返回给浏览器,如果用户查看 html 源文件,将可以看到这些注释。vbscript 支持撇号格式的注释。与 html 注释不同,处理脚本时将删除这些注释并且不会发送到浏览器。
输出表达式中不能包含注释。例如,下面第一行能正常工作,而第二行则无法工作,因为该行以 <%= 开始。
<% i = i +1 ’此语句用来递增 i 值。(此脚本会工作。) %>
<%= name ’此语句用来打印变量名。(此脚本将失败。) %>
可以在 .asp 文件中使用 vbscript“option explicit”语句,以便要求必须使用“dim”、“private”、“public”和“redim”语句显式声明变量。“option explicit”语句必须位于任何 asp 命令、任何 html 文本或脚本命令之前。例如:
<% option explicit %>
<html>
<%
dim strusername
public lngaccountnumber
%>
注意:将变量范围限制到过程中有利于提高性能。
有必要养成显式声明所有变量的习惯。这一点当使用“#include”语句在 .asp 文件中包含其他文件时尤其重要。被包含的脚本虽然在单独的文件中,但却当作是包含文件的一部分。除非声明变量,否则很容易忘记必须在主脚本和被包含脚本中使用不同的变量名。
如果在脚本中要多次参考 session 作用域变量,可以考虑将该变量赋给一个局部变量以便提高性能。 同样地,如果脚本重复参考 application 作用域变量,应将该变量赋给局部变量以便提高性能。
可以定义自己的常量。在 vbscript 中,使用“const”语句。在 jscript 中,可以使用“var”语句将常量值赋给变量。如果要在多个 .asp 文件中使用常量,则需要将定义放在单独文件中,并在所有使用该常量的 .asp 文件中包含这些定义。
将服务器端脚本语句散布到客户端脚本(由 html <script> 标记括起),可以在请求时动态初始化和更改客户端脚本,用来配置客户端数据库或 dhtml 个性化脚本。创造性地运用这项技术还可以减少往返次数和服务器处理。
对首要脚本语言之外其他语言的过程使用 <script> 元素。当使用 html <script> 标签时,必须使用两个属性以便确保服务器端能够处理脚本。使用 <script> 标签的语法为:
<script language=jscript runat=server>
过程定义
</script>
脚本块中的命令必须以所选脚本语言中形成一个或多个过程。例如,下列命令定义 jscript 过程“myfunction”。
<html>
<script language=jscript runat=server >
function myfunction() { response.write(“您调用了 myfunction()。”) }
</script>
要点:不要在服务器端 <script> 标签内包含任何完整过程以外的脚本命令。过程以外的命令没有固定的执行顺序,因此可能导致无法预知的结果。另外,在过程中不能使用 asp 输出命令 <%= %>。不过,可以通过 response.write 将内容发送到浏览器。
对于 vbscript,调用过程时也可以使用关键字 call。不过,如果调用的过程要求变量,则变量列表必须包含在括号内。如果省略关键字 call,同时也必须省略包含变量列表的括号。如果使用 call 语句调用任何内置函数或用户定义函数,将丢弃函数的返回值。
要将整个数组传递给过程,在 vbscript 中,数组名后应紧接一对空括号.
设计优秀的 web 表单通常包含客户端脚本,以便在将信息发送到服务器之前验证用户输入。“验证脚本”可以检查许多事情,如用户输入值是否有效或者文本框是否为空。您可能需要验证用户是否在相应表单字段中输入了数字或文本信息,以防将潜在的无效信息发送到服务器。
通常,在客户端尽可能多地验证表单数据将非常有好处。除了能尽快提示用户输入错误外,客户端验证能提高响应速度、减少服务器负担并为其他应用程序释放带宽。
为了提高交互性,可以将错误信息放到无效信息所在的表单字段旁边,以便于用户发现出错的地方。(通常,基于 web 的表单将请求转发给包含错误信息的单独的 web 页。不能立即理解此信息的用户可能会灰心。)
由于通常无法得知集合中所存储的项目数,asp 支持集合的 count 属性,该属性返回集合中的项目个数。可以使用 count 属性指定计数器的最大值。
要使通过“for”语句使用 count 属性变得更为高效,应将 count 值分配给本地变量,并用该变量来设置计数器的最大值。这样,脚本引擎就不必每次循环都去查找 count 值。
<%
’声明计数器变量。
dim lngitem, lngcount
lngcount = session.contents.count
’重复该循环直到集合中的计数器等于项目个数。
for lngitem = 1 to lngcount
response.write session.contents(lngitem) & “<br>”
next
%>
脚本可在单个 cookie 中嵌入多个关联值,以便减少在浏览器和 web 服务器之间传递的 cookie 数目。request 和 response 对象的 cookies 集合可在单个项目中载有多个值。这些子项目或子关键字可单独使用。只有 request.cookies 和 response.cookies 集合支持子关键字。request.cookies 仅支持读操作,response.cookies 仅支持写操作。
下面将创建一个普通 cookie 和一个带子关键字的 cookie:
<%
’将 cookie 发送到浏览器。
response.cookies(“fruit”) = “pineapple”
’用子关键字将 cookie 发送到浏览器。
response.cookies(“mammals”)(“elephant”) = “african”
response.cookies(“mammals”)(“dolphin”) = “bottlenosed”
%>
发送到浏览器的 http 响应中的 cookie 文本显示如下:
http_cookie= mammals=elephant=african&dolphin=bottlenosed; fruit=pineapple;
可以列举出 request.cookies 集合中的所有 cookies 和 cookies 中的所有子关键字。不过,对不存在子关键字的 cookie 迭代子关键字将无法生成项目。要避免出现这种情况,请先检查 cookie 的子关键字是否是使用 cookies 集合的 haskeys 属性得到的。这一技巧将在下面的示例中加以说明。
<%
’声明计数器变量。
dim cookie, subkey
’显示整个 cookie 集合。
for each cookie in request.cookies
response.write cookie
if request.cookies(cookie).haskeys then
response.write “<br>”
’显示子关键字。
for each subkey in request.cookies(cookie)
response.write ” ->” & subkey & ” = ” & request.cookies(cookie)(subkey) & “<br>”
next
else
response.write ” = ” & request.cookies(cookie) & “<br>”
end if
next
%>
该脚本将返回以下结果:
mammals
->elephant = african
->dolphin = bottlenosed
fruit = pineapple
尽管 asp 集合与 visual basic 中的 collection 对象十分类似,但它们仍有一些区别。asp 集合支持 count 属性以及 item、remove 和 removeall 方法,但它们不支持 add 方法。
querystring 集合有一个可选参数,可用来访问 url 请求中出现的多个值中的单个值(使用 get 方法)。也可以使用 count 属性来计算特定类型值出现的次数。
例如,包含多项目列表框的表单可生成下面的请求:
http://organicfoods/list.asp?food=apples&food=olives&food=bread
可以使用下面的命令计算多个值:
request.querystring(“food”).count
要显示多个值类型,可在 list.asp 中包含下面的脚本:
<%
lngtotal = request.querystring(“food”).count
for i = 1 to lngtotal
response.write request.querystring(“food”)(i) & “<br>”
next
%>
前述脚本将显示为:
apples
olives
bread
要将整个值列表显示为用都逗号分隔的字符串,可以使用下面的脚本:
<% response.write request.querystring(“food”) %>
将显示下面的字符串:
apples,olives,bread
有时,可能需要使用 html <script></script> 标签来包含服务器端文件。例如,下面的脚本包含服务器可以执行的文件(使用相对路径):
<script language=”vbscript” runat=server src=”utils\datasrt.inc”></script>
注意 当使用此方法包含文件时不要在 <script> 标签内放置任何程序逻辑;使用另外一组 <script> 标签来添加这样的逻辑。
使用脚本创建 com 组件
asp 支持 windows script components,这是 microsoft 提供的用来创建 com 组件的功能强大的脚本技术。尤其是,您可以将用于数据库访问或内容生成等的通用脚本封装在可重复利用的组件中,以便在任何 .asp 文件或程序中使用。无需特殊的开发工具,使用 vbscript 或 jscript 编写脚本即可创建 windows 脚本组件。也可以将 windows 脚本组件与使用 com 兼容编程语言编写的程序相结合,如 visual basic、c++ 或 java 等。
下面是一个用 vbscript 编写的脚本示例,它定义了将华氏温度值转换为摄氏温度值的方法:
<scriptlet>
<registration
description=”converttemp”
progid=”converttemp.scriptlet”
version=”1.00″
>
</registration>
<implements id=automation type=automation>
<method name=celsius>
<parameter name=f/>
</method>
<method name=fahrenheit>
<parameter name=c/>
</method>
</implements>
<script language=vbscript>
function celsius(f)
celsius = 5/9 * (f – 32)
end function
function fahrenheit(c)
fahrenheit = (9/5 * c) + 32
end function
</script>
</scriptlet>
在执行该 windows 脚本组件之前,必须以 .sct 为扩展名保存该文件,然后在“windows 资源管理器”中,右键单击该文件并选择“注册”。要在 web 页中使用该 windows 脚本组件,应使用类似以下所示的服务器端脚本:
<%
option explicit
dim objconvert
dim sngfvalue, sngcvalue
sngfvalue = 50
sngcvalue = 21
set objconvert = server.createobject(“converttemp.scriptlet”)
%>
<%= sngfvalue %> degrees fahrenheit is equivalent to <%= objconvert.celsius(sngfvalue) %> degrees celsius<br>
<%= sngcvalue %> degrees celsius is equivalent to <%= objconvert.fahrenheit(sngcvalue) %> degrees fahrenheit<br>
通常,应避免在循环中创建对象。如果必须在循环中创建对象,则需要手工释放该对象使用的资源:
<%
dim objad
for i = 0 to 1000
set objad = server.createobject(“mswc.adrotator”)
……
objad.getadvertisement
……
set objad = nothing
next
%>
提供对象 session 作用域
session-scope 对象是为应用程序中的每个新会话创建的,并且在会话结束后释放;因此,每个活动会话都有一个对象。session 作用域用于那些由多个脚本调用但只影响一个用户会话的对象。只应在必要时提供对象 session 作用域。如果使用 session 作用域,则必须知道提供对象的组件的线程模型,这是因为线程模型影响对象的性能和安全环境。详细信息,请参阅本主题中的高级信息:性能问题。
要提供对象 session 作用域,可将对象存储在 asp 的 session 内建对象中。可以通过在 global.asa 文件中使用 html <object> 标签或在 asp 页中使用 server.createobject 方法来创建 session 作用域对象例程。
在 global.asa 文件中,可以使用 <object> 标签,并扩展 runat 属性(必须设置为 server)和 scope 属性(必须设置为 session)。下面的例子将创建“浏览器能力”组件的 browser type 对象的 session 作用域实例:
<object runat=server scope=session id=mybrowser progid=”mswc.browsertype”>
</object>
当对象已经存储在 session 对象中后,即可从应用程序的任何页访问该对象。下面语句使用在前例中通过 <object> 标签创建的对象实例:
<%= if mybrowser.browser = “ie” and mybrowser.majorver >= 4 then . . .%>
在 asp 页中,也可以使用 server.createobject 方法将对象存储到 session 内建的对象中。下面的示例将 browser type 对象的一个实例存储到 session 对象中。
<% set session(“mybrowser”) = server.createobject(“mswc.browsertype”) %>
要在其他 .asp 文件中显示浏览器信息,必须首先检索 session 对象中存储的 browsertype 对象的实例,然后调用 browser 方法来显示浏览器名称。
<% set mybrowser = session(“mybrowser”) %>
<%= mybrowser.browser %>
对于通过 <object> 标签声明的对象,在 .asp 文件脚本命令参照该对象之前 asp 不会对其实例化。server.createobject 方法可立即实例化对象。因此,对于 session 作用域对象来说,<object> 标签可以比 server.createobject 方法提供更好的伸缩性。
session 和 application 作用域的替代方案
通常,对于那些初始化时间很长的项目或对象,如字典对象或记录集,应尽可能地使用session 和 application 作用域。不过,如果 session 或 application 状态的对象占用太多的资源,如内存或数据库连接,则应寻求其他方案来实施这些对象。例如,组件的线程模型会影响从该组件创建的对象性能,尤其是具有 session 和 application 作用域的对象的性能。
在许多情况下,比创建 session 或 application 作用域对象更好的方案就是使用 session 或 application 作用域变量,这些变量可以将信息传递给在页面级创建的对象。例如,不应对 ado 的 connection 对象提供 session 或 application 作用域,因为该对象创建的连接会长时间保持打开状态,而且脚本不再利用连接池。不过,可以在“session”或“application”内建的对象中存储 odbc 或 ole db 连接字符串,并访问该字符串以便为在页面上创建的“connection”对象实例设置属性。这样,可以将经常使用的信息存储为 session 或 application 状态,而且只在需要时才创建使用该信息的对象。
如果在内容或头部返回到浏览器之后使用 response.redirect,就会看到一条错误消息。可以使用 response.buffer=true 命令将输入到浏览器的内容缓存来解决。默认情况下,对 asp 应用程序开启缓冲功能。
可以使用 server.transfer 方法而不是 response.redirect 方法从一个 .asp 文件传输到位于同一服务器上的另一个文件中。使用 server.transfer 可以直接传输 .asp 文件请求而不必离开服务器队列,这样可以节省昂贵的往返代价。
例如,下面的脚本演示了如何使用 server.transfer 在依赖于状态信息的应用程序页面之间跳转:
<%
if session(“blnsalecompleted”) then
server.transfer(“/order/thankyou.asp”)
else
server.transfer(“/order/moreinfo.asp”)
end if
%>
server.transfer 将请求从一个正在执行的 .asp 文件发送到另一个文件中。在传输过程中,原来请求的 .asp 文件立即终止执行,但并不清除输出缓冲。请求信息然后在目标文件中变得可用并开始执行。在执行过程中,该文件与原来请求的文件访问同一组内部对象(request、response、server、session 和 application)。
asp 还提供 server.execute 命令,可以用来传输给文件、执行其内容,然后再返回到启动传输的文件。如果熟悉 vbscript,这样就有助于将 server.execute 与过程调用进行类比,只不过是过程调用执行一个过程,而 server.execute 则是执行一个完整的 .asp 文件。
例如,下面的脚本演示了如何使用 server.execute 来进行 .asp 文件的动态包含:
<%
if blnusedhtml then
server.execute(“dhtml.asp”)
else
server.execute(“html.asp”)
end if
%>
只要目标文件属于同一服务器上的某个应用程序,原始应用程序将转到该文件并执行它的内容,然后继续执行启动转换的那个文件。正象 server.transfer 一样,被执行的 .asp 文件的行为就象它是原始应用程序的一部分。
用户第一次请求特定应用程序内的 .asp 文件时,asp 将生成一个“sessionid”。这是通过复杂算法产生的数值,sessionid 唯一标识每个用户的会话。新会话开始时,服务器将 session id 作为 cookie 存储到用户 web 浏览器中。
asp 每次收到网页请求时,都检查 http 请求头文件内的 sessionid cookie。
只要服务器收到的请求中不包含有效的 sessionid cookie,就将自动启动新会话。
如果确定 asp 应用程序不需要会话管理,则可以禁止 asp 跟踪会话和向用户发送 sessionid cookie。
在下列情况下,asp 将不会发送会话 cookie,应用程序禁用会话状态,asp 页定义为无会话:
<%@ enablesessionstate=false %>
应将该脚本置于 .asp 文件第一行,在其他任何脚本之前。
如确实希望结束会话,可以使用“session”对象的 abandon 方法。例如,可以在窗体中提供“退出”按钮,在该窗体中对包含下列命令的 .asp 文件 url 设置 action 参数。
<% session.abandon %>
可以使用“connection”对象建立数据库连接,也可以直接使用“recordset”对象的“open”方法来建立链接,后一种方法使用ado的默认连接属性。如下是后一种方法的示例:
<%
strconnectionstring = “provider=microsoft.jet.oledb.4.0;data source=c:\data\employees.mdb”
strsql = “select firstname, lastname from customers where lastname = ’smith’ ”
set rstcustomers = server.createobject(“adodb.recordset”)
’使用 open 方法打开连接,并使用通过 connection 对象建立的连接。
rstcustomers.open strsql, strconnectionstring
’遍历记录集,显示结果,并使用 movenext 方法递增记录位置。
set objfirstname = rstcustomers(“firstname”)
set objlastname = rstcustomers(“lastname”)
do until rstcustomers.eof
response.write objfirstname & ” ” & objlastname & “<br>”
rstcustomers.movenext
loop
%>