Asp.net+Xml實現無數據庫論壇一點即通
起草語:流行論壇(我們重點討論ASP,ASP。NET論壇)的開發思路
老手可略過此節,就讀下節。
目前,網上論壇各式各樣各種版本不計其數,歸根結底如何神通其核心數據存取倉庫都是“數據庫”,我是指我們常用的ACCESSSQLSERVER等等這種形式的“數據庫”,而後由PHPASPASP。NETJSP等等這些後台語言通過中心“ADO,SQL”兩條線,像伐木搭橋似的一小塊一小塊(會員注冊、會員登陸、論壇欄目分類、項目統計、單個欄目、帖子瀏覽、後台管理……)積木似的累積成形式各異的論壇係統,而這一塊塊的“積木”,如何異樣然終歸就是對數據庫的存取其成分無非就是構成木料的物質不會變成鐵的,可見,好的論壇程序並不難寫,難得是清晰的思路、優質的“數據庫結構”,既然是這樣,下麵我就將本人著手開發ASP。NET+XML無數據庫實現論壇總結的一些經驗思路一一陳述,讀畢若有興趣不妨自己動手一試,嚐試一下用全新的手段開發論壇的樂趣
第一節:廢話不說、解答疑問
1:這篇文章需熟悉哪些知識的人才能讀懂?
至少從事學習一年以上WEB後台網站編程綜合知識的人即可讀懂,熟悉ASP。NET編程及XML文檔結構的程序員更能深入意會
2:Xml能充當“數據庫”嗎?
能,隻不過是不同的概念和組織形式
3:用Xml充當數據庫製作論壇的開發難度是否比使用ACCESS、SQLSERVER等為數據庫的開發難度高?
高許多,甚至有些功能本人水平有限無從下手解決(XML充當數據庫相比ACCESS等有一定本質上的局限),但並不代表不可能
4:本文為什麼選擇ASP。NET做為後台程序語言來結合XML建造論壇?
無特殊意義,ASP、PHP、JSP或其他後台程序語言均可,甚至VB、VC、JAVA等能以軟件形式表現論壇
5:兩者相比,Xml充當“數據庫”做的論壇或其他係統有何好處?
如程序及XML結構精妙完善,無論在大小程序係統上均在
-速度(基於文件,相對憂於ADO存取數據庫)
-資源占用(無論數據總和多少,基本是處理分布式的小型文件(通常在1-100K內),無論是在內存或CPU的占用等均憂於數據庫)
-分布式(單一的文件集合於文件夾,與將數據集成為一身的數據庫,各有優勢)
-移植性和通用性(XML本身即是一種通用數據描述語言,無論是在不同操作係統或程序語言上均能順利移植和應用)
-修改、查找、維護、批量處理(如數據量大,則必須借助程序係統操作,如直接在文件夾管理文件非常麻煩,這方麵遜於數據庫係統的界麵和易用性,除非建立自己的XML數據處理軟件或WEB係統彌補這方麵的不足)
-安全性(大智慧是取決於程序、加密方麵,小聰明是更改後台文件、文件夾的名稱和存放位置,隻不過基於XML文件構建的數據庫結構比較散亂,不如數據表封裝的簡單)
第二節:引路入門、建立基地(XML數據庫結構)
明確做什麼樣的論壇係統,才能理起思路,這裏我們假設開發一簡單論壇,其功能功用均效仿常見論壇,我們隻要求一個欄目
XML數據庫的實現{
會員資料存儲(在主目錄新建一文件,名為user.xml,該user.xml文件即作為存儲所有會員資料的文件,本例結構可是如下形式)
<?xml version="1.0" encoding="gb2312"?> <alluser> <fyw name="風雲舞" pass="1234" sex="男士" age="20" img="https://www.chinaz.com" email="abc@chinaz.com" oicq="10001" qianming="簽名檔內容" address="火星"/> <cike name="孤獨刺客" pass="123" sex="男士" age="20" img="man2.gif" fatie="0" exp="20" homepage="" email="chinaz@chinaz.com" oicq="" qianming="風雲他是豬!吭大爺做關稅區的斑竹!" address="火星"/> <plgirl name="千千純子" pass="123" sex="女士" age="20" img="woman1.gif" fatie="0" exp="0" homepage="" email="" oicq="" qianming="" address=""/> </alluser> |
論壇帖子資料存儲(在主目錄新建一文件夾,名為data,該data文件夾今後即保存所有會員發表的帖子,其中帖子的文件名是隨機或有規律的如1.xml,2.xml,3.xml,這些文件存儲了帖子的所有數據包括主題、回複,當然這些文件的建立、修改、起名、刪除等都是在以後用程序實現的,至於新文件起名的程序部分要保證其名稱與以有文件互不衝突即可,文件名可以是無任何規律的,畢竟今後我們不以文件名來實現排序,其單個XML文件內容結構如下)
1.xml:
<?xmlversion="1.0"encoding="gb2312"?> <?xml-stylesheettype='text/xsl'href='../file.aspx?dex=1.xml'?> <document> <record> <anthor>fyw</anthor> <title>帖子標題</title> <date>2003-12-63:27:18</date> <gengxindate>2003-12-63:27:18</gengxindate> <body>帖子內容 <hr>內容是以過濾HTML等於XML文檔規範相衝突的字符以後的合法內容,標題也需要過濾 |
2.xml:
<?xmlversion="1.0"encoding="gb2312"?> <?xml-stylesheettype='text/xsl'href='../file.aspx?dex=7908604.xml'?> <document> <record> <anthor>fyw</anthor> <title>帖子標題</title> <date>2003-12-63:54:59</date> <gengxindate>2003-12-63:54:59</gengxindate> <body>帖子內容</body> <reply> <anthor>cike</anthor> <date>2003-12-65:53:38</date> <gengxindate>2003-12-65:53:38</gengxindate> <body>1樓回複的內容</body> </reply> <reply> <anthor>plgirl</anthor> <date>2003-12-75:53:38</date> <gengxindate>2003-12-75:53:38</gengxindate> <body>2樓回複的內容</body> </reply> </record> </document> |
這是本例論壇帖子的XML存儲結構,現在我們建立起了會員資料存儲文件(user.xml)以及論壇帖子存放地點和存放結構(data/*.xml),你是否以有所啟發?用程序在這兩者基石上搭橋引線是否真的能夠實現複雜的論壇係統哪?答案是肯定的,隻要能通過程序在後台操縱這兩個存儲基地,加以友好的界麵,即可小試牛刀
第三節:諸葛布陣、將士磨刀
XML數據存儲結構以完成,下麵一一列出完成論壇大業所需要的材料
項目包括:
通用函數頁
(建立或一或二這種通用函數頁或DLL或者是用戶控件,將常用的程序過程、變量、函數放入其中,此後使用可大大節省時間避免重複勞動,這在下一章將有所提及)
遊客與會員的區分
(即是一個session,本例為session("who")值是否存在的判斷,如存在即判斷是會員,如不存在值即為遊客,我們本例不使用cookies存儲用戶數據,遊客權限自然是隻能瀏覽帖子,不能發表或回複帖子,而會員則可以)
會員注冊
(包含各種表單的頁麵,目的是完成向user.xml添加一新的標簽節點(等同添加一新的會員數據),要處理好用戶所提交的數據,方法要用到防止跨站提交、會員帳號(即XML節點頭標簽)要用正則表達式限製為類似程序變量的語法要求或幹脆隻允許使用英文字母、XML節點屬性至少要過濾<>&"'以及回車符號、防止申請的會員帳號以存在user.xml、所有數據英文符號均轉換為小寫格式即不區分大小寫包括用戶帳號和密碼)
會員登陸
(包含用戶帳號輸入框、密碼輸入框和一個登陸按鈕,提交後利用XMLDOM搜索user.xml是否有匹配的用戶帳號(要特別注意過濾用戶提交的數據,尤其是*號等,這在XMLDOM的搜索中被認為是通配符),如user.xml存有該帳號,即將一個session,本例為session("who"),設值為該用戶帳號,遊客身份即成為會員身份)
會員資料修改
(禁止遊客瀏覽本頁,樣式保持與會員注冊頁的表單基本一樣(但不包含用戶帳號名稱修改的功能),隻不過所有表單的值均是預讀了user.xml中匹配session("who")該會員的信息,用戶修改過後,單擊完成修改按鈕,此時後台程序修改user.xml中該會員對應的節點數據即可)
會員資料顯示
(隻讀頁麵,讀取網址參數中對應的會員帳號,顯示會員所有無需保密的信息)
一個論壇欄目主頁
(即帖子列表,根據URL頁碼參數分頁,顯示data目錄中對應頁碼的所有帖子信息,排序自然根據文件的修改日期,最新更新的最靠頂,這是開發本論壇中最難的一個項目之一,要謹慎處理,最好實現點對點(即1-10,30-40,100-110)形式分頁的抽取data目錄中的文件,可以保證最優質的運行速度)
帖子顯示頁
(本例的帖子顯示是直接在瀏覽器訪問XML文件,即https://xxx.xxx.xxx/xxx.xml的URL形式訪問,由於僅僅使用靜態XSL控製XML文件的二層輸出形式是遠遠不夠的,所以我們采取的顯示結構是三層,其順序為(1:打開XML文件後查找xml-stylesheet節點的href所指定的XSL文件---2:由於目標文件類型是aspx,我們在目標aspx中根據url參數訪問參考對應的XML文件數據,控製數據流輸出格式為xsl,叢中很好的整理出理想的xsl樣式表,即起到了中間層的關鍵作用---3:由於aspx輸出的xsl是我們在後台整理過的,其高度的智能、合理,即可以配合XML數據輸出結構複雜的帖子顯示頁),期間中間層的開發難度最大,是本論壇係統中最難的一個步驟,簡單的地方是XMLDOM分析抽取目標XML中的節點數據,實現顯示主題、顯示帖子作者、顯示帖子內容、顯示帖子所有回複,但最難點,本人在著手開發時,就無法解決帖子回複的分頁,以及aspx服務器端控件和xsl文檔規範相互衝突,可能是本人水平有限,或也是本人原創的這種3層輸出存在本質的缺陷,所謂XML實現數據庫容易,但通過XSL實現超越HTML的理想輸出難)
發表新貼
(禁止遊客發表,該項目即是一個輸入主題的輸入框+內容輸入框+提交按鈕,可以綁定在欄目帖子列表頁下方或新建一個專頁,用戶提交發表後要用server.HTMLEncode()過濾用戶所提交的數據,而後用程序創建XML文件、給XML文件起名、整理XML文件的文件格式如第二節所寫的格式、向節點內寫入過濾後的數據、修改user.xml對應的發貼會員的節點實現積分+2和發貼數+1,用cookies限製7秒內禁止多次提交灌水)
回複新貼
(禁止遊客回複,該頁可綁定帖子顯示頁下方或新建一個專業,提供一內容輸入框+提交按鈕,提交後如發表新貼過程類同,要進行數據過濾,而後在對應的帖子存儲XML文件中插入一reply節點,在該節點中建立用於存儲回複作者名稱、回複內容、回複日期、回複更新日期等節點,修改user.xml對應的發貼會員的節點實現積分+1和發貼數+1,用cookies限製7秒內禁止多次提交灌水)
版主管理功能
(要實現密碼驗證,判斷禁止遊客及會員使用,可選的後台管理功能有獎勵會員積分、減少會員積分、刪除會員、修改任何帖子、刪除任何帖子,甚至可以考慮諸多封IP、置頂、鎖定、封版主等等高級功能)
第四節:君臨沙場、錦囊相助
通過以上三節修煉,君若仔細攻讀,定已胸有成竹,躍躍欲試,此時想必已經動起手來,或者是思路很清晰卻不知程序該如何寫,若真是如此,不必急噪,筆者先將平生所學一些常用“兵法”一一列出,定可使汝茅塞頓開
1:錯誤提示函數(需要時使用,可彈出對話框給與用戶錯誤提醒,而後自動退回上一頁,此函數建議保存為一通用文件,需要時<!--#include-->一下即可使用)
<scriptlanguage=vbrunat='server'> subt2(tstr2asstring) response.write(replace("<scriptlanguage=vbs>msgbox"&chr(34)&tstr2&chr(34)&",16,"&chr(34)&"錯誤提示"&chr(34)&":history.back()</script>","<","<")):response.end endsub </script> |
2:一般數據檢測函數(修改XML標簽屬性時建議使用,用於一般檢測,至於用戶帳號等還需要更嚴密的數據過濾)
<scriptlanguage=vbrunat='server'> |
3:asp.net拒絕跨站提交注入(可在會員注冊、會員修改頁等表單較多的頁使用)
<% iflcase(mid(request.ServerVariables("HTTP_REFERER"),8,len(request.ServerVariables("SERVER_NAME"))))<>lcase(request.ServerVariables("SERVER_NAME"))thent2("拒絕跨站提交!") %> |
4:向目標XML文件添加新節點
<%@import namespace='system.xml'%> <% dim userdom1=new xmldocument,userdom2,userdom3 userdom1.load (server.mappath("user.xml")) '裝載需要操作的xml文件 userdom2=userdom1.selectsinglenode("alluser") '操作遊標指向alluser節點,句柄給userdom2變量 userdom3=userdom1.createelement("fyw") '新創建一名為fyw的節點,並將句柄給userdom3變量 userdom3.setattribute("name","風雲舞") '為userdom3添加節點屬性,新屬性名為name,值為風雲舞 userdom3.setattribute("pass","123") userdom3.innertext="測試" '設置userdom3節點所包含的數據 userdom2.appendchild(userdom3) 'userdom2即alluser節點下添加userdom3所描述的fyw節點 userdom1.save (server.mappath("user.xml")) '將變動後的新xml數據保存到user.xml %> |
5:修改XML節點
<%@import namespace='system.xml'%> <% dim userdom1=new xmldocument,userdom2 userdom1.load (server.mappath("user.xml")) userdom2=userdom1.selectsinglenode("alluser").getelementsbytagname("fyw") '操作遊標指向alluser節點下的fyw節點 userdom2(0).setattribute("name","風雲舞") '設定fyw節點數組的第一個,將其name屬性值修改為風雲舞 userdom2(0).innertext="測試" '設定fyw節點數組的第一個,將其所包含的數據改為測試 userdom1.save (server.mappath("user.xml")) '將變動後的新xml數據保存到user.xml %> |
6:查找判斷XML節點是否存在
<%@import namespace='system.xml'%> <% dim userdom1=new xmldocument userdom1.load (server.mappath("user.xml")) '裝載需要操作的xml文件 '以下正是本人為什麼要用“用戶帳號”標識用戶唯一身份的目的,查找方便呀:) if userdom1.selectsinglenode("alluser").getelementsbytagname("fyw").count<>0 then t2("fyw節點以存在") %> |
7:批量添加XML節點(在編寫回複帖子時,用第4例提到的方法一個一個填加節點很麻煩,這時可以考慮用此方法批量填加)
<%@import namespace='system.xml'%> <% dim filedom=new xmldocument,filedom2 filedom.load(server.mappath("data/" & request.querystring("dex"))) 'request.querystring("dex")=6.xml filedom2=filedom.createelement("reply") '以下這種方法很方便,而且對xml文件的結構排版也很好,合理的空格和回車可以表現良好的xml文檔結構 filedom2.innerxml=vbcrlf & " <anthor>" & session("who") & "</anthor>" & vbcrlf & " <date>" & now & "</date>" & vbcrlf & " <gengxindate>" & now & "</gengxindate>" & vbcrlf & " <body>" & neirong.value & "</body>" & vbcrlf & " " filedom.selectsinglenode("document/record").appendchild(filedom2) filedom.save(server.mappath("data/" & request.querystring("dex"))) 'request.querystring("dex")=6.xml %> |
8:刪除XML節點
<%@import namespace='system.xml'%> <% dim userdom1=new xmldocument,userdom2 userdom1.load (server.mappath("user.xml")) userdom1.documentelement.removechild (userdom1.selectsinglenode("alluser/fyw")) '刪除alluser節點下的所有fyw節點 userdom1.save (server.mappath("user.xml")) %> |
9:創建新的XML文件(可以創建任何類型後綴的文件,不局於XML文件)
<%@import namespace='system.io'%> <% dim newfile=new streamwriter(server.mappath("data/" & new directoryinfo(server.mappath("data")).getfiles().length+1 & ".xml"),false,system.text.encoding.default) '以上我們指定默認編碼方式為system.text.encoding.default,或者可改為system.text.encoding.getencoding("gb2312"),不然將以utf8編碼那樣xml含有中文就無法正常工作了 newfile.write ("<?xml version=" & chr(34) & "1.0" & chr(34) & " encoding=" & chr(34) & "gb2312" & chr(34) & "?>" & _ vbcrlf & "<?xml-stylesheet type='text/xsl' href='../file.aspx?dex=" & filelength+1 & ".xml'?>" & vbcrlf & _ "<document>" & vbcrlf & " <record>" & vbcrlf & " <anthor>" & session("who") & "</anthor>" & vbcrlf & _ " <title>" & server.htmlencode(biaoti.value) & "</title>" & vbcrlf & " <date>" & now & "</date>" & vbcrlf & _ " <gengxindate>" & now & "</gengxindate>" & vbcrlf & " <body>" & server.htmlencode(neirong.text) & "</body>" & vbcrlf & _ " </record>" & vbcrlf & "</document>") newfile.close:newfile=nothing %> |
10:刪除指定文件
<%@import namespace='system.io'%> |
11:用cookies實現7秒內不許重複灌水
<% ifnotrequest.cookies("lshdicbbs")isnothingthen ifisdate(request.cookies("lshdicbbs")("guanshui"))=falsethenresponse.cookies("lshdicbbs")("guanshui")=now ifdatediff("s",request.cookies("lshdicbbs")("guanshui"),now)<7thenresponse.write("7秒內禁止重複發貼灌水"):response.cookies("lshdicbbs")("guanshui")=now:response.end endif response.cookies("lshdicbbs")("guanshui")=now %> |
12:用正則表達式限製用戶提交的數據必須為英文字母(有興趣可延伸強化為支持英文字母+數字的形式)
<% dimname1=request.form("username") ifregex.replace(name1,"[a-z]+","",RegexOptions.IgnoreCase)<>""thent2("帳號名必須使用A-Za-z範圍的英文字母") %> |
13:擴展提示工具(早先原創腳本,可根據需要修改)
<divstyle='position:absolute;left:0;top:0;border-bottom:1solidgreen;border-right:1solidgreen;border-left:1solidcccccc;border-top:1solidcccccc;display:none;z-index:500;background-color:#FFF7FF;padding:2;white-Space:nowrap;table-Layout:fixed;'id=showdiv></div> <script> varoldtext="加速變量",colors1=newArray("#FFECD5","#FFF7FF","#FFFFEB","white","#F5FFEB","#EEFAFF","#FFFFEE","#EDFFFC") functiondocument.onmousemove(){ try{ if(event.srcElement.getAttribute('lshdic')) { showdiv.style.left=event.x-3;showdiv.style.top=event.y+document.body.scrollTop+18;if(event.srcElement.lshdic!=oldtext){oldtext=event.srcElement.lshdic;showdiv.innerText=oldtext;showdiv.style.backgroundColor=colors1[Math.round(Math.random()*colors1.length)]};if(showdiv.style.display=='none')showdiv.style.display='' }else{if(showdiv.style.display=='')showdiv.style.display='none';}}catch(e){} } </script> <a href=https://www.chinaz.com title='歡迎訪問中國站長站'>中國站長站</a> <a href=https://bbs.chinaz.com/ title='歡迎訪問藍麗技術論壇 2003-12-610:31:32'>中國站長論壇</a> |
第五節:神劍在此、贈我知音
經過以上4個章節的艱苦學習,我相信您以基本了解了如何用後台程序結合XML數據庫實現複雜的論壇和係統,但通讀N邊也起不了實際作用,你必須著手去做,才能在實踐中總結出自己的經驗,本文章僅僅是個輔助參考而已
由於時間有限,本人隻能將親手開發的ASP。NET版本的XML無數據庫論壇(全稱:藍麗NetXml無數據庫論壇1.0)奉獻給各位研究,由於本人的ASP。NET虛擬空間有點問題,無法提供在線演示,現僅提供全部原代碼下載(以上13例原代碼多數采摘於本係統中),地址:https://www.lshdic.com/download/netxmlbbs.rar,下載後可參考幫助文件,在您自己的ASP.NET服務器上測試。
最後更新:2017-04-02 00:06:33