Tag Archives: ASP - Page 2

[ASP] 《在JScript中使用缓存技术》补遗

《在JScript中使用缓存技术》一文中,在JScript中实现了基于Application.StaticObjects的缓存技术,并且实现一个类用于缓存的操作,但在实际使用过程中仍需要注意一些问题。

在JScript的函数中,如果参数类型是number或者string,那么是按值传递的,但如果是object,那么就是按引用传递了。另外,数组在JScript中也是作为一个特殊的对象对待,因此,数组的类型也是object,同样是按引用传递的。

使用xbsCache类进行保存和获取数据操作即put和get时,不管是按值还是按引用,都没有问题,但是在使用过程中,对数据操作的效果由数据类型不同而不同。

如果数据是number或string类型的,那么在get数据时,返回值是按值的,也就是说,我们得到的数据是缓存数据的一份copy,对变量的操作并不会影响到缓存中的数据,例:

  • // code by xujiwei
  • // from www.xujiwei.cn
  • var myname=”my name is xujiwei”;
  • xbsCache.put(“name”,myname);
  • // 从缓存中获取name,值为”my name is xujiwei”
  • var myname2=xbsCache.get(“name”);
  • // 给myname2赋值”xujiwei”
  • myname2=”xujiwei”;
  • // 从缓存中获取name,值仍为”my name is xujiwei”
  • var myname3=xbsCache.get(“name”);

但是在数据类型为object的情况下,我们就需要注意,在从缓存中获取数据之后,我们得到的只是一个指向缓存数据的引用而已,并不是缓存数据的copy,因此,对数据的修改是直接影响到缓存的,例:

  • // code by xujiwei
  • // from www.xujiwei.cn
  • // 构建一个myname对象,具有属性Name,值为”my name is xujiwei”
  • var myname={Name:”my name is xujiwei”};
  • xbsCache.put(“name”,myname);
  • // 从缓存中获取name,Name属性值为”my name is xujiwei”
  • var myname2=xbsCache.get(“name”);
  • // 给myname2赋值”xujiwei”
  • myname2.Name=”xujiwei”;
  • // 从缓存中获取name,Name属性值变为”xujiwei”
  • var myname3=xbsCache.get(“name”);

由于数据类型不同而引起的这两种情况,在使用缓存时需要分别对待,如果需要会对缓存中object类型数据进行修改,应该设置一个标志变量,以免对数据重复进行修改,从而破坏了数据的准确性。

[ASP] 在JScript中使用缓存技术

在编写ASP程序时,通常为了提高ASP程序的运行效率及减少对数据库的连接和查询,会使用缓存技术来缓存一些需要从数据库读取的数据。而在ASP中实现缓存的方法常用的就是使用Application对象。在编写ASP程序时,我们有两种语言可以选择,分别是VBScript和JScript。

在使用VBScript时,我们可以用Application缓存数组来实现缓存,例:

  • Dim rs,arr
  • rs.Open conn,sql,1,1
  • arr=rs.GetRows()
  • Application.Lock()
  • Application(“cache”)=arr
  • Applicatoin.UnLock()

在VBScript里,数组是可以存到Application对象里的,但是如果ASP的语言选择为JScript的话,那么就有些不妙了,我们在使用Application储存一个数组时,会出现以下错误:

Application object, ASP 0197 (0×80004005) Disallowed object use Cannot add object with apartment model behavior to the application intrinsic object.

在微软的知识库可以找到具体原因如下:

JScript arrays are considered to be ”Apartment” COM components. Only Component Object Model (COM) components that aggregate the Free Threaded Marshaler (FTM) can be assigned to Application scope within an Internet Information Server (IIS) 5.0 ASP page. Because an ”Apartment” component cannot aggregate the FTM (it cannot allow a direct pointer to be passed to its clients, unlike a ”Both with FTM” object), JScript arrays do not aggregate the FTM. Therefore, JScript arrays cannot be assigned to Application scope from an ASP page.

以上描述引用自:PRB: Error When You Store a JScript Array in Application Scope in IIS 5.0

因此,为了解决这个问题,在Google里找了一大会,终于找到了一篇文章《Application对象的Contents和StaticObjects做Cache的一些结论》,解决了这个问题,方法就是使用Application.StaticObject存放一个Scripting.Dictionary对象,然后再使用Scripting.Dictionary对象来存放需要缓存的数据。

据此,写了一个操作缓存的类,实现put、get、remove和clear方法,使用之前,需要在global.asa中添加一个object:

  • <object id=”xbsCache” runat=”server” scope=”Application” progid=”Scripting.Dictionary”></object>

