分页: 150/196 第一页 上页 145 146 147 148 149 150 151 152 153 154 下页 最后页 [ 显示模式: 摘要 | 列表 ]
Jun 30
如果你希望用ASP发送E-MAIL,你需要安装一个A S P部件。有几种第三方厂商的部件你可以使用。但是在IIS4下,你可以使用CDONTS。

  虽然名字奇怪,它是很容易使用的并且性能良好。如果你希望使用它,请跟随下面步骤。

  1.检查你是否安装了SMTP服务。OPTION PACK缺省安装时是包括SMTP服务的。

  SMTP服务安装后,在你的system32目录下会有一个文件叫CDONTS.DLL。

  2.你可以用下面的简单脚本通过A S P发送E-MAIL:

  

  $#@60;%

  Dim MailObject

  Set MailObject = Server.CreateObject("CDONTS.NewMail")

  MailObject.Send "[email protected]","[email protected]","My subject","My text"

  %$#@62;

  是不是很简单?

  

  发送附件

  CDONTS的一个常用特性是用来在E-MAIL中发送附件。代码也不难写。

  $#@60;%

  Dim MailObject

  Set MailObject = Server.CreateObject("CDONTS.NewMail")

  att_file="c:\attachments\StandardPolicy.txt"

  f_name="Policy.txt"

  MailObject.From="[email protected]"

  MailObject.To="[email protected]"

  MailObject.Subject="Subject Text Here"

  MailObject.Body="Body Text Here"

  MailObject.AttachFile att_file,f_name

  MailObject.Send

  %$#@62;

  第三方厂商部件

如果你对CDONTS不满意,下面的地址清单是你可以找到的第三方厂商部件(大多数你需要花钱购买)

  Blat - http://gepasi.dbs.aber.ac.uk/softw/Blat.html

  Try Looking through: http://www.15seconds.com/
Jun 28
点击在新窗口中浏览此图片


 大嘴宋祖德又得罪人了。由于在博客里称黄家驹真实死因是因为陷入一场三角恋而引起了Beyond的强烈不满,昨天,宋祖德公司的网站被黑,首页上留下的是触目惊心的黄家驹遗像及歌迷对他的警告。对此,宋祖德表示自己并不知情,并表示这些歌迷太冲动了,自己将有可能采取法律行动。


称黄家驹陷入三角恋:坠台并非意外


6月18日,宋祖德在自己的博客中发表了一篇名为《黄家驹真实死因》的文章,其中写道黄家驹的死并不是意外,而是他为感情困扰,才殉情而死。宋祖德在文章第一段介绍了黄家驹在日本做节目时从高台坠下而死的情况,而第二段中则写道“黄家驹的死不是意外,而是因为感情困扰。”他称,黄家驹正纠缠于一场旷日持久的三角恋中,去日本演出前已经精神恍惚,所以在做那个高台游戏时让自己告别人世,“从而也彻底告别了人世的一切烦恼。一个音乐天才就这样为情而死,实在让人感慨不已。”文中还写道,黄家驹与一个自己谈了两年的女朋友感情很好,但在中途又遇到一个有夫之妇,而该女子又为他而离婚,所以他很难选择,两头为难的他,“在去日本做节目时从三米多的高台上给他提供了‘灵感’,他就这样像一片树叶一样飘下。”


歌迷反应强烈:宋祖德公司网站被黑


许多Beyond乐队和黄家驹的歌迷看到该博客后,表示了强烈不满。昨天,记者看到,宋祖德的公司网站被黑,首页上面红字写着怀念家驹,还有一张黄家驹坟墓的图片,下面都是歌迷写的对宋祖德进行警告的话语,“请不要诋毁一个与你无冤无仇的人”。“这仅仅是给你一个教训。”记者注意到,侵入宋祖德公司的歌迷还特别留下了一个网址,在那里,他们收集全体歌迷的签名来要求宋祖德对此表示公开道歉。


在百度贴吧中记者看到,很多歌迷对此发表了自己的看法。有网友发表意见说,“他就是胡说八道,应该给他点教训。”“诋毁一个已经不在人世的人,这样做太没道德了。”还有一些歌迷则认为宋祖德是在炒作自己,“他就是要做些出格的事让别人去关注他。他就是故意侮辱家驹,这样他FANS才会生气,才会去骂他,间接为他增加人气。所以大家要冷静。大家都不理他,他就没辙了。”歌迷在网上写道。
以下为被黑的网站截图:
点击在新窗口中浏览此图片


点击在新窗口中浏览此图片


点击在新窗口中浏览此图片


点击在新窗口中浏览此图片

今天下午17:00的截图



点击在新窗口中浏览此图片

今天是6月29日上午宋祖德影视公司的网站(www.szdys.com已经恢复正常)下午有被正义的"真水无香"黑掉了,截图如下:

点击在新窗口中浏览此图片
Tags:
Jun 25
技巧12:将常用数据复制到脚本变量中

  当访问ASP中的COM对象时,应该将常用对象数据复制到脚本变量中。着将减少COM方法调用。而COM方法调用代价相对比访问脚本数据更高。当访问Collection和
Dictonary对象时,这项技术也能消减高昂的查询代价。  


  通常,当准备不止一次访问一个对象数据时,应该将这个数据放当一个脚本对象中。

  这项优化的主要目标是Request变量(Form和QueryString变量)。例如,你的站点传递一个叫UserID的QueryString变量,假定在一个特定页UserID被引用十次。在ASP页面的顶部,将UserID的值赋给一个变量,来替代十次的调用Request
("UserID"),将接生9次COM调用。

  在实际中,访问COM属性或方法的昂贵代价可能比较隐蔽。下面是一个例子,显示一段普通的代码:

Foo.bar.blah.baz = Foo.bar.blah.qaz(1)
If Foo.bar.blah.zaq = Foo.bar.blah.abc Then ' ...

  下面是这段代码运行的步骤:

1. 变量Foo被解析为一个全局对象
2. 变量bar被解析为Foo的一个成员。这触发一次COM方法调用
3. 变量blash被解析为Foo.bar的一个成员。同样,这也触发一次COM方法调用
4. 变量qaz被解析为Foo.bar.blash的一个成员。对,这也触发一次COM方法调用
5. 调用 Foo.bar.blah.qaz(1)。一个或多个COM方法调用。获取图片?
6. 重复步骤1到步骤3来解析baz。系统不知道调用qaz是否会改变对象模型,所以步骤1到步骤3又执行了一次,来解析baz
7. 解析出baz是Foo.bar.blah的一个成员,执行属性put.
8. 重复步骤1到步骤3来解析zaq
9. 重复步骤1到步骤3来解析abc

  正如你所看到的,这是多么低效(并且慢)。快速的方法是按如下代码写VBScript:

Set myobj = Foo.bar.blah ' do the resolution of blah ONCE
Myobj.baz = myobj.qaz(1)
If Myobj.zaq = Myobj.abc Then '...

  如果你用的是VBScript 5.0或更后的版本,可以使用With语句:

With Foo.bar.blah
  .baz = .qaz(1)
  If .zaq = .abc Then '...
  ...
End With

  技巧13:避免使用可变数组

  尽量避免使用可变数组。既然关心性能,最好还是在数组初始化的时候就设置好它可能的最大大小。当然,这不是说你明知不需要几M的内存,但还是应该给数组分配了那么多。  


  下面的代码是一个无理使用Redim的示范:

<%
Dim MyArray()
Redim MyArray(2)
MyArray(0) = "hello"
MyArray(1) = "good-bye"
MyArray(2) = "farewell"
...
Redim Preserve MyArray(5)
MyArray(3) = "more stuff"
MyArray(4) = "even more stuff"
MyArray(5) = "yet more stuff"
%>

  简单地将数组初始化的时候定义成正确的大小(这里应该是5)远比Redim数组使它变大好。你可能会浪费一些内存(如果你最后没有用完所有的元素),但得到的是速度!

  技巧14:使用响应缓冲(Response Buffering)

  打开“响应缓冲”就可以缓冲整个页面的输出,这样可以减少向浏览器写的次数,提高了总体性能。每次写浏览器都要耗费一定的时间和资源,因此减少写浏览器次数能提高性能;同时,TCP/IP协议发送少的大块数据比发送多的小块数据效率更高。  


  有两种方法可以打开响应缓冲。首先,可以使用Internet Service Manager来打开整个应用的响应缓冲。这是推荐的方法。在IIS 4.0和IIS 5.0中,新建一个应用时,响应缓冲缺省是打开的。第二种方法:针对每个独立的ASP页面,可以通过在页面顶部放置如下代码来打开响应缓冲:

<% Response.Buffer = True %>

  这行语句必须在所有缓冲数据写之前执行(就是说,在所有HTML和通过Response.Cookies设置Cookie之前)。通常,最好是为整个应用打开响应缓冲;这样你就不用在每个ASP页面顶部写上面那条语句了。

Response.Flush

  对于响应缓冲,因为用户在看到东西之前必须等待整个页面生成,所以用户可能够感觉到ASP页面响应比较慢(虽然整体响应时间缩短了);对一个运行时间较长的页面,可以同过Response.Buffer = False 来关掉响应缓冲;但更好的策略是使用Reponse.Flush方法。这个方法把所有已经由ASP生成的HTML输出到浏览器中。例如,一个1,000行的大表,在写完100行之后,ASP可以调用Response.Flush来强制把结果写到浏览器中,这样,用户就可以在其余行生成之前先看到100行数据。这个技术能让你两全其美—响应缓冲和渐进式地在浏览器表现数据。

  (注意,在上面的1,000行表的例子中,很多浏览器在遇到</table>标记之前可能并不画出整个表。如果想让浏览器逐步显示出数据,可以将一个大表分成多个小表,然后对每个小表调用Response.Flush。新版本的IE会在下载完整个表之前显示表,并且如果指定了表的列宽,显示的速度会更快。)

  另外,当产生一个非常大的页面时,响应缓冲可能会消耗掉许多的服务器内存。这个问题也可以通过使用Response.Flush来解决。

  技巧15:脚本大块化和Response.Write语句

  VBScript语法<% = 表达式 %>把“表达式”的值写到ASP输出流中;但如果响应缓冲没有打开,每个这样的语句都会想浏览器写数据,就把网络流分成很多小的包。这样会慢。同样,零星的小段脚本和HTML导致频繁的在脚本引擎和HTML之间切换,降低了性能。因此,应该使用以下技巧:把小块内嵌表达式改成调用Response.Write。例如,在下面的例子中,每行的每个字段都向响应流中写数据,并且每行都在VBScript和HTML中切换:  


<table>
<% For Each fld in rs.Fields %>
  <th><% = fld.Name %></th>
<%
Next
While Not rs.EOF
%>
 <tr>
 <% For Each fld in rs.Fields %>
  <td><% = fld.value %></td>
 <% Next
 </tr>
 <% rs.MoveNext
Wend %>
</table>

  下面是更有效的代码,每行只向响应流中写一次。所有的代码包含在一个VBScript块中:

<table>
<%
 For each fld in rs.Fields
   Response.Write ("<th>" &amp; fld.Name &amp; "</th>" &amp; vbCrLf)
 Next
 While Not rs.EOF
  Response.Write ("<tr>")
  For Each fld in rs.Fields %>
   Response.Write("<td>" & fld.value & "</td>" & vbCrLf)
  Next
  Response.Write "</tr>"
 Wend
