到了今天,數據庫已經成了網站的靈魂,可以說,沒有對數據進行集中管理就算不上是一個真正的網站。而ASP加數據庫,更成了主流中的主流,網站裡的用戶登錄,論壇,留言本都成了它們用武之地,從前用51個文件才能做成的事,現在用2個文件就可以了,但ASP加數據庫,卻並非完美,尤其是與服務器進行頻繁的交互方面。
比如按ASP+數據庫的方案,我們完全可以將那位敬業的站長的工作簡化為兩個文件:一個
數據庫文件,記錄小說的所有章節;另一個ASP文件,用來讀取數據庫的內容;當客戶端點擊“下一章”的時候便可以浏覽下一章內容……的確,這看似很直觀方便,但不可乎視的是,每當我們浏覽下一章的時候,我們的浏覽器都會自動自覺地去訪問一次數據庫,因此,當有訪問者耐心地將這本小說讀完的時候,我們的數據庫已經與它親密接觸了49次了。
那如果同時有N個49次呢?誰還能保證自己的服務器仍然能從容地應付所有請求?特別是一些提供了搜索數據,將數據分頁顯示的網站,服務器不堪重負的現象更應該重視,因為查詢結果有N頁,就表示訪問者遍覽所有結果需要連接服務器打N次。
如果現在你說“N次就N次吧,咱無所謂”,那麼你應該馬上用鼠標點擊浏覽器的“後退”因為我下面將談到一些垃圾內容。當然,如果你也想讓你的數據庫程序變成“N頁記錄,一次交互”的話,歡迎繼續看下去,我們將一起探討XML與數據庫的整合運用。
其實XML並不像許多人想的那樣空有名聲,而無實際用途。我不知道你是不是也這麼想,但在網上很難見到一些真正應用了XML的網站,這是事實。現在,我列出幾條獨有XML才能實現的案例,希望能夠以此證明XML的實用與強大:
1. 1個XML文件 + 1個普通Html文件 = 49章小說分章顯示
適用於那些不支持ASP的普通主頁空間,這種情況下XML完全代替了數據庫,很經典地實現了數據與排版的分離。XML與Html完全分工。
2. 1個XML文件 + 1到N個ASP文件 = 留言本/論壇
適用於那些禁用了文件組件FileSystemObject與數據庫組件的ASP主頁空間,不用文件存取與數據庫,用XML照樣可以做留言本與論壇,並實現數據庫的所有功能。
(我在本論壇發表的“第三種途徑-----基於XML的ASP留言板”中,詳細地闡述了這一技術,有興趣的話可以在論壇中搜索此文。)
3. 1個數據庫 + 1個嵌入了XML的ASP文件 = “N頁記錄,一次交互”
可以說,這幾種技術都體現了XML的精髓。特別是第2種技術,XML充分證明了自身的優勢——
既有數據庫的強大又具備文本文件的輕巧(一個.mdb文件上百K,而一個.XML文件才幾k,而且數據庫文件修改要借助專門軟件或相對應的ASP程序,但xml文件,記事本足矣。)更讓人興奮的是,XML完全可以拋開文件存取組件與數據庫組件實現數據的寫入讀取,甚至新建文件。而我們將要談到的“N頁記錄,一次交互”則更是XML對數據庫的全面超越。
先看下面這個XML文件:
<?XML version="1.0" encoding="gb2312"?>
<在線播放>
<歌曲>
<歌名>Hello Goodbye</歌名>
<URL>FTP://61.139.37.148/music/songs01/english/beatles/hellogoodbye.mp3</URL>
<演唱者>The Beatles</演唱者>
<歌詞>You say yes, I say no</歌詞>
</歌曲>
<歌曲>
<歌名>Yesterday</歌名>
<URL>http://www.mayia.com/beatlescom/beatles/mp3/mp3/yesterday.mp3</URL>
<演唱者>The Beatles</演唱者>
<歌詞>Yesterday, all my troubles seemed so far away</歌詞>
</歌曲>
</在線播放>
試試看,用記事本編輯一下這個文件,並保存文件名為songList.xml,然後用IE浏覽器打開這個文件,如果沒有語法錯誤,即可在浏覽器中顯示XML所獨有的樹狀頁面這就是一個合法的XML文檔,而XML文檔的規則與格式也非常自由,如果你要創建一個新的XML文件,只需一字不改地照寫第一行“<?XML version="1.0" encoding="gb2312"?>”,而後面的標簽與標簽之間的text就可以很隨意,僅僅遵守以下規則即可:
1.首標簽與尾標簽必須對應,可以重復,但不可以嵌套。
2.標簽的命名規則與Java/C/C++等程序語言的變量命名規則相似,區分大小寫。
3.一個文檔只能有一個根元素,如實例中的“<在線播放>”
4.唯一的關鍵字“XML”,標簽不能以這三個字母開頭。
5.如果文檔與規則有所沖突,將導制XML文檔在浏覽器中無法正常顯示,亦表示非合法的XML 文檔。
OK,我們已經知道怎樣寫一個合法的XML文檔了,下一步我們將開始探討將XML文件嵌入到Html文件中,並用VBScript腳本語言操作XML文檔中的數據。先看下面這個文件:
<Html>
<head>
<title>用XML嵌入Html</title>
</head>
<body bgcolor="#000000" text="#FFFFFF">
<xml id = "XMLFile">
<在線播放>
<歌曲>
<歌名>Hello Goodbye</歌名>
<URL>FTP://61.139.37.148/music/songs01/english/beatles/hellogoodbye.mp3</URL>
<演唱者>The Beatles</演唱者>
<歌詞>You say yes, I say no</歌詞>
</歌曲>
<歌曲>
<歌名>Yesterday</歌名>
<URL>http://www.mayia.com/beatlescom/beatles/mp3/mp3/yesterday.mp3</URL>
<演唱者>The Beatles</演唱者>
<歌詞>Yesterday, all my troubles seemed so far away</歌詞>
</歌曲>
</在線播放>
</XML>
<script language="VBScript">
set xml=XMLFile.recordset
XML.MoveFirst
document.write "第一條記錄<BR>"
document.write XML("歌名")&"<BR>"
document.write XML("演唱者")&"<BR>"
document.write XML("URL")&"<BR>"
document.write XML("歌詞")&"<BR><br>"
XML.MoveNext
document.write "第二條記錄<BR>"
document.write XML("歌名")&"<BR>"
document.write XML("演唱者")&"<BR>"
document.write XML("URL")&"<BR>"
document.write XML("歌詞")&"<BR>"
</script>
</body>
</Html>
在這個HTML文件中,我們加入了一對<xml></xml>標記,用來嵌入一個內部XML文檔。嵌入在Html文件中的XML文檔一樣地遵循與獨立的XML文檔一樣的規則,只是省去了獨立XML文檔的聲明部分“<?xml version="1.0" encoding="gb2312"?>”。在<XML>標簽中,我們設置了XML的ID:xmlFile,以便後面的腳本語言訪問該XML對象。
“set xml=xmlFile.recordset” 語句創建了一個可以訪問XML的游標。這個游標類似於ASP中的RecordSet對象,所擁有的方法與後者也幾乎是完全一樣的。如:
當我們用set xml=xmlFile.recordset創建了一個名為XML的數據游標後,我們就可以使用以下方法與屬性:
XML.MoveFirst() 移到第一條記錄
XML.MoveNext() 移到下一條
XML.MovePrevious() 移到上一條
XML.MoveLast() 移到最後一條
XML.BOF 表示游標在第一條記錄之前
XML.EOF 表示游標在最後一條記錄之後
XML.RecordCount 記錄集總數
XML.AbsolutePosition 游標當前位置
XML.AddNew() 添加一條記錄
XML.Delete() 刪除一條記錄
例如:我們要顯示某一首歌的歌名,我們只須將游標移到該記錄上,再用XML("歌名")
便可獲取XML文檔中<歌名>與</歌名>之間的文本。非常方便。
好了,在了解以上關於XML的這些內容後,我們完全可以開始我們真正的服務器減負行動了!
我們的思路是:
1.客戶端向服務器的某個ASP程序發出查詢條件。
2.該ASP程序響應,並連接數據庫。
3.數據庫將查詢結果返回給該ASP程序。
4.獲得數據後,用ASP程序將數據格式化為XML格式, 從而將查詢結果建立為該ASP的內嵌式XML對象。
5.在客戶端實現XML的分頁(分頁方法類似於數據庫分頁)
6.此後,無論是客戶端將查詢結果翻多少頁看多少遍,均不會再與服務器發生交互。
另外,就算是客戶端斷開網線,也仍然可以浏覽還未浏覽的分頁頁面。
下面是我寫的一個歌曲在線播放程序頁面程序,由兩個文件構成:
songList.mdb 一個數據庫,裝載著歌曲信息。songList.asp ASP程序,數據庫中的數據格式成XML,頁面完全顯示後,無論點多少次“下一首”,也不會與服務器交互。
◆songList.ASP◆
<Html>
<head>
<title>殷亮的在線播放</title>
<style type="text/CSS">
<!--
.input
{
background-color: #000000;
border: #000000;
color: #FF9900;
}
-->
</style>
</head>
<body bgcolor="#000000" text="#FF9900">
<% ''''''''''''''''''''連接數據庫'''''''''''''''''''''''''
set songCon = Server.CreateObject("ADODB.connection")
conPath = Server.MapPath("songList.mdb")
conStr = "DRIVER={Microsoft Access Driver (*.mdb)}; dbq="
songCon.open(conStr & conPath)
set rs = Server.CreateObject("ADODB.Recordset")
rs.open "Select * from songList",songCon,3,3
%>
<!--動態生成內嵌式XML文檔,"在線播放"是根標記-->
<xml id = "XMLFile">
<在線播放>
<%
If not rs.eof then
while not rs.eof
%>
<歌曲>
<歌名><%= trim(rs("song_name")) %></歌名>
<URL><%= trim(rs("song_url")) %></URL>
<演唱者><%= trim(rs("songer")) %></演唱者>
<歌詞><%= trim(rs("song_lyrics")) %></歌詞>
</歌曲>
<%
rs.movenext
wend
End If
%>
</在線播放>
</XML>
<div id="Layer1" style="position:absolute; width:500px; height:59px; z-index:1; left: 118px; top: 4px;">
<!--Window Media Player控件-->
<OBJECT classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95" width="500" height="43" id="player" style="WIDTH: 500px; HEIGHT: 43px" VIEWASTEXT>
<PARAM NAME="AudiOStream" VALUE="-1">
<PARAM NAME="AutoSize" VALUE="0">
<PARAM NAME="AutoStart" VALUE="-1">
<PARAM NAME="AnimationAtStart" VALUE="-1">
<PARAM NAME="AllowScan" VALUE="-1">
<PARAM NAME="AllowChangeDisplaySize" VALUE="-1">
<PARAM NAME="AutoRewind" VALUE="0">
<PARAM NAME="Balance" VALUE="0">
<PARAM NAME="BaseURL" VALUE="">
<PARAM NAME="BufferingTime" VALUE="5">
<PARAM NAME="CaptioningID" VALUE="">
<PARAM NAME="ClickToPlay" VALUE="-1">
<PARAM NAME="CursorType" VALUE="0">
<PARAM NAME="CurrentPosition" VALUE="-1">
<PARAM NAME="CurrentMarker" VALUE="0">
<PARAM NAME="DefaultFrame" VALUE="">
<PARAM NAME="DisplayBackColor" VALUE="0">
<PARAM NAME="DisplayForeColor" VALUE="16777215">
<PARAM NAME="DisplayMode" VALUE="0">
<PARAM NAME="DisplaySize" VALUE="4">
<PARAM NAME="Enabled" VALUE="-1">
<PARAM NAME="EnableContextMenu" VALUE="-1">
<PARAM NAME="EnablePositionControls" VALUE="-1">
<PARAM NAME="EnableFullScreenControls" VALUE="0">
<PARAM NAME="EnableTracker" VALUE="-1">
<PARAM NAME="Filename" VALUE="">
<PARAM NAME="InvokeURLs" VALUE="-1">
<PARAM NAME="Language" VALUE="-1">
<PARAM NAME="Mute" VALUE="0">
<PARAM NAME="PlayCount" VALUE="1">
<PARAM NAME="PrevIEwMode" VALUE="0">
<PARAM NAME="Rate" VALUE="1">
<PARAM NAME="SAMILang" VALUE="">
<PARAM NAME="SAMIStyle" VALUE="">
<PARAM NAME="SAMIFileName" VALUE="">
<PARAM NAME="SelectionStart" VALUE="-1">
<PARAM NAME="SelectionEnd" VALUE="-1">
<PARAM NAME="SendOpenStateChangeEvents" VALUE="-1">
<PARAM NAME="SendWarningEvents" VALUE="-1">
<PARAM NAME="SendErrorEvents" VALUE="-1">
<PARAM NAME="SendKeyboardEvents" VALUE="0">
<PARAM NAME="SendMouseClickEvents" VALUE="0">
<PARAM NAME="SendMouseMoveEvents" VALUE="0">
<PARAM NAME="SendPlayStateChangeEvents" VALUE="-1">
<PARAM NAME="ShowCaptioning" VALUE="0">
<PARAM NAME="ShowControls" VALUE="-1">
<PARAM NAME="ShowAudioControls" VALUE="-1">
<PARAM NAME="ShowDisplay" VALUE="0">
<PARAM NAME="ShowGotoBar" VALUE="0">
<PARAM NAME="ShowPositionControls" VALUE="-1">
<PARAM NAME="ShowStatusBar" VALUE="0">
<PARAM NAME="ShowTracker" VALUE="-1">
<PARAM NAME="TransparentAtStart" VALUE="0">
<PARAM NAME="VideoBorderWidth" VALUE="0">
<PARAM NAME="VideoBorderColor" VALUE="0">
<PARAM NAME="VideoBorder3D" VALUE="0">
<PARAM NAME="Volume" VALUE="0">
<PARAM NAME="WindowlessVideo" VALUE="0">
</OBJECT>
</div>
<div id="Layer3" style="position:absolute; width:200px; height:115px; z-index:3; left: 120px; top: 140px;"><img src="P_online.jpg" width="300" height="170"></div>
<div id="Layer4" style="position:absolute; width:191px; height:54px; z-index:4; left: 430px; top: 199px;">
<table width="190" height="52" border="1" align="right" bordercolor="#000000" bgcolor="#FF9900">
<tr>
<td height="23" valign="bottom">
<div align="center"></div>
<div align="right">
<input name="btnPre" type="button" disabled="true" id="btnPre" value="上一首">
</div></td>
</tr>
<tr>
<td valign="top">
<div align="right">
<input name="btnNext" type="button" id="btnNext" value="下一首">
</div></td>
</tr>
</table>
</div>
<div id="Layer2" style="position:absolute; width:503px; height:58px; z-index:2; left: 120px; top: 67px;">
<table width="501" border="1">
<tr>
<td width="100"><font color="#FFFFFF" size="2">播放內置歌曲:</font></td>
<td width="317">
<SELECT name="list" size="1" id="list" style="WIDTH: 328px; BACKGROUND-COLOR: darkorange">
<!--用循環來初始化下拉列表-->
<script language="VBScript">
set xml=XMLFile.recordset
XML.MoveFirst
dim num
for num=0 to XML.RecordCount-1
document.write("<OPTION value="&xml("url")&">"&XML("歌名")&"</OPTION>")
XML.MoveNext
next
XML.MoveFirst
</script>
</SELECT>
</td>
<td width="62"><div align="right">
<input name="btnLAN" type="button" id="btnLAN" value="播放">
</div></td>
</tr>
<tr>
<td><font color="#FFFFFF" size="2" >播放網絡歌曲:</font></td>
<td><input name="textURL" type="text" id="textURL" style="WIDTH: 328px; BACKGROUND-COLOR: darkorange;color: #000000;"></td>
<td><div align="right">
<input name="btnNET" type="reset" id="btnNET" value="播放">
</div></td>
</tr>
</table>
</div>
<div id="Layer5" style="position:absolute; width:500px; height:20px; z-index:5; left: 120px; top: 320px;">
<p><font color="#FFFFFF" size="2">正在播放:
<input name="textSonger" type="text" class="input" id="textSonger" size="15">
演唱的
<input name="textSongName" type="text" class="input" id="textSongName" size="35">
</font></p>
</div>
<div id="Layer6" style="position:absolute; width:500px; height:150px;
z-index:6; left: 120px; top: 349px;">
<textarea name="area" cols="68" rows="15" id="area"
style="BORDER-RIGHT: white double; BORDER-TOP: white double;
BORDER-LEFT: white double;COLOR: #000000; DIRECTION: ltr;
BORDER-BOTTOM: white double;BACKGROUND-COLOR: darkorange;
TEXT-ALIGN: left">
</textarea>
</div>
<!--各按鈕的單擊事件-->
<script language="VBScript">
sub play()
textSonger.value=XML("演唱者")
textSongName.value=XML("歌名")
textURL.value=""
area.value=XML("歌詞")
player.filename=XML("URL")
if xml.AbsolutePosition=XML.recordcount then
btnNext.disabled=true
else
btnNext.disabled=false
end if
if XML.AbsolutePosition=1 then
btnPre.disabled=true
else
btnPre.disabled=false
end if
end sub
sub btnLAN_onclick
XML.MoveFirst
while XML("URL")<>list.value
XML.MoveNext
wend
call play()
end sub
sub btnNET_onclick
player.filename = textURL.value
textSonger.value = ""
textSongName.value = ""
area.value = "自定義網絡歌曲"
end sub
sub btnPre_onclick
XML.MovePrevious
list.selectedIndex = list.selectedIndex - 1
call play()
end sub
sub btnNext_onclick
XML.MoveNext
list.selectedIndex = list.selectedIndex + 1
call play()
end sub
</script>
</body>
</Html>
現在,你知道怎麼給服務器減負了嗎?^-^本文旨在探討,如有錯漏,歡迎指正與討論。