类的实现如下:

  • <script language=”JScript” runat=”server”>
  • /**
  • Title: cache operate class
  • Description: operate system cache
  • @Copyright: Copyright (c) 2007
  • @Author: xujiwei
  • @Website: http://www.xujiwei.cn/
  • @Version: 1.0
  • @Time: 2007-06-29 12:03:45
  • **/
  • var xbsCache = {
  • get: function(key) {
  • return Application.StaticObjects(“xbsCache”).Item(“Cache.”+key);
  • },
  • put: function(key, data) {
  • Application.Lock();
  • Application.StaticObjects(“xbsCache”).Item(“Cache.”+key)=data;
  • Application.UnLock();
  • },
  • remove: function(key) {
  • Application.Lock();
  • Application.StaticObjects(“xbsCache”).Remove(“Cache.”+key);
  • Application.UnLock();
  • },
  • clear: function() {
  • Application.Lock();
  • Application.StaticObjects(“xbsCache”).RemoveAll();
  • Application.UnLock();
  • }
  • }
  • </script>

如此,就完成了ASP中使用JScript时的缓存实现。

使用VS2005调试ASP程序

很早之前就在PJ的blog上看到可以用VS2005调试ASP程序,但是没有写出具体的步骤,后来一次偶尔也让我找到了方法,但是一直没把它写出来,今天就把用VS2005调试ASP程序的方法写出来,希望对写ASP程序的朋友们有用。

首先需要说明的是,我所用的环境是Win2003+IIS6,PJ用的环境是Vista+IIS7+WPF,不过我想WPF应该是无关紧要的,主要是服务器支持服务端脚本调试。在此我以IIS6为例说明怎样开启服务端脚本调试。

先打开“Internet 信息服务(IIS)管理器”,找到要开启服务端脚本调试的网站,进入属性页,进入“主目录”选项卡,点击“应用程序设置”中的“配置”,进入应用程序配置,进入“调试”选项卡,选中“启用ASP服务端脚本调试(E)”,确定即可。

图片附件

配置完IIS之后,就需要用VS2005来调试程序了。当然安装VS2005是必须的步骤,这里就不多说了。

使用VS2005调试ASP程序可以在两种情况下使用,一是程序出错时调试,一是手工加载调试。

如果想在ASP程序出错时才用VS2005进行调试,那么可以在装完VS2005之后直接测试ASP程序,如果程序出现错误,会自动提示是否使用VS2005进行调试。

图片附件

一个测试ASP程序,a=1,b=0,因此会有除0的错误,提示是否使用VS2005调试,选择是,使用新实例,如果已经打开了VS2005,则也可以直接用已经存在的实例来调试

图片附件

错误信息,可以选择中断或者继续

图片附件

中断,光标停在出错行,下部用红框标出的是变量监视窗口,可以查看当前上下文中的变量

另一种情况是在还没出错的情况下进行调试,这时需要先在浏览器中访问过需要调试的文件,因为这样ASP代码才会载入内存,然后打开VS2005,选择菜单中“工具->附加到进程”,然后选择w3wp.exe,如果在进程列表中没有找到w3wp.exe,可能是因为你还没有运行过ASP程序。

图片附件

这时可以在左边看到内存中存在的脚本文件,可以选择要调试的文件打开,然后进行下断点之类的操作,从下图可以看出,我下了个断点在a=1,运行时程序停在了a=1这一行。

图片附件

如果没有看到脚本资源管理,可以用菜单“调试->窗口->脚本资源管理器”来打开,或者使用快捷键Ctrl+Alt+N。

至此,我们就可以使用VS2005来调试ASP程序了,相信这会在ASP程序开发过程中给大家带来很大的方便。

[ASP] 在JScript中使用RecordSet对象的GetRows方法

写ASP程序时,一般情况总是使用的VBScript,不过也不只是这一种选择,也可以用JScript。但在用JScript作为ASP的语言时,比用VBScript有一些小小的不方便,比如RecordSet的GetRows方法。

在ASP中操作数据库,一般都要用到RecordSet对象,如果注重程序效率的话,可能就会用到RecordSet对象的GetRows方法,把记录集对象转换成数组,而操作数组在速度上将比用RecordSet对象的MoveNext方法快很多,而且可以在取出数组后尽早释放RecordSet对象,从而减少资源的占用,这也是优化ASP性能的一个方法。

在VBScript里,用RecordSet.GetRows方法取到的是一个二维数组,里面的数据可以通过遍历数组的方式来取得。