%>
</table>

  当响应缓冲被禁止时,这个技巧非成的有效。最好打开响应缓冲,然后再看看批量地Response.Write对性能的提高。

  技巧16:在进入长时运算之前使用Resonse.IsClientConnected

  如果用户感到不耐烦,他们可能在ASP页面计算他们的请求之前离开这个页面。如果他们点击刷新或是跳到服务器上的另一个页面,新的请求将位于ASP请求队列尾部,而中断的请求却在请求队列的中部;通常服务器在高负载情况下可能发生这种情况(服务器有很长的请求队列,同时请求次数也很多);而这种情况又使服务器的负载情况变得更加恶劣。如果用户已经断掉连接,没有必要再执行这个ASP页面(尤其当这是一个很慢、很耗资源的页面时);Response.IsClientConnected属性能检查出这种情况;如果属性返回False,就应该调用Resonse.End来结束剩余的页面。事实上,IIS 5.0使这种检查规律划--无论什么时候ASP准备执行一个新的请求,他先检查请求队列有多长;如果队列已经超过3秒钟,ASP就会检查客户端是否连接;如果客户端已经断开,ASP立即终止这个请求。可以使用AspQueueConnectionTestTime设置来调整3秒的超时。  


  如果有一个非常耗时的页面要执行,也可以在页面中检查
  Response.IsClientConnected。当响应缓冲打开时,在页面运行中使用
  Response.Flush也能给用户操作正在执行的感觉。

  注意:在IIS 4.0上,除非你先执行了Response.Write,否则Response.IsClientConnected的结果有可能不正确;如果响应缓冲已经打开,还必须先执行Response.Flush。在IIS 5.0上,就没有这个必要了, Response.IsClientConnected工作得很正常。无论任何情况,Response.IsClientConnected总要消耗一些时间,因此,只应该在执行耗时至少超过500ms的页面中执行。首要原则是,不要在一个紧密的循环中反复调用这个属性。

  技巧17:用<OBJECT>标记来实例化对象

  如果你想在Global.asa中引用一个不在所有的代码路径中使用的对象(特定的服务器 - 或应用 - 范围对象),使用<object runat=server id=objname>标记定义比用Server.CreateObject方法定义更为合适一点。因为Server.CreateObject立即创建对象,但如果过你以后不使用这个对象,则浪费了资源。<object id=objname>只是声明objname,但objname并没有真正创建;objname在第一次使用时才创建。

  技巧18:为ADO和其他组件使用类型库声明

  当使用ADO时,开发者往往通过包含adovbs.txt来访问ADO常量。这个文件必须包含在每个使用常量的页面里;而常量文件还想相当的大,大大增加了处理每页耗费的时间和资源。  



  IIS 5.0引入了绑定组件类型库的能力;允许只引用类型库一次,然后就可以在每个ASP页面中使用。每个页面不用在为编译常量文件而消耗资源;组件开发者也不用为ASP准备VBScript包含文件了。

  可以在Global.asa中放入如下语句,来访问ADO类型库:

<!-- METADATA NAME="Microsoft ActiveX Data Objects 2.5 Library"
    TYPE="TypeLib" UUID="{00000205-0000-0010-8000- 00AA006D2EA4}" -->


<!-- METADATA TYPE="TypeLib"
    FILE="C:&amp;#92;Program Files&amp;#92;Common Files&amp;#92;system&amp;#92;ado&amp;#92;msado15.dll" -->

  技巧19:在循环中避免进行字符串连接

  很多人喜欢用如下的循环生成字符串:  


s = "<table>" & vbCrLf
For Each fld in rs.Fields
  s = s & " <th>" & fld.Name & "</th> "
Next

While Not rs.EOF
  s = s & vbCrLf & " <tr>"
  For Each fld in rs.Fields
    s = s & " <td>" & fld.value & "</td> "
  Next
  s = s & " </tr>"
  rs.MoveNext
Wend

s = s & vbCrLf & "</table>" & vbCrLf
Response.Write s

  这种方法有一些问题。第一个就是在循环中连接字符串会使时间成二次方(quadratic)成长;或者说,运行这个循环的时间同记录的字段数目平方成正比。

  下面简单的例子能更清楚地看见本质:

s = ""
For i = Asc("A") to Asc("Z")
  s = s & Chr(i)
Next

  在第一次循环中,s等于"A";在第二次循环中,VBScript必须重新分配s的空间,并把字符串"AB"赋给s;在第三次循环中,又重新分配s的空间,重新赋值。在第N(26)次循环中,VBScript重新分配并复制了N次字符串给s,所以,总共是1+2+3+...+N=N*(N+1)/2次复制。

  在上面例子中,如果有100条记录,每个记录有5个字段,则内循环执行100*5=500次,所有复制和重新分配空间的次数相应的就是 500*500=250,000次;这还只是对一个很小的记录集。

  在这中情况下,可以通过用Response.Write或是内嵌脚本(<% = fld.value %>)来替换字符串连接来提高性能。如果响应缓冲已经(也应该被)打开,Response.Write只是向响应缓冲尾部添加数据,没有重新分配内存,因此非常高效。

  在一些特定的将ADO记录集转换为HTML表的情况中,可以考虑使用GetRows或GetString函数。

  如果使用JScript连接字符串,强烈推荐使用 += 操作符;就是说,用 s += "some string",不要使用 s = s + "some string"。

  技巧20:使用Server.Transfer代替Response.Redirect

  Response.Redirect告诉浏览器请求另外一页。这个函数经常用来把用户跳转到登录页面或错误页面。既然redirect强制产生新的页面请求,结果就是浏览器和Web服务器间做了两次交互,Web服务器不得不多处理一次额外的请求。IIS 5.0引入了一个新的函数:Server.Transfer;这个函数直接把运行权交给同一个服务器上的另一个页面;避免了额外的浏览器到Web服务器的交互,提高了性能。

  技巧21:在目录URL的尾部加上斜杠(/)

  如果省略了尾部的斜杠,浏览器回发送一个请求给服务器,被告知它的请求是一个目录;然后浏览器再发送一个二次请求,不过这次URL尾部加上了斜杠,然后服务器再次响应浏览器。如果一开始就给URL加上斜杠,便可以省去无用的请求;当然,为了用户友好性,你可以在显示名字时省略尾部斜杠。  


  例如,按如下的写法:

<a href=http://www.webjx.com/;; title="webjx.com">http://www.webjx.com<;;/a>

  技巧22:避免使用服务器端变量

  访问服务器端变量将使站点给服务器发送一个特殊请求,收集所有的服务器端变量,不仅仅是你所访问的那一个。
Jun 25
技巧1:将常用数据在Web服务器端缓存起来

  大部分的ASP页面都要从后台数据库中提取数据,然后将数据用HTML方式表现出来。
不管你的数据库多么快,从内存中提取数据总比从后台数据库中提取快;从本地硬盘中读取数据通常也比从数据库中快。因此,你可以通过在Web服务器端缓存数据来提高性能。  


  缓存是个典型的以空间换取时间的交易。如果你正确的缓存了数据,性能可能会突飞猛进。要想一个缓存能真正发挥效益,必须缓冲那些常用和计算复杂的数据。装满过期数据的缓冲区只能浪费内存。

  不经常变化的数据也是缓存的一个良好候选者,因为你可以不用关心同数据库中的数据保持同步。下拉列表框、引用表、小段DHTML代码,XML字符串、菜单项和站点配置变量(包括数据源名字(DSN),IP地址和Web路径)都是很好的缓存候选者。注意,不仅仅可以缓存数据本身,还可以缓存数据的表现。如果一个ASP页面很少变化,并且缓存代价比较高(比如,产品列表),可以考虑用静态HTML页面。

  技巧2:用Application对象或Session对象缓存常用数据

  ASP的Application和Session对象是一个极其方便的在内存中缓存数据的容器。你可以把数据放到Application或Session对象中,这些数据就会在整个HTTP调用中一直存在。每个用户有自己的Session对象中的数据,而Application对象中的数据可以在所有用户中共享。  


  应该在什么时候将数据装入Application或Session中呢?通常,数据在Application或Session启动的时候装入。要想在Application或Session启动的时候装入数据,需要分别在Global.asa的Application_OnStart()或Session_OnStart()中添加适当的代码;如果Global.asa中没有这两个函数,你可以手工添加。也可以在数据第一次使用的时候将其装入。要想这样,应该在ASP页面中写一些代码(或是写一个可重用的脚本函数)来检查数据是否存在并且如果数据不存在则将其装入内存。下面是一个经典的性能调整技术--Lazy Evaluation:

<%
Function GetEmploymentStatusList
 Dim d
 d = Application("EmploymentStatusList")
 If d = "" Then
   ' FetchEmploymentStatusList function (not shown)
   ' fetches data from DB, returns an Array
   d = FetchEmploymentStatusList()
   Application("EmploymentStatusList") = d
 End If
 GetEmploymentStatusList = d
End Function
%>

Similar functions could be written for each chunk of data needed.

In what format should the data be stored? Any variant type can be
stored, since all script variables are variants. For instance, you
can store strings, integers, or arrays. Often, you’ll be storing the
contents of an ADO recordset in one of these variable types. To get
data out of an ADO recordset, you can manually copy the data into
VBScript variables, one field at a time. It’s faster and easier to
use one of the ADO recordset persistence functions GetRows(),GetString
() or Save() (ADO 2.5). Full details are beyond the scope of this
article, but here’s a function that demonstrates using GetRows() to
return an array of recordset data:

' 获取记录集,返回数组
Function FetchEmploymentStatusList
 Dim rs
 Set rs = CreateObject("ADODB.Recordset")
 rs.Open "select StatusName, StatusID from EmployeeStatus", _
     "dsn=employees;uid=sa;pwd=;"
 FetchEmploymentStatusList = rs.GetRows() ' 将记录集用数组返回
 rs.Close
 Set rs = Nothing
End Function

A further refinement of the above might be to cache the HTML for the
list, rather than the array. Here’s a simple sample:

' 获取记录集,返回HTML Option列表
Function FetchEmploymentStatusList
 Dim rs, fldName, s
 Set rs = CreateObject("ADODB.Recordset")
 rs.Open "select StatusName, StatusID from EmployeeStatus", _
     "dsn=employees;uid=sa;pwd=;"
 s = "" & vbCrLf
 rs.Close
 Set rs = Nothing ' 释放rs
 FetchEmploymentStatusList = s ' 用字符串方式返回数据
End Function

  在正确情况下,你可以将ADO记录集本身缓存在Application或Session范围,但必须满足下面两个条件: .ADO必须被标记为自由线程模型(Free-threaded) .必须使用无连接记录集

  如果不能满足上面两个条件,一定不要缓存记录集。在下面的“不灵活的组件”和“不要缓存Connection”两个技巧中,我们将讨论在Application和Session中保存COM对象的危险性。

  当你在Application或Session中存储数据后,数据将一直保存,知道你的程序改变它,或是Session过期,或是Web服务重新启动。What if the data needs to be updated?手工刷新Application数据,可以调用只有管理员才可访问的用来刷新数据的ASP页面;或者定期的通过一个函数来周期性的更新数据。下面的例子在缓存数据中保存了一个时间戳,然后一段时间之后自动刷新数据。

