ASP编码优化技巧8则
程序员文章站
2023-01-03 22:06:38
1.声明vbscript变量在asp中,对vbscript提供了强劲的支持,能够无缝集成vbscript的函数、方法,这样给扩展asp的现有功能提供了很大便利。由于asp中...
1.声明vbscript变量
在asp中,对vbscript提供了强劲的支持,能够无缝集成vbscript的函数、方法,这样给扩展asp的现有功能提供了很大便利。由于asp中已经模糊了变量类型的概念,所以,在进行asp与vbscript交互的过程中,很多程序员也惯于不声明vbscript的变量,这样加重了服务器的解析负担,进而影响服务器的响应请求速度。
鉴于此,我们可以象在vb中强制用户进行变量声明一样在vbscript中强制用户进行变量声明。实现方法是:
在asp程序行首放置<% option explicit%>。
2.对url地址进行编码
在我们使用asp动态生成一个带参数url地址并进行跳转时,在ie中解析很正常,但在netscrape浏览时却有错误如下:
http error 400
400 bad request
due to malformed syntax, the request could not be understood by the server.
the client should not repeat the request without modifications.
解决方法是对生成的url参数使用asp内置server对象的urlencode方法进行url编码,例子如下:
<%
url="xur.asp"
var1="username=" & server.urlencode("xur")
var2="&company=" & server.urlencode("xurstudio")
var3="&phone=" & server.urlencode("021-53854336-186")
response.redirect url & "?" & var1 & var2 & var3
%>
3.清空对象
当使用完对象后,首先使用close方法来释放对象所占用的系统资源;然后设置对象值为“nothing”释放对象占用内存。下面的代码使用数据库内容建立一个下拉列表。代码示例如下:
<% mydsn="dsn=xur;uid=xur;pwd=xur"
mysql="select * from authors where au_id<100"
set conntemp=server.createobject("adodb.connection")
conntemp.open mydsn
set rstemp=conntemp.execute(mysql)
if rstemp.eof then
response.write "数据库为空"
response.write mysql
conntemp.close
set conntemp=nothing
response.end
end if%>
<%do until rstemp.eof %>
<%
rstemp.movenext
loop
rstemp.close
set rstemp=nothing
conntemp.close
set conntemp=nothing
%>
4.使用字符串建立sql查询
使用字符串来建立查询并不能加快服务器的解析速度,相反,它还会增加服务器的解析时间。但在这里仍然推荐使用字符串代替简单的查询语句来进行查询。这样做的好处是,可以迅速发现程序问题所在,从而便利高效地生成程序。示例如下:
<%mysql= ""select * "
mysql= mysql & "from publishers"
mysql= mysql & "where state='ny'"
response.write mysql
set rstemp=conntemp.execute(mysql)
rstemp.close
set rstemp=nothing
%>
5.使用case进行条件选择
在进行条件选择的时候,尽量使用case语句,避免使用if语句。使用case语句,可以使程序流程化,执行起来也比if语句来的快。示例如下:
<%
for i = 1 to 1000
n = i
response.write addsuffix(n) & "<br>"
next
%>
<%
function addsuffix(num)
numpart = right(num,1)
select case numpart
case "1"
if instr(num,"11") then
num = num & "th"
else
num = num & "st"
end if
case "2"
if instr(num,"12") then
num = num & "th"
else
num = num & "nd"
end if
case "3"
if instr(num,"13") then
num = num & "th"
else
num = num & "rd"
end if
case "4"
num = num & "th"
case else
num = num & "th"
end select
addsuffix = num
end function
%>
6.使用adovbs.inc文件中定义的常量打开记录集
打开记录集时,可以定义记录集打开的游标类型和锁定类型。在adovbs.inc文件中定义了一些常量来定义这些类型。adovbs.inc文件保存在\inetpub\iissamples\iisamples目录下面。下面列举几个常用的游标类型和锁定类型。
游标类型:adopenfowardonly游标只能向前;adopenkeyset游标可向前或者向后,如一用户添加记录,新记录不会出现在记录集中;adopendynamic游标动态随意;adopenstatic记录集不对其他用户造成的记录修改有所反映。
锁定类型:adlockreadoney不能修改记录集中的记录;adlockpessimistic在编辑一条记录时锁定它;adlockoptimstic调用记录集update方法时才锁定记录;adlockbatchopeimstic记录只能成批更新。
<!--#include virtual="/adovbs.inc" -->
<%
connectme="dsn=xur;uid=xur;pwd=xur"
sqltemp="select * from publishers where name='xur'"
set rstemp=server.createobject("adodb.recordset")
rstemp.open sqltemp, connectme, adopenstatic,adlockoptimstic
response.write rstemp.recordcount & " records in<br>" & sqltemp
rstemp.close
set rstemp=nothing
%>
7.避免在使用global.asa文件中进行对象定义
由于global.asa文件中的内容可以为站点内所有文件引用,无疑,在global.asa文件中进行对象定义可以省去很多重复工作。比如在global.asa中的application_onstart函数中进行如下定义:
<%sub application_onstart
set application("theconn")=server.createobject("adodb. connection")
end sub %>;
这样就可以在站点任何代码中做类似引用:
<%
mysql="select * from publishers where state='xur'
set rstemp=application("theconn").execute(mysql)
%>
同样地,可以在session_onstart函数中创建记录集对象
<%sub session_onstart
set session("rstemp")=server.createobject("adodb.recordset")
end sub %>
然后在站点也面中进行如下引用:
<%
mysql="select * from publishers where state='xur'
set session("rstemp")=conntemp.execute(mysql)
%>
但这样做的同时也有很大的负面影响,由于application和session变量都只有在关闭网站的时候才释放占用的资源,所以session参数会浪费大量不必要内存,而且此时application变量成为服务器性能的瓶颈。
解决方法:建立定义对象asp页面,在需要进行调用这些对象的页面上,引入这张asp页面。假设定义对象的asp页面名称为define.asp,则只要在对应asp页面中加入以下语句就能引入该页面。
<!--#include virtual="/define.asp" -->
在进行页面引进时,最好在待引进的asp文件中不要包含<%@language="vbscript"%>语句。因为在asp文件中,只能有一句由@来定义的脚本解析语言。
8.安全防护
asp提供了很好的代码保护机制,所有的asp代码都在服务器端执行而只返回给客户端代码执行结果。即便这样,在老版本的iis中还可以在文件名后面加::$data来查看asp的源代码,这已经属于web server安全范畴不在本文讨论范围内。下面提出两点简单的安全注意事项。
虽然在asp中建议引入文件以inc作为扩展名,在这里仍建议以asp作为引文件的扩展名。当这些代码在安全机制不好的web server上运行时,只需在地址栏上输入引入文件的地址(inc为扩展名),就可以浏览该引入文件的内容,这是由于在web server上,如果没有定义好解析某类型(比如inc)的动态连接库时,该文件以源码方式显示。
不要把数据库文件放在网站结构内部,这样,当恶意人士获取数据库路径后,就可以轻易获取该数据库,进而肆意更改数据库内容。比较好的做法是,为数据库建立dsn(date source name),而在进行数据库访问时直接访问该dsn。
asp提速技巧五则
技巧之一:提高使用request集合的效率
访问一个asp集合来提取一个值是费时的、占用计算资源的过程。因为这个操作包含了一系列对相关集合的搜索,这比访问一个局部变量要慢得多。因此,如果打算在页面中多次使用request集合中的一个值,应该考虑将其存贮为一个局部变量。例如将代码写成下面的形式以加快脚本引擎处理速度:
strtitle=request.form("title")
strfirstname=request.form("firstname")
strlastname=request.form("lastname")
if len(strtitle) then strtitle=strtitle & " "
if strfirstname="" then strfullname=strtitle & " " & strlastname
elseif len(strfirstname)=1 then
strfullname=strtitle & strfirstname & ". " & strlastname
else
strfullname=strtitle & strfirstname & " " & strlastname
end if
技巧之二:直接访问适当的集合
如果不是别无选择,否则不要使用strpage=request("page")的这样的形式来获取参数,因为这将按顺序搜索全部的集合—querystring、form、cookies、clientcertificate、servervarible直到发现第一个匹配值的名称。这样做比直接访问适当的集合效率低,并且是不安全的,除非能绝对保证这个值不会出现在另外一个集合中。
例如,可能希望搜索满足客户请求的web服务器名称,这通过出现在每个查询中的request.servervarables集合中寻找“server_name”来实现。然而,假如其他的集合也包含名为“server_name”的值(键名不区分大小写),当使用request("server_name")时,就会得到错误的结果。总而言之,应尽可能直接访问适当的集合。
技巧之三:在费时操作前使用response.isclientconnected属性
使用response.isclientconnected是观察用户是否仍连到服务器并正在载入asp创建的网页的有用方式。如果用户断开连接或停止下载,我们就不用再浪费服务器的资源创建网页,因为缓冲区内容将被iis丢弃。所以,对那些需要大量时间计算或资源使用较多的网页来说,值得在每一阶段都检查游览者是否已离线:
…… code to create first part of the page
if response.isclientconnected then
response.flush
else
response.end
end if
…… code to create next part of page
技巧之四:优化asp中的ado操作
通常面言,数据构成了web站点的实际内容。所以,优化ado操作以加速asp代码执行,十分有用:
a. 仅选择所需的列:当打开ado记录集时,除非需要获得所有的列,否则不应自动地使用表名(即select *)。使用单独的列意味着将减少发送到服务器或从服务器取出的数据量。即使需要使用全部列,单独地命名每个列也会获得最佳的性能,因为服务器不必再解释这些列的名字。
b. 尽可能的使用存储过程。存储过程是预先编译的程序,含有一个已经准备好的执行计划,所以比sql语句执行更快。
c. 使用适当的光标和锁定模式。如果所做的全部工作只是从记录集中读取数据,并将其显示在屏幕上,那么就使用缺省的只能前移、只读的记录集。ado用来维护记录和锁定的细节的工作越少,执行的性能就越高。
d. 使用对象变量。当遍历记录集时一个肯定能提高性能的方法是使用对象变量指向集合中的成员。例如:
while not rsgc.eof
response.write "工程名称:" & rsgc("gcmc") & "(工程代码:" & rsgc("gccode") & ")
"
rsgc.movenext
wend
可以用改写为下面的代码以加快执行:
set gcmc=rsgc("gcmc")
set gccode=rsgc("gccode")
while not rsgc.eof response.write "工程名称:" & gcmc & "(工程代码:" & gccode & ")
" rsgc.movenext
wend
新的代码建立了对象变量的引用,所以可以使用对象变量而不是实际的变量,这意味着脚本引擎的工作减少了,因为在集合中进行索引的次数变少了。
技巧五:不要混用脚本引擎
我们知道,asp页面中既可以使用vbscript,也可以使用jscript。但是在同一个页面上同时使用jscript和vbscript则是不可取的。因为服务器必须实例化并尝试缓存两个(而不是一个)脚本引擎,这在一定程度上增加了系统负担。因此,从性能上考虑,不应在同一页面中混用多种脚本引擎。
在asp中,对vbscript提供了强劲的支持,能够无缝集成vbscript的函数、方法,这样给扩展asp的现有功能提供了很大便利。由于asp中已经模糊了变量类型的概念,所以,在进行asp与vbscript交互的过程中,很多程序员也惯于不声明vbscript的变量,这样加重了服务器的解析负担,进而影响服务器的响应请求速度。
鉴于此,我们可以象在vb中强制用户进行变量声明一样在vbscript中强制用户进行变量声明。实现方法是:
在asp程序行首放置<% option explicit%>。
2.对url地址进行编码
在我们使用asp动态生成一个带参数url地址并进行跳转时,在ie中解析很正常,但在netscrape浏览时却有错误如下:
http error 400
400 bad request
due to malformed syntax, the request could not be understood by the server.
the client should not repeat the request without modifications.
解决方法是对生成的url参数使用asp内置server对象的urlencode方法进行url编码,例子如下:
<%
url="xur.asp"
var1="username=" & server.urlencode("xur")
var2="&company=" & server.urlencode("xurstudio")
var3="&phone=" & server.urlencode("021-53854336-186")
response.redirect url & "?" & var1 & var2 & var3
%>
3.清空对象
当使用完对象后,首先使用close方法来释放对象所占用的系统资源;然后设置对象值为“nothing”释放对象占用内存。下面的代码使用数据库内容建立一个下拉列表。代码示例如下:
<% mydsn="dsn=xur;uid=xur;pwd=xur"
mysql="select * from authors where au_id<100"
set conntemp=server.createobject("adodb.connection")
conntemp.open mydsn
set rstemp=conntemp.execute(mysql)
if rstemp.eof then
response.write "数据库为空"
response.write mysql
conntemp.close
set conntemp=nothing
response.end
end if%>
<%do until rstemp.eof %>
<%
rstemp.movenext
loop
rstemp.close
set rstemp=nothing
conntemp.close
set conntemp=nothing
%>
4.使用字符串建立sql查询
使用字符串来建立查询并不能加快服务器的解析速度,相反,它还会增加服务器的解析时间。但在这里仍然推荐使用字符串代替简单的查询语句来进行查询。这样做的好处是,可以迅速发现程序问题所在,从而便利高效地生成程序。示例如下:
<%mysql= ""select * "
mysql= mysql & "from publishers"
mysql= mysql & "where state='ny'"
response.write mysql
set rstemp=conntemp.execute(mysql)
rstemp.close
set rstemp=nothing
%>
5.使用case进行条件选择
在进行条件选择的时候,尽量使用case语句,避免使用if语句。使用case语句,可以使程序流程化,执行起来也比if语句来的快。示例如下:
<%
for i = 1 to 1000
n = i
response.write addsuffix(n) & "<br>"
next
%>
<%
function addsuffix(num)
numpart = right(num,1)
select case numpart
case "1"
if instr(num,"11") then
num = num & "th"
else
num = num & "st"
end if
case "2"
if instr(num,"12") then
num = num & "th"
else
num = num & "nd"
end if
case "3"
if instr(num,"13") then
num = num & "th"
else
num = num & "rd"
end if
case "4"
num = num & "th"
case else
num = num & "th"
end select
addsuffix = num
end function
%>
6.使用adovbs.inc文件中定义的常量打开记录集
打开记录集时,可以定义记录集打开的游标类型和锁定类型。在adovbs.inc文件中定义了一些常量来定义这些类型。adovbs.inc文件保存在\inetpub\iissamples\iisamples目录下面。下面列举几个常用的游标类型和锁定类型。
游标类型:adopenfowardonly游标只能向前;adopenkeyset游标可向前或者向后,如一用户添加记录,新记录不会出现在记录集中;adopendynamic游标动态随意;adopenstatic记录集不对其他用户造成的记录修改有所反映。
锁定类型:adlockreadoney不能修改记录集中的记录;adlockpessimistic在编辑一条记录时锁定它;adlockoptimstic调用记录集update方法时才锁定记录;adlockbatchopeimstic记录只能成批更新。
<!--#include virtual="/adovbs.inc" -->
<%
connectme="dsn=xur;uid=xur;pwd=xur"
sqltemp="select * from publishers where name='xur'"
set rstemp=server.createobject("adodb.recordset")
rstemp.open sqltemp, connectme, adopenstatic,adlockoptimstic
response.write rstemp.recordcount & " records in<br>" & sqltemp
rstemp.close
set rstemp=nothing
%>
7.避免在使用global.asa文件中进行对象定义
由于global.asa文件中的内容可以为站点内所有文件引用,无疑,在global.asa文件中进行对象定义可以省去很多重复工作。比如在global.asa中的application_onstart函数中进行如下定义:
<%sub application_onstart
set application("theconn")=server.createobject("adodb. connection")
end sub %>;
这样就可以在站点任何代码中做类似引用:
<%
mysql="select * from publishers where state='xur'
set rstemp=application("theconn").execute(mysql)
%>
同样地,可以在session_onstart函数中创建记录集对象
<%sub session_onstart
set session("rstemp")=server.createobject("adodb.recordset")
end sub %>
然后在站点也面中进行如下引用:
<%
mysql="select * from publishers where state='xur'
set session("rstemp")=conntemp.execute(mysql)
%>
但这样做的同时也有很大的负面影响,由于application和session变量都只有在关闭网站的时候才释放占用的资源,所以session参数会浪费大量不必要内存,而且此时application变量成为服务器性能的瓶颈。
解决方法:建立定义对象asp页面,在需要进行调用这些对象的页面上,引入这张asp页面。假设定义对象的asp页面名称为define.asp,则只要在对应asp页面中加入以下语句就能引入该页面。
<!--#include virtual="/define.asp" -->
在进行页面引进时,最好在待引进的asp文件中不要包含<%@language="vbscript"%>语句。因为在asp文件中,只能有一句由@来定义的脚本解析语言。
8.安全防护
asp提供了很好的代码保护机制,所有的asp代码都在服务器端执行而只返回给客户端代码执行结果。即便这样,在老版本的iis中还可以在文件名后面加::$data来查看asp的源代码,这已经属于web server安全范畴不在本文讨论范围内。下面提出两点简单的安全注意事项。
虽然在asp中建议引入文件以inc作为扩展名,在这里仍建议以asp作为引文件的扩展名。当这些代码在安全机制不好的web server上运行时,只需在地址栏上输入引入文件的地址(inc为扩展名),就可以浏览该引入文件的内容,这是由于在web server上,如果没有定义好解析某类型(比如inc)的动态连接库时,该文件以源码方式显示。
不要把数据库文件放在网站结构内部,这样,当恶意人士获取数据库路径后,就可以轻易获取该数据库,进而肆意更改数据库内容。比较好的做法是,为数据库建立dsn(date source name),而在进行数据库访问时直接访问该dsn。
asp提速技巧五则
技巧之一:提高使用request集合的效率
访问一个asp集合来提取一个值是费时的、占用计算资源的过程。因为这个操作包含了一系列对相关集合的搜索,这比访问一个局部变量要慢得多。因此,如果打算在页面中多次使用request集合中的一个值,应该考虑将其存贮为一个局部变量。例如将代码写成下面的形式以加快脚本引擎处理速度:
strtitle=request.form("title")
strfirstname=request.form("firstname")
strlastname=request.form("lastname")
if len(strtitle) then strtitle=strtitle & " "
if strfirstname="" then strfullname=strtitle & " " & strlastname
elseif len(strfirstname)=1 then
strfullname=strtitle & strfirstname & ". " & strlastname
else
strfullname=strtitle & strfirstname & " " & strlastname
end if
技巧之二:直接访问适当的集合
如果不是别无选择,否则不要使用strpage=request("page")的这样的形式来获取参数,因为这将按顺序搜索全部的集合—querystring、form、cookies、clientcertificate、servervarible直到发现第一个匹配值的名称。这样做比直接访问适当的集合效率低,并且是不安全的,除非能绝对保证这个值不会出现在另外一个集合中。
例如,可能希望搜索满足客户请求的web服务器名称,这通过出现在每个查询中的request.servervarables集合中寻找“server_name”来实现。然而,假如其他的集合也包含名为“server_name”的值(键名不区分大小写),当使用request("server_name")时,就会得到错误的结果。总而言之,应尽可能直接访问适当的集合。
技巧之三:在费时操作前使用response.isclientconnected属性
使用response.isclientconnected是观察用户是否仍连到服务器并正在载入asp创建的网页的有用方式。如果用户断开连接或停止下载,我们就不用再浪费服务器的资源创建网页,因为缓冲区内容将被iis丢弃。所以,对那些需要大量时间计算或资源使用较多的网页来说,值得在每一阶段都检查游览者是否已离线:
…… code to create first part of the page
if response.isclientconnected then
response.flush
else
response.end
end if
…… code to create next part of page
技巧之四:优化asp中的ado操作
通常面言,数据构成了web站点的实际内容。所以,优化ado操作以加速asp代码执行,十分有用:
a. 仅选择所需的列:当打开ado记录集时,除非需要获得所有的列,否则不应自动地使用表名(即select *)。使用单独的列意味着将减少发送到服务器或从服务器取出的数据量。即使需要使用全部列,单独地命名每个列也会获得最佳的性能,因为服务器不必再解释这些列的名字。
b. 尽可能的使用存储过程。存储过程是预先编译的程序,含有一个已经准备好的执行计划,所以比sql语句执行更快。
c. 使用适当的光标和锁定模式。如果所做的全部工作只是从记录集中读取数据,并将其显示在屏幕上,那么就使用缺省的只能前移、只读的记录集。ado用来维护记录和锁定的细节的工作越少,执行的性能就越高。
d. 使用对象变量。当遍历记录集时一个肯定能提高性能的方法是使用对象变量指向集合中的成员。例如:
while not rsgc.eof
response.write "工程名称:" & rsgc("gcmc") & "(工程代码:" & rsgc("gccode") & ")
"
rsgc.movenext
wend
可以用改写为下面的代码以加快执行:
set gcmc=rsgc("gcmc")
set gccode=rsgc("gccode")
while not rsgc.eof response.write "工程名称:" & gcmc & "(工程代码:" & gccode & ")
" rsgc.movenext
wend
新的代码建立了对象变量的引用,所以可以使用对象变量而不是实际的变量,这意味着脚本引擎的工作减少了,因为在集合中进行索引的次数变少了。
技巧五:不要混用脚本引擎
我们知道,asp页面中既可以使用vbscript,也可以使用jscript。但是在同一个页面上同时使用jscript和vbscript则是不可取的。因为服务器必须实例化并尝试缓存两个(而不是一个)脚本引擎,这在一定程度上增加了系统负担。因此,从性能上考虑,不应在同一页面中混用多种脚本引擎。
上一篇: 一些简单的ASP练习
下一篇: 南瓜籽油的功效与作用?原来南瓜籽那么厉害