假设现在有一个数据库,其中有一个表名为mytable,有3个字段,名称分别为id,first,second。

  • ‘ code by xujiwei
  • ‘ http://www.xujiwei.cn/
  • ‘ 定义变量
  • Dim conn,rs,data,recN,i
  • ‘ 连接数据库
  • Set conn=Server.CreateObject(“ADODB.Connection”)
  • conn.Open ”Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” &_
  • Server.MapPath(“data.mdb”)
  • ‘ 获取记录集
  • Set rs=conn.Execute(“SELECT id,first,second FROM mytable”)
  • ‘ 获取数据数组
  • data=rs.GetRows()
  • ‘ 关闭记录集,释放对象
  • rs.Close()
  • Set rs=Nothing
  • ‘ 获取记录数
  • recN=UBound(data,2)
  • ‘ 循环输出数据
  • For i=0 To recN
  • ‘ 注意,数组下标从0开始
  • ‘ 显示数据库中数据
  • Response.Write(“ID: ”&data(0,i)&”, First: ”&data(1,i)&_
  • “, Second: ”&data(2,i)&”<br />”)
  • Next
  • ‘ 关闭数据库连接,释放对象
  • conn.Close()
  • Set conn=Nothing
  • %>

但是在JScript使用时,就会有一个问题,那就是JScript并没有二维数组,如果要用GetRows所获取的数据,必要将这个VBScript中的二维数组转换成JScript能识别的数组,即元素为数组的一个一维数组。

在JScript里,用GetRows方法获取的数组有一个toArray方法,可以转换成JScript中能用的数组,但是这个数组是一维的,也就是说,如果要像在VBScript一样使用的话,还需要我们自己来做转换。

查阅了MSDN及在网上搜索了相关的文章之后,我写了一个数组转换的函数用于在JScript中使用GetRows方法。

  • <script language=”JScript” runat=”server”>
  • // code by xujiwei
  • // http://www.xujiwei.cn/
  • // 定义变量
  • var conn,rs,vdata,data,recN,i;
  • // 连接数据库
  • conn=Server.CreateObject(“ADODB.Connection”);
  • conn.Open(“Provider=Microsoft.Jet.OLEDB.4.0;Data Source=”+
  • Server.MapPath(“data.mdb”));
  • // 获取记录集
  • rs=conn.Execute(“SELECT id,first,second FROM test”);
  • // 获取数据数组,并转换成为JScript中可用的数组类型
  • vdata=rs.GetRows().toArray();
  • // 获取数据表的字段数
  • i=rs.Fields.Count;
  • // 关闭记录集,释放对象
  • rs.Close();
  • rs=null;
  • // 转换数组
  • data=transArray(vdata,i);
  • // 获取记录数
  • recN=data.length;
  • // 循环输出数据
  • for(i=0;i<recN;i++) {
  • // 注意,数组下标从0开始
  • // 显示数据库中数据
  • Response.Write(“ID: ”+data[i][0]+”, First: ”+data[i][1]+
  • “, Second: ”+data[i][2]+”<br />”);
  • }
  • // 关闭数据库连接,释放对象
  • conn.Close();
  • conn=null;
  • // 数组转换函数
  • // by xujiwei
  • // 参数:arr - GetRows方法得到的对象用toArray方法得到的数组
  • //       fieldslen - 数据表字段数
  • function transArray(arr,fieldslen) {
  • var len=arr.length/fieldslen,data=[],sp;
  • for(var i=0;i<len;i++) {
  • data[i]=new Array();
  • sp=i*fieldslen;
  • for(var j=0;j<fieldslen;j++)
  • data[i][j]=arr[sp+j];
  • }
  • return data;
  • }
  • </script>

对于一些更新频率不高,而使用次数比较多的数据,可以在成功获取数据数组之后,用Application对象来缓存起来,从而减少对数据库的查询次数,一定程序程度上优化ASP的性能。

[ASP] 用Server.Transfer实现博客日志的永久链接

在许多博客日志阅读页面里的尾部都能看到一个永久链接,这个链接一般是持久在在的,即使博客程序换了,也可以用这个链接来访问原来的日志,而不会出现找不到页面的情况,这对于一个博客的确是一个比较实用的功能。

在修改blog程序时,也考虑了这个问题,决定也给我的博客日志加上永久链接功能。

IIS6中如果请求一个目录后面跟上参数时,会把这个参数传给默认文档,即如果请求我的博客首页http://www.xujiwei.cn/blog/?id=500,那么id=500将会传递给默认文档default.asp。利用这点就可以实现博客日志的永久链接了。当然了,这个永久链接是建立在博客目录不改变的情况下,如果目录改了,就需要另外处理了。