<%
Const Update_INTERVAL = 300 ' 刷新间隔,单位是秒

'返回雇员状态列表
Function GetEmploymentStatusList
 UpdateEmploymentStatus
 GetEmploymentStatusList = Application("EmploymentStatusList")
End Function

'周期性的更新缓存中的数据
Sub UpdateEmploymentStatusList
 Dim d, strLastUpdate
 strLastUpdate = Application("LastUpdate")
 If (strLastUpdate = "") or _
    (Update_INTERVAL < DateDiff("s", strLastUpdate, Now)) Then

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

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

   ' 更新Application对象时用Application.Lock()来保持数据一致性
   Application.Lock
   Application("EmploymentStatusList") = Events
   Application("LastUpdate") = CStr(Now)
   Application.Unlock
 End If
End Sub

  要知道在Session或Application中缓存大数组并不是一个太好的方法。在访问数组中的任何元素之前,脚本解释器都需要生成一个临时的整个数组的副本。例如,如果你缓存了一个100,000个字符串元素的数组,用来将邮政编码和当地的天气对应一一起来,在访问数组中任何一个字符串之前,ASP解释器首先必须复制所有的100,000个天气情况数据到一个临时数组中。在这种情况下,开发一个组件来储存天气情况数据或是使用词典(Dictioary)对象更为合适一点。不过,也不要因小失大,数组对象的的查找速度更快。索引一个词典比索引一个数组慢。你可以因你的情况而宜,选择合适的数据结构。

  技巧3:在硬盘上缓存数据和HTML页面

  有时,可能有太多的数据缓存在内存中。“太多”是个模糊的说法,它取决与Web服务器的内存大小、缓存项的数目和这些缓存项被访问的频度。无论如何,如果太多的数据在内存中缓存,可以考虑将数据用文本或XML文件缓存到Web服务器的硬盘上。可以将缓存到硬盘上和到内存中结合起来,针对你的站点,找到最优化的策略。  


  注意,当我们测量单一ASP页面的性能时,从硬盘上读取数据可能比从数据库中读取慢。但是,缓存能够减少数据库和网络的负载。在高负载的情况下,这将大大提高总体吞吐量。当被缓存的数据是非常复杂的查询,比如多表连接或是一个复杂的查询过程或一个非常大的记录集,缓存的效果将非常明显。

  ASP和COM提供了一些工具来建立基于硬盘的缓存方案。ADO Recordset对象的Save和Open方法可以保存和装入到磁盘上。还有一些用来访问文件的组件: .Scripting.FileSystemObject允许你创建、读取和写入文件。 .MSXML,同IE捆绑的微软的XML解释器,支持保存和装入XML文档。 .LookupTable对象是一个用来从磁盘装入简单列表的非常好的选择。

  最后,将数据表现缓存在硬盘上,比缓存数据本身要好。生成的HTML可以一个.htm或.asp文件保存在硬盘上;超连可以直接指向那些文件。你也可以用一些商业工具,如XBuilder和SQL Server互连网发布特性,来生成和处理HTML文件。另外,也可以用#include将HTML片段包含到ASP文件中;还可以用FileSystemObject来读取HTML文件。

  技巧4:避免在Application或Session对象中缓存COM对象

  虽然在Application或Session对象中缓存数据是一个好注意,但缓存COM对象可能带来严重的后果。在Application或Session对象中缓存常用COM对象非常诱人,但非常不幸,很多COM对象,包括那些用VB 6.0或早期版本写的组件,如果被缓存到
Application或Session对象中将会导致严重的性能瓶颈。  


  特别地,所有非Agile的组件被缓存到Session或Application中时,都将产生性能瓶颈。Agile组件是指聚合了Free-threaded marshaler(FTM)并且线程模型是Both
(ThreadingModel=Both),或线程模型是Neutral(Netural新出现在Windows 2000
和COM+中)的组件。下面的组件都是非Agile的:


  自由线程模型组件(除非他们聚合了FTM)
  Apartment线程模型组件
  单线程组件

  Configured组件(MTS/COM+库和服务包/应用)是非Agile的,除非它们是Neutral线程模型的。Apartment线程模型组件和其他非Agile组件最好是工作在页面范围内(就是说,他们在一个单一ASP页面中创建和销毁)。

  在IIS 4.0中,线程模型是Both的组件被看作是Agile的,但在IIS 5.0中,他们不再满足Agile的条件。组件线程模型必须是Both的,并且聚合了FTM,才被看作Agile的。如果试图将一个用Server.CreateObject创建的非Agile组件存储到
Application对象中时,IIS 5.0将会抛出一个错误。

  当ADO组件被标记为自由线程模型时,ADO记录集对象可以安全地存储。可以用Makfre15.bat,一般是放在\\program Files\Common\System\ADO这个文件夹里,将ADO组件标记为自由线程模型。有一点要注意:当用Access作后台数据库时,ADO不能被标记为自由线程模型。词典(Dictionary)组件也是Agile对象。

  技巧5:不要缓存数据库连接

  缓存ADO Connection对象是一个不好的策略。如果一个Connection对象被存储在