在ASP中可以利用Response.Redirect,其原理是服务器向客户端发送一个302 Object Moved的响应,然后客户端根据响应进行转向,但这个会增加额外的带宽开销,并且不利用搜索引擎收录,所以推荐使用Server.Transfer来转向。Server.Transfer则是直接停止当前脚本的执行,转而执行指定的脚本,并且当前的一些变量如会话等均可在新脚本里直接使用,而毋须再重新进行参数传递了,而Response.Redirect则不可以。

两种方法的另外一个比较明显的区别就是使用Response.Redirect客户端显示的URL会改变,而Server.Transfer则不会,使用Server.Transfer时客户端不会感到当前URL其实已经改变。其实这个区别也可以通过两种方法的调用方法来看出来,一个是Response.Redirect由客户端做出改变,而Server.Transfer则是由服务端做出改变。

了解了这些就可以开始做了,打开博客的默认文档,一般就是博客程序的首页,如default.asp、index.asp等,然后在其有输出内容之前加上以下代码:

<%IF Request.QueryString(“id”) Then Server.Transfer(“article.asp”)%>

当然了,article.asp是要根据博客程序来做相应改变的,id即为要做为永久链接时的参数,需要注意这个参数必须为article.asp所能识别的,即article.asp可以根据这个参数来显示日志,如果不行的话就要做相应的改变,即把article.asp中的参数名称改为id,或者把id改成其他名称。

ok,完成!其实这个东西是很简单的,这么大篇幅大都是废话,真正有用的就那么一句代码^_^。

AJAX应用之草稿自动保存

相信用过Gmail的人都知道Gmail有一个草稿自动保存的功能,每过一段时间,Gmail都会自动保存邮件草稿,这样在一些突发情况下就能快速地恢复工作,免得写了半天的邮件眨眼之间就没有了。在学了AJAX之后,我也给自己的blog加上了这个功能。当然,这个应用并不只限于blog上,应该说还是比较通用的。

PS.为了开发的方便,我用了一个自己写的AJAX类,具体内容和下载在这里

演示地址

仍旧以代码加注释的方式来说明怎么编写。

首先是表单填写页面,用一个ID为AutoSaveMsg的DIV来显示返回信息,并且用一个ID为Draft_AutoSave的CheckBox来确定是否进行自动保存,然后将Textarea的ID命名为message。同时为了应对多用户同时使用的需要,加上用户名,每个用户的草稿分开保存。为了说明方便,我把一些修饰性的东西去掉,这样看起来比较明了:

  • AJAX应用之草稿自动保存<br />
  • <!– 用户名默认为NONAME –>
  • 用户名:<input type=”text” name=”memName” id=”memName” size=”20″ value=”NONAME” />&nbsp;&nbsp;&nbsp;&nbsp;
  • <!– 在自动保存选项的onclick事件中调用自动保存状态设置函数 –>
  • <input onclick=”SetAutoSave();” type=”checkbox” id=”Draft_AutoSave” value=”1″ checked=”true”  />自动保存?<br />
  • 内容:
  • <textarea id=”message”></textarea><br />
  • <!– AutoSaveMsg显示返回信息 –>
  • <div id=”AutoSaveMsg”></div>
  • <input type=”submit” value=”提交内容” />&nbsp;&nbsp;
  • <!– 调用函数恢复最后保存的草稿 –>
  • <input type=”button” onclick=”AutoSaveRestore();” value=”恢复最后保存的草稿” />
  • </div>
  • </div>
  • <!– 将JS代码放在所有对象之后,以免在页面未加载完成时出现对象不存在的错误 –>
  • <!– AJAX类 –>
  • <script type=”text/javascript” src=”ajaxrequest.js”></script>
  • <!– 自动保存代码 –>
  • <script type=”text/javascript” src=”autosave.js”></script>

接下来是autosave.js

  • // 首先设置全局变量
  • // 要保存的内容对象FormContent
  • var FormContent=document.getElementById(“message”);
  • // 显示返回信息的对象
  • var AutoSaveMsg=document.getElementById(“AutoSaveMsg”);
  • // 用户名
  • var memName=document.getElementById(“memName”).value;
  • // 自动保存时间间隔
  • var AutoSaveTime=60000;
  • // 计时器对象
  • var AutoSaveTimer;
  • // 首先设置一次自动保存状态
  • SetAutoSave();
  • // 自动保存函数
  • function AutoSave() {
  • // 如果内容或用户名为空,则不进行处理,直接返回
  • if(!FormContent.value||!memName) return;
  • // 创建AJAXRequest对象,详细使用见文章开始的链接
  • var ajaxobj=new AJAXRequest;
  • ajaxobj.url=”autosave.asp”;
  • ajaxobj.content=”memname=”+escape(memName)+”&postcontent=”+escape(FormContent.value);
  • ajaxobj.callback=function(xmlObj) {
  • // 显示反馈信息
  • AutoSaveMsg.innerHTML=xmlObj.responseText;
  • }
  • ajaxobj.send();
  • }
  • // 设置自动保存状态函数
  • function SetAutoSave() {
  • // 是否自动保存?
  • if(document.getElementById(“Draft_AutoSave”).checked==true)
  • // 是,设置计时器
  • AutoSaveTimer=setInterval(“AutoSave()”,AutoSaveTime);
  • else
  • // 否,清除计时器
  • clearInterval(AutoSaveTimer);
  • }
  • // 恢复最后保存的草稿
  • function AutoSaveRestore() {
  • // 创建AJAXRequest对象
  • var ajaxobj=new AJAXRequest;
  • // 提示用户正在恢复
  • AutoSaveMsg.innerHTML=”正在恢复,请稍候……”
  • ajaxobj.url=”autosave.asp”;
  • ajaxobj.content=”action=restore&memname=”+escape(memName);
  • ajaxobj.callback=function(xmlObj) {
  • // 提示用户恢复成功
  • AutoSaveMsg.innerHTML=”恢复最后保存成功”;
  • // 如果内容为空则不改写textarea的内容
  • if(xmlObj.responseText!=”") {
  • // 恢复草稿
  • FormContent.value=xmlObj.responseText;
  • }
  • }
  • ajaxobj.send()
  • }

最后是autosave.asp,用于在后台保存草稿:

  • <%@LANGUAGE=”VBscript” CODEPAGE=”65001″%>
  • <% Option Explicit %>
  • <%
  • ‘ 语言为VBScript,编码为UTF-8,要求变量声明
  • ‘ 出现错误则忽略,继续执行
  • On Error Resume Next
  • ‘ 定义一些变量
  • Dim PostContent,memName,action,objStream
  • ‘ 获取操作,是保存草稿还是恢复草稿
  • action=Request.Form(“action”)
  • ‘ 获取用户名
  • memName=Request.Form(“memname”)
  • ‘ 获取草稿内容
  • PostContent=Request.Form(“postcontent”)
  • IF action=”restore” Then
  • ‘ 恢复草稿,如果用户名不为空则进行恢复操作
  • IF memName<>Empty Then
  • ‘ 使用 ADODB.Stream 来进行文件操作
  • Set objStream = Server.CreateObject(“ADODB.Stream”)
  • With objStream
  • .Type = 2
  • .Mode = 3
  • .Open
  • ‘ 文件名为 autosave_ + 用户名 + .txt
  • .LoadFromFile(Server.MapPath(“autosave_”&memName&”.txt”))
  • .Charset = ”utf-8″
  • ‘.Position = 0
  • PostContent = .ReadText()
  • .Close
  • End With
  • Set objStream = NoThing
  • ‘ 输出草稿
  • IF PostContent<>”" Then Response.Write(PostContent)
  • End IF
  • Else
  • ‘ 保存草稿,如果草稿内容和用户名均不为空则进行保存操作
  • IF PostContent<>Empty AND memName<>Empty Then
  • ‘ 使用 ADODB.Stream 来进行文件操作
  • Set objStream = Server.CreateObject(“ADODB.Stream”)
  • With objStream
  • .Type = 2
  • .Mode = 3
  • .Open
  • .Charset = ”utf-8″
  • .Position = objStream.Size
  • .WriteText= PostContent
  • .SaveToFile Server.MapPath(“autosave_”&memName&”.txt”),2
  • .Close
  • End With
  • Set objStream = NoThing
  • ‘ 输出保存是否成功信息
  • If Err.Number=0 then
  • Response.Write(“最后于 ”&Now()&” 自动保存成功”)
  • Else
  • Response.Write(“最后于 ”&Now()&” 自动保存失败,错误号:”&Err.Number&”,错误描述:”&Err.Dscription)
  • End If
  • End IF
  • End IF
  • %>

至此,AJAX草稿自动保存完成了。

一个简单的AJAX请求类

给blog加上无刷新搜索和即时验证检测后,又看了下代码,感觉太过麻烦,就把XMLHttpRequest请求封装到一个类里面,用起来方便多了,不用记那么多代码,什么创建XMLHttpRequest对象什么的,这部分代码也是重用性比较高的~已经打包,在日志的末尾下载。