Application对象中并被所有页面使用,所有页面就会争着使用这个连接。如果
Connection对象被存储在Session对象中,就要为每个用户创建一个数据库连接,这就消减了连接池的作用,并且增大了Web服务器和数据库服务器的压力。可以用在每个使用ADO的ASP页创建和释放ADO对象来替代缓存数据库连接;因为IIS内建了数据库连接池,所以这种方法非常有效。  


  既然有连接的记录集保存了一个数据库连接的引用,因此也不应该在Application或Session对象中保存有连接的记录集。但是,你可以安全的缓存无连接的记录集,因为它并不包含到数据连接的引用。要想挂断一个记录集,可以采取如下两个步骤:

  Set rs = Server.CreateObject("ADODB.RecordSet")
  rs.CursorLocation = adUseClient ' 第一步

  rs.Open strQuery, strProv

  ' 将记录集同数据提供者和数据源挂断
  rs.ActiveConnection = Nothing  '第二步

  技巧6:正确地使用Session对象

  我们已经提到了在Application和Session中缓存数据的好处,下面我们将说一些
Session对象的缺点。在繁忙的站点上使用Session有一些不利的地方。繁忙是指这个站点每秒钟要处理数以百计的页面请求或同时连接数以千计的并发用户。这个技巧对那些必须要水平伸缩的站点--就是说,这些站点用多个服务器来实现负载平衡或容错--非常重要。对小的站点,如公司内网,Session相对与他消耗的资源来说,还是值得一用的。  


  ASP自动为每个访问Web服务器的拥护创建一个Session对象。每个Session大约消耗10K的资源,并使所有的请求都慢了一点。这个Session在超时周期内一直存在,这个周期一般是20分钟。对于Session来说最大的问题不是性能而是伸缩能力。Session不是跨Web服务器的;一旦一个Session在某个服务器上创建,它的数据都保存在那儿。
  这意味着如果你要在多个Web服务器环境中使用Session,你必须设计一套能使用户总是访问它的Session对象所在的Web服务器的策略;即将一个用户粘到一个Web服务器上。如果Web服务器崩溃,因为Session不是永久保存在磁盘上的饿,所以全部“粘”
  在其上的用户的Session状态都将丢失。实现“粘Session(sticky session)”的策略包括硬件和软件方案,如Windows 2000 Advanced Server中的Network Load Balancing和Cisco的Local Director。当然,这些方案并不完美,都要损失一些可伸缩性。Application对象也不是跨服务器的,如果你想在多服务器间共享和更新Application数据,你必须使用一个后台数据库。但无论如何,只读Application数据在多服务器环境中还是十分有用的。

  绝大多数任务优先(mission-critical)的站点都想在至少两台Web服务器上发布--如果没有比延长正常运行时间更重要的理由的话。因此,在设计阶段,你就要实现“粘Session”,或是简单地避免Session和其他将用户状态保存在一个独立Web服务器上的状态管理技术。

  如果不使用Session,就将它们关闭;可以通过Internet Service Manager(参看ISM文档)关闭你的应用的Session功能。如果决定使用Session,就要用一些方法将他们对性能的影响减到最小。可以将不需要Session的内容(如帮助窗口等)移到一个的关闭了Session的ASP应用中。如果某个单一页面不需要Session,可以将下面的语句放在页面的顶部来禁止Session功能:

<% @EnableSessionState=False %>

  使用该语句还有一个原因是Session在帧中会产生一个有趣的问题。ASP保证任何时候一个会话只有一个请求,这就导致如果浏览器同时请求多个页面,同一时刻将只有一个ASP请求能够访问Session;这避免了访问Session对象时产生的多线程问题;但很不幸,一个帧中的多个页面只能顺序的生成,一个接着一个,而不是兵法。用户可能会为多个帧等待较长时间。所以如果帧中的某个页面没有使用Session,就在页面顶部放置<% @EnableSessionState=False %>语句。

  作为使用Session对象的替代,还有很多其他的方法来管理会话状态。对小规模的状态(小于4KB),推荐使用Cookies,QueryString变量和隐藏表单变量。对大量数据,如购物信息,一个后台数据库可能是很好的选择。

  技巧7:将代码封装到COM对象中

  如果有很多VBScript或JScript代码,可以通过将代码封装到COM对象中来提高性能。