要看效果的话点开侧边栏里的日志搜索,里面有一个无刷新搜索,就是了,或者在阅读日志或留言簿里的注册码那里有即时检测,如果不输入验证码或者输错了验证码,输入框都会变红的^_^

类名:AJAXRequest

创建方法:var ajaxobj=new AJAXRequest;,如果创建失败则返回false

属性:method  -  请求方法,字符串,POST或者GET,默认为POST

url         -  请求URL,字符串,默认为空

async     -  是否异步,true为异步,false为同步,默认为true

content -  请求的内容,如果请求方法为POST需要设定此属性,默认为空

callback  - 回调函数,即返回响应内容时调用的函数,默认为直接返回,回调函数有一个参数为XMLHttpRequest对象,即定义回调函数时要这样:function mycallback(xmlobj)

方法:send     -  发送请求,无参数

一个例子:

  • <script type=”text/javascript” src=”ajaxrequest.js”></script>
  • <script type=”text/javascript”>
  • var ajaxobj=new AJAXRequest;    // 创建AJAX对象
  • ajaxobj.method=”GET”;   // 设置请求方式为GET
  • ajaxobj.url=”default.asp”  // URL为default.asp
  • // 设置回调函数,输出响应内容
  • ajaxobj.callback=function(xmlobj) {
  • document.write(xmlobj.responseText);
  • }
  • ajaxobj.send();    // 发送请求

点击AJAX请求类压缩包

AJAX初体验之实战篇——打造博客无刷新搜索

如果你对AJAX不是很了解,可以先看看这篇教程的前篇《AJAX初体验之上手篇》

现在博客很流行,相信应该上网时间稍微长点的朋友都会在这或者在那的有一个自己的博客。对于一些有一定能力的朋友,可能更喜欢自己去下载一个博客程序来架设一个自己的博客,而不是使用一些博客网站提供的服务。而大部分博客程序所带的搜索功能是提交查询关键字到搜索页面,然后在后台生成搜索结果,再呈现给用户,这过程之中浪费了一些带宽,如博客的侧边栏。要节约这一些带宽,我们可以用AJAX来打造自己的无刷新日志搜索。

在本篇教程中,数据库的表名和日志查看页面以L-Blog为例,因为我的博客程序是从L-Blog修改而来^_^。

本教程中的例子已经通过实际测试,可以直接在L-BlogFBS中使用。当然,要真正应用的话还是需要做一些美化及完善的。

在数据库中日志内容数据表名为blog_Content,其中日志ID为log_ID,日志标题为log_Title,日志查看页面为blogview.asp,参数为日志logID。有了这些资料,就可以开始创建搜索结果的XML文档模板了。在显示搜索结果时,需要显示日志的标题,以及日志的ID来创建到查看日志的链接。

搜索结果模板sample.xml

  • <?xml version=”1.0″ encoding=”utf-8″?>
  • <blogsearch>
  •     <!– 每一个reslut就是一个搜索结果 –>
  •     <result>
  •         <!– 日志的ID –>
  •         <logid>1</logid>
  •         <!– 日志的标题 –>
  •         <logtitle>AJAX初体验之上手篇</logtitle>
  •     </result>
  • </blogsearch>

每个result就是一个搜索结果,为了处理没有找到相关内容的情况,我定义了当搜索结果为空时logid为#。

在完成XML文档模板之后,就可以用ASP来动态生成搜索结果需要的XML文档了。搜索的关键字采用POST方式来传递。

搜索结果输出ajaxsearch.asp

  • <!– #include file=”commond.asp” –>
  • <!– #include file=”include/function.asp” –>
  • <%
  • ‘ commond.asp为数据库连接文件
  • ‘ function.asp中有要用到的函数CheckStr
  • Dim Search_Word,XML_Result,rsSearch,sqlSearch
  • Set rsSearch=Server.CreateObject(“ADODB.RecordSet”)
  • ‘ 获取搜索关键字
  • Search_Word=CheckStr(Trim(Request.Form(“searchword”)))
  • ‘ XML文档头
  • XML_Result=”<?xml version=”"1.0″” encoding=”"utf-8″”?><blogsearch>”
  • IF Search_Word<>Empty Then
  •     ’ 创建查询SQL语句
  •     sqlSearch=”SELECT log_ID,log_Title,log_Content FROM blog_Content WHERE log_Title”_
  • &” LIKE ’%”&Search_Word&”%’ AND log_IsShow=True ORDER BY log_ID DESC”
  •     ’ 打开记录集
  •     rsSearch.open sqlSearch,Conn,1,1
  •     ’ 如果没有搜索结果就产生一个结果,logid为#,标志着没有搜索结果
  •     IF rsSearch.BOF AND rsSearch.EOF Then 
  •         XML_Result=XML_Result&”<result><logid>#</logid><logtitle /></result>” 
  •     End IF
  •     ’ 循环输出搜索结果
  •     Do While Not rsSearch.EOF
  •         XML_Result=XML_Result&”<result><logid>”&rsSearch(“log_ID”)&”</logid><logtitle><![CDATA["&rsSearch("log_Title")&"]]></logtitle></result>”  ’ 循环输出每一个结果
  •         rsSearch.MoveNext
  •     Loop
  • Else
  •     ’ 关键字为空,则返回无搜索结果
  •     XML_Result=XML_Result&”<result><logid>#</logid><logtitle /></result>”
  • End IF
  • XML_Result=XML_Result&”</blogsearch>”
  • ‘ 设置MIME Type为XML文档
  • Response.ContentType = ”application/xml”
  • ‘Response.CharSet = ”utf-8″
  • ‘ 输出搜索结果
  • Response.Write(XML_Result)
  • %>

有了后台搜索结果输出的部分,就可以开始写前台搜索的部分了。

首先需要的是给用户输入搜索关键字及显示搜索结果的地方,我用div来分别显示这两个部分:

ajaxsearch.htm

  • <!– 要用到JavaScript,外部链入 –>
  • <script type=”text/javascript” src=”ajaxsearch.js”></script>
  • <!– 用户输入部分 –>
  • <div>
  •     <!– 因为没有用form,所以要处理input的keydown事件。在用户按下回车后搜索 –>
  •     <input type=”text” id=”searchword” onkeydown=”if(event.keyCode==13) AjaxSearch();” /> 
  •     <!– 搜索按钮 –>
  •     <input type=”button” onclick=”AjaxSearch();” value=”搜索” />
  • </div>
  • <!– 搜索结果显示部分 –>
  • <div id=”search_result”>
  •     <!– 初始时提示用户输入搜索关键字 –>
  •     <ul><li>请输入关键字</li></ul>
  • </div>

完成了用户输入及结果输出的部分,就可以开始写最后的部分——客户端程序了。

首先是创建XMLHttpRequest对象,这部分代码不再多说,对AJAX稍有接触应该都看得懂这段代码,前篇教程中也有详细注释:

ajaxsearch.js(part1)

  • var xmlObj = false;
  • var xmlResult;
  • try {
  •     xmlObj=new XMLHttpRequest;
  • }
  • catch(e) {
  •     try {
  •         xmlObj=new ActiveXObject(“MSXML2.XMLHTTP”);
  •     }
  •     catch(e2) {
  •         try {
  •             xmlObj=new ActiveXObject(“Microsoft.XMLHTTP”);
  •         }
  •         catch(e3) {
  •             xmlObj=false;
  •         }
  •     }
  • }
  • if (!xmlObj) {
  •     alert(“XMLHttpRequest init Failed!”);
  • }

接下来是发送搜索请求部分:

ajaxsearch.js(part2)

  • function AjaxSearch() {
  •     var searchword;
  •     // 获取搜索关键字,并且进行URLEncode
  •     searchword=escape(document.getElementById(“searchword”).value);
  •     if(searchword==”") {
  •         // 如果关键字为空,则提示用户输入关键字
  •         document.getElementById(“search_result”).innerHTML=”<ul><li>请输入关键字!</li></ul>”;
  •         return;
  •     }
  •     // 给出提示,正在搜索
  •     document.getElementById(“search_result”).innerHTML=”<ul><li>正在加载,请稍候</li></ul>”;
  •     // 打开一个连接,采用POST
  •     xmlObj.open (“POST”, ”ajaxsearch.asp”, true);
  •     // 设置请求头,表单内容格式为URLEncoded
  •     xmlObj.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”);
  •     // 设置完成请求后响应函数
  •     xmlObj.onreadystatechange=function() {
  •         // 完成响应
  •         if(xmlObj.readyState==4) {
  •             // 状态正常
  •             if(xmlObj.status==200) {
  •                 // 设置xmlResult为搜索结果XML文档
  •                 xmlResult=xmlObj.responseXML;
  •                 // 调用AjaxShowResult()显示搜索结果
  •                 AjaxShowResult();
  •             }
  •         }
  •     }
  •     // 发送请求,内容为搜索的关键字
  •     xmlObj.send(“searchword=”+searchword);
  • }

最后是搜索结果的显示:

ajaxsearch.js(part3)

  • function AjaxShowResult() {
  •     var results,i,strTemp;
  •     // 获取搜索结果集合
  •     results=xmlResult.getElementsByTagName(“result”);
  •     // 用无序列表来显示搜索结果
  •     strTemp=”<ul>”;
  •     // 首先判断搜索结果是否为空
  •     if(results[0].getElementsByTagName(“logid”)[0].firstChild.data==”#”)
  •         // 是空,则显示没有符合的搜索结果
  •         strTemp=strTemp+”<li>无搜索结果</li>”;
  •     else
  •         // 循环输出每个搜索结果
  •         for(i=0;i<results.length;i++)
  •             strTemp = strTemp + ”<li><a href=’blogview.asp?logID=” + results[i].getElementsByTagName(“logid”)[0].firstChild.data + ”‘>” + results[i].getElementsByTagName(“logtitle”)[0].firstChild.data + ”</a></li>”; 
  •     strTemp=strTemp+”</ul>”;
  •     // 显示搜索结果
  •     document.getElementById(“search_result”).innerHTML = strTemp
  • }

至此,一个完整的AJAX实例完成了。

几个经验:

1. 页面使用UTF-8编码,这样可以省却很多烦恼

2. 在获取搜索结果时,因为用的getElementsByTagName,返回的是一个集合,所以要在结果之后加上下标,如例子中的:

    results[i].getElementsByTagName(“logid”)[0].firstChild.data

3. 建议使用document.getElementById()来获取对象,而不要使用document.all这样的方法

参考资料:

1. 《AJAX初体验之上手篇》

2. 发布三个ajax相关的函数,包括无刷新提交表单等

下载文件 实例中的三个文件打包下载

[本日志由 xujiwei 于 2006-08-08 01:10 PM 编辑]

Comments (8), Views (51513), Pings (1), Leave a response!

XML+XSL+CSS+ASP打造留言簿

前段时间无意间看到一个博客的RSS可以用XSL格式输出并且能在Firefox里浏览,想到自己以前写的一个XML留言簿因为不兼容Firefox所不了了之了,现在看到他的能在Firefox浏览就觉得很好奇,看了一下代码,一句一句的比对,最后终于找到了原因,也就把这个留言簿给完成了。因为是一个简单的XML留言簿,所以取名SXGB(Simple XML GuestBook)。

查看留言本演示,管理密码为test:

首先定义留言簿的XML文档的格式。作为一个留言簿,不需要太复杂的内容,于是我就给留言内容分为3个部分:留言者姓名、留言者主页和留言内容。另外,一个留言簿还需要有使用者的一些信息,包括用户名和用户主页。再有,在留言比较多时还需要分页信息。大致结构完成后就可以开始写XML文档模板了。

XML文档根元素定义为gbook

XML文档模板gbook.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<!– DTD file –>
<!DOCTYPE gbook SYSTEM “sxgb.dtd”>
<!– XSL file –>
<?xml-stylesheet type=”text/xsl” href=”gbook.xsl”?>
<gbook>
<!– 留言簿相关信息 –>
<info>
<!– 用户名 –>
<user>HotHeart</user>
<!– 用户主页 –>
<home>http://www.xujiwei.cn</home>
<!– 分页信息,分别为目前所在页,总页数,上一页,下一页 –>
<pagenow>1</pagenow>
<pagetotal>1</pagetotal>
<pageprev>1</pageprev>
<pagenext>2</pagenext>
<!– 是否已经登陆,用来处理是否显示登陆框 –>
<logined>NO</logined>
</info>
<!– 留言列表 –>
<messages>
<!– 一个留言 –>
<message>
<!– 留言ID –>
<id>1</id>
<!– 留言者姓名 –>
<username>Admin</username>
<!– 留言时间 –>
<time>2005-08-09 12:00</time>
<!– 留言者主页 –>
<homepage>http://www.xujiwei.cn/</homepage>
<!– 留言内容 –>
<content><![CDATA[ 留言内容 ]]></content>
</message>
</messages>
</gbook>

要注意在引用XSL时不能用

<?xml:stylesheet type=”text/xsl” href=”gbook.xsl”?>

xml和stylesheet之间应该用一杠(-)而不能用冒号(:),在Firefox里是不支持用冒号的。

一个好的XML文档,除了要有结构性,还应该要有有效性,所以在XML文档的一开头就定义了文档类型定义(DTD) sxgb.dtd,下面就来把这个文档类型定义给完成。因为已经设计好留言簿XML文档的结构,所以写出DTD是很方便的。

Read more »

.