编译过的代码通常比解释代码运行得快。COM对象可以通过“前期绑定”来访问其他COM对象,这比脚本使用的“后期绑定”更高效。  


  下面是将代码码封装到COM对象中的优点(不仅仅是性能):

  COM对象可以很好地将商业逻辑同表现逻辑分离
  COM对象使代码可重用
  用VB,C或VJ写的代码比ASP代码更易调试

  COM对象也有不足,包括开发周期长和需要不同的编程经验等。有一点尤需注意,封装少量ASP代码可能在性能上适得其反;这种情况下,创建和调用COM对象的代价超过了编译代码性能上的好处。如何组合ASP代码和COM组件代码来产生最佳性能,往往是个令人头疼的问题。注意,同Windows NT 4.0/IIS 4.0相比,Windows 2000/IIS 5.0在脚本和ADO性能上已经大大提高。

  技巧8:对资源晚获取,早释放

  通常情况下,晚获取和早释放资源是最好的。这不仅适用于COM对象,也适用于文件句柄和其他资源。ADO连接和记录集是这项优化策略的主要对象。当使用完一个Recordset对象,应该立即将它释放,而不应等到页面结束。将VBScript变量设成Nothing是最好的方法。同时,释放相关的Command和Connection对象(别忘了在将Connection对象设成Nothing之前调用Close()方法)。

  技巧9:进程外执行以性能换取可靠性

  ASP和MTS/COM+都有选项让你来用可靠性换取性能。当建立和发布你的应用时,你应该理解这项交易的内幕。  


  ASP选项

  ASP应用有三种运行方法可选择。在IIS 5.0中,引入“分离级别(isolation level)”这个术语来描述这些选项。三种分离级别分别是:低(Low),中 (Medium)和高(High)。

  低分离级 这种级别被所有版本的IIS支持,并且速度也是最快的。它在Inetinfo.exe--主要的IIS进程--中运行ASP。如果ASP应用崩溃,IIS也将崩溃。

  (在IIS 4.0中,网管必须用诸如InetMon之类的工具来监视IIS,一旦IIS停止,运行批处理文件。IIS 5.0引入了“可靠的重启(reliable restart)”,会自动重新启动失败的服务器。

  中分离级 从IIS 5.0开始引入的新级别,指进程外运行,即ASP运行在IIS进程之外。 在中分离级中,所有的ASP应用共享一个进程空间。把多个进程外应用在同个空间中运行,减少了进程的树木。中分离级是IIS 5.0的默认级别。

  高分离级 IIS 4.0和IIS 5.0都支持。高分离级也是进程外的。如果ASP崩溃了,Web服务器并不崩溃。ASP应用会在下个ASP请求到达的时候自动重启。每个被配置为高分离级的ASP应用有自己的进程空间;这将每个ASP应用保护起来。它的缺点是对每个ASP应用需要一个分离的进程;这增加了许多资源消耗。

  哪种选项是最好的。在IIS 4.0中,进程外运行将使性能急剧下降;在IIS 5.0中,许多改进使进程外ASP应用的代价降到最低。事实上,在许多测试中,IIS 5.0中的ASP进程外应用比II4 4.0中的进程内运行都快。但无论如何,在任何平台上,还是进程内(低分离级)运行能带来最佳的性能。然而,在相对低点击率或低最大吞吐量的情况下,低分离级不会带来任何益处;因此,除非每个Web服务器需要应付成千上百的页面请求,不然你不会需要用低分离级。通常,需要在多个配置下进行测试,才能决定使用哪种配置。

  注意:当在进程外运行ASP应用时(中或低分离级),ASP应用运行在NT 4上的MTS中或Windows 2000的COM+中;就是说,在NT4中,ASP应用运行在Mtx.exe中;在
Windows 2000中,ASP应用运行在DllHost.exe中。你可以在任务管理器中看到这些进程在运行。

  COM选项

  COM组件也有三种配置选项,但不完全对应于ASP的选项。COM组件可以是“无配置的(Unconfigured)”、作为一个库应用(Library Application)或是作为一个服务应用(Server Application)。“无配置的”意味着组件不注册到COM+中,组件将在调用者进程空间中运行;即“进程内”。库应用也是进程内的,但可以从COM+的服务,如安全、事务和上下文支持,中获益。服务应用则被配置成运行在自己的进程空间内。

“无配置”比库应用有一点优越性;而库应用比服务应用在性能上更优越。这是因为库应用和ASP是在同一个进程内的,而服务应用是运行在自己的进程空间里的。进程间调用比进程内调用的代价高。同样,在进程间传递如记录集这样的数据,需要在两个进程间复制所有的数据。

  缺陷!当使用COM服务应用时,要想在ASP和COM间传送数据,必须保证对象实现了“按值排列(marshall-by-valu)”,或者说MBV。实现了MBV的对象将自身从一个进程复制到另一个进程。这比下面的方法好:对象留在创建者进程,其他进程重复调用创建进程来使用对象。无连接ADO记录集是MBV,有连接记录集就不是。

  Scripting.Dictonary对象没有实现MBV,不能在进程之间传递。最后,对VB程序员的一个提示:MBV不是通过用ByVal来传递参数。MBV是原始组件作者实现的。

  怎样做?
  推荐的用可靠性换取性能的配置:

  在IIS 4.0上,用ASP的低分离级,并使用MTS服务包。
  在IIS 5.0SHANG,用ASP的中分离级,使用COM+的库应用。

  技巧10:使用Option Explicit

  在.asp文件中使用Option Explicit。该指示放在.asp文件的顶部,强制开发者在使用任何变量之前必须定义它。许多程序员认为这有助于调试程序,因为它消除了打字错误的可能(如将MyXMLString=敲成MyXLMString=)  


  另外一点可能更加重要:已定义变量比未定义的变量快。ASP每次是用名字来引用未定义变量的;而另一方面,每个已定义变量有一个序号,ASP用这个序号来引用已定义变量。既然Option Explicit强制变量定义,就保证了所有的变量都是已定义的,访问速度就更快了。

  技巧11:在子过程和函数中使用本地变量

  本地变量是那些在子过程和函数中定义的变量。在函数和子过程中,访问本地变量比访问全局变量更快。使用本地变量也使代码更干净,因此尽量使用本地变量吧。
Jun 25
LCase()
  FUNCTION: 返回字符串的小写形式
  SYNTAX: Lcase(string)
  ARGUMENTS: string is any valid string expression.
  EXAMPLE: <%
  strTest = "This is a test!"
  response.write LCase(strTest)
  %>
  RESULT: this is a test!

Left()
  FUNCTION: 返回字符串左边第length个字符以前的字符(含第length个字符).
  SYNTAX: Left(string, length)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test!"
  response.write Left(strTest, 3)
  %>
  RESULT: Thi

Len()
  FUNCTION: 返回字符串的长度.
  SYNTAX: Len(string | varName)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test!"
  response.write Len(strTest)
  %>
  RESULT: 15

LTrim()
  FUNCTION: 去掉字符串左边的空格.
  SYNTAX: LTrim(string)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = " This is a test!"
  response.write LTrim(strTest)
  %>
  RESULT: This is a test!

Mid()
  FUNCTION: 返回特定长度的字符串(从start开始,长度为length).
  SYNTAX: Mid(string, start [, length>)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test! Today is Monday."
  response.write Mid(strTest, 17, 5)
  %>
  RESULT: Today

Minute()
  FUNCTION: 返回时间的分钏.
  SYNTAX: Minute(time)
  ARGUMENTS:
  EXAMPLE: <%=Minute(#12:45:32 PM#)%>
  RESULT: 45

Month()
  FUNCTION: 返回日期.
  SYNTAX: Month(date)
  ARGUMENTS: date is any valid date expression.
  EXAMPLE: <%=Month(#08/04/99#)%>
  RESULT: 8

MonthName()
  FUNCTION: Returns a string identifying the specified month.
  SYNTAX: MonthName(month, [, Abb>)
  ARGUMENTS: month is the numeric representation for a given month; Abb (optional) is a boolean value used to display month abbreviation. True will display the abbreviated month name and False (default) will not show the abbreviation.
  EXAMPLE: <%=MonthName(Month(#08/04/99#))%>
  RESULT: August

Now()
  FUNCTION: Returns the current system date and time.
  SYNTAX: Now()
  ARGUMENTS: None
  EXAMPLE: <%=Now%>
  RESULT: 8/4/99 9:30:16 AM

Replace()
  FUNCTION: Returns a string in which a specified sub-string has been replaced with another substring a specified number of times.
  SYNTAX: Replace(strToBeSearched, strSearchFor, strReplaceWith [, start [, count [, compare>>>)
  ARGUMENTS: strToBeSearched is a string expression containing a sub-string to be replaced; strSearchFor is the string expression to search for within strToBeSearched; strReplaceWith is the string expression to replace sub-string strSearchFor; start (optional) is the numeric character position to begin search; count (optional) is a value indicating the comparision constant.
  EXAMPLE: <%
  strTest = "This is an apple!"
  response.write Replace(strTest, "apple", "orange")
  %>
  RESULT: This is an orange!

Right()
  FUNCTION: 返回字符串右边第length个字符以前的字符(含第length个字符).
  SYNTAX: Right(string, length)
  ARGUMENTS: .
  EXAMPLE: <%
  strTest = "This is an test!"
  response.write Right(strTest, 3)
  %>
  RESULT: st!

Rnd()
  FUNCTION: 产生一个随机数.
  SYNTAX: Rnd [ (number) >
  ARGUMENTS:
  EXAMPLE: <%
  Randomize()
  response.write RND()
  %>
  RESULT: 任何一个在0 到 1 之间的数

Round()
  FUNCTION: 返回按指定位数进行四舍五入的数值.
  SYNTAX: Round(expression [, numRight>)
  ARGUMENTS: numRight数字表明小数点右边有多少位进行四舍五入。如果省略,则 Round 函数返回整数.
  EXAMPLE: <%
  i = 32.45678
  response.write Round(i)
  %>
  RESULT: 32

Rtrim()
  FUNCTION: 去掉字符串右边的字符串.
  SYNTAX: Rtrim(string)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test!! "
  response.write RTrim(strTest)
  %>
  RESULT: This is a test!!

Second()
  FUNCTION: 返回秒.
  SYNTAX: Second(time)
  ARGUMENTS: .
  EXAMPLE: <%=Second(#12:34:28 PM#)%>
  RESULT: 28

StrReverse()
  FUNCTION: 反排一字符串
  SYNTAX: StrReverse(string)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test!!"
  response.write StrReverse(strTest)
  %>
  RESULT: !!tset a si sihT

Time()
  FUNCTION: 返回系统时间.
  SYNTAX: Time()
  ARGUMENTS: .
  EXAMPLE: <%=Time%>
  RESULT: 9:58:28 AM

Trim()
  FUNCTION: 去掉字符串左右的空格.
  SYNTAX: Trim(string)
  ARGUMENTS: string is any valid string expression.
  EXAMPLE: <%
  strTest = " This is a test!! "
  response.write Trim(strTest)
  %>
  RESULT: This is a test!!

UBound()
  FUNCTION: 返回指定数组维数的最大可用下标.
  SYNTAX: Ubound(arrayname [, dimension>)
  ARGUMENTS: dimension (optional) 指定返回哪一维上界的整数。1 表示第一维,2 表示第二维,以此类推。如果省略 dimension 参数,则默认值为 1.
  EXAMPLE: <%
  i = Array("Monday","Tuesday","Wednesday")
  response.write UBound(i)
  %>
  RESULT: 2

UCase()
  FUNCTION: 返回字符串的大写形式.
  SYNTAX: UCase(string)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test!!"
  response.write UCase(strTest)
  %>
  RESULT: THIS IS A TEST!!

VarType()
  FUNCTION: 返回指示变量子类型的值
  SYNTAX: VarType(varName)
  ARGUMENTS:
  EXAMPLE: <%
  i = 3
  response.write varType(i)
  %>
  RESULT: 2(数字)详见"asp常数"

WeekDay()
  FUNCTION: 返回在一周的第几天.
  SYNTAX: WeekDay(date [, firstdayofweek>)
  ARGUMENTS: .
  EXAMPLE: <%
  d = #8/4/99#
  response.write Weekday(d)
  %>
  RESULT: 4(星期三)

WeekDayName()
  FUNCTION: 返回一周第几天的名字.
  SYNTAX: WeekDayName(weekday [, Abb [, firstdayofweek>>)
  ARGUMENTS: Abb可选。Boolean 值,指明是否缩写表示星期各天的名称。如果省略, 默认值为 False,即不缩写星期各天的名称.firstdayofweek指明星期第一天的数值
  EXAMPLE: <%
  d = #8/4/99#
  response.write WeekdayName(Weekday(d))
  %>
  RESULT: Wednesday

Year()
  FUNCTION: 返回当前的年份.
  SYNTAX: Year(date)
  ARGUMENTS:
  EXAMPLE: <%=Year(#8/4/99#)%>
  RESULT: 1999
分页: 150/196 第一页 上页 145 146 147 148 149 150 151 152 153 154 下页 最后页 [ 显示模式: 摘要 | 列表 ]