【轉載】DotNET靜態頁面生成解決方案

靜態頁面有訪問速度快、容易被搜索引擎注意到等優點,將網站的部分頁面轉換成靜態頁面來進行速度和搜索引擎的優化是一種很好的策略。本文將介紹我司生成靜態頁面的一種解決方案:

ASP.NET的頁面生成機制大概如下:

當服務器接收到一個.net頁面的Request的時候,將會調用.net的服務模塊,然後生成對應頁面的一個對象,在其中就有我們所做的數據的操作(比如從數據庫檢索數據、從Request中提取參數、從Session或Cookie讀出或寫入內容以及其它的運算),等所有操作做完了以後,服務模塊會自動調用一個叫Render的函數,這個函數負責的工作叫呈現,其實就是將服務模塊解析出來的HTML輸出到客戶端。那我們要生成靜態頁面就得在它身上動動手腳。

現在切入點已經找到,不再茫然無半點頭緒,不過,問題也就立刻出現了,既然是個函數是負責將輸出寫到客戶端,那我們怎麼載取要輸入到客戶端的文本內容呢?其實截取很容易,只要在子類重寫一下Render就可以了,問題出在,Render的函數原形如下:

protected void Render(System.Web.UI.HtmlTextWriter writer);

HtmlTextWriter是什麼東西?這個嘛,可以看一下MSDN,下面是它的類繼承圖:

System.Object
System.MarshalByRefObject
System.IO.TextWriter
System.Web.UI.HtmlTextWriter

說到這裏,我們最好先介紹一下關於.NET的IO模型。.NET的文件IO是以流的形式存在的,即是說,將文件或內存或網絡數據傳輸等當成一個流對象,可以對其進行讀取和寫入,最基本的幾個流操作如下:

1、 可以從流讀取。讀取是從流到數據結構(如字節數組)的數據傳輸。
2、 可以向流寫入。寫入是從數據源到流的數據傳輸。
3、 流可以支持查找。查找是對流內的當前位置進行查詢和修改。

流支持以上全部或部分操作,這要決定於“流”本身的性質,例流,NetworkStreams這個流就不支持查找操作,這是由網絡的性質決定的。流的基礎類放在System.IO命名空間中。

OK,瞭解了流的基本概念後,就可以來看看我們究竟要怎麼截取生成的HTML了。

從上面的類繼承圖可以看到,HtmlTextWriter 是System.IO.TextWriter的一個子類。再看看它的構造函數:

public HtmlTextWriter(TextWriter);

哦,需要一個TextWriter做參數,TextWriter是它的基類,其實它是一個抽象類,看來,HtmlTextWriter不想自己定義自己的輸出流,而是希望將輸出結果送到指定的一個目的地,一般到說,是客戶端瀏覽器,不過,我們現在得將它轉轉向,將它輸出到我們指定的文件就行了。

那我們再看看,一般我們寫文件用的是什麼類?哦,對了,是StreamWriter類,那查查它的類繼承圖吧,或許有點幫助:

System.Object
System.MarshalByRefObject
System.IO.TextWriter
System.IO.StreamWriter

哈哈,果然不出所料,它的基礎類也是TextWriter,這樣就非常好了。那說明我們只要生成一個代表一個文件的一個StreamWriter對象,然後將其做爲HtmlTextWriter構造函數的參數,然後生成一個HtmlTextWriter對象,那麼這個HtmlTextWriter寫入的就是我們的目標文件了。同理,生成一個MemoryStream,然後將其做爲HtmlTextWriter構造函數的參數就可以將生成的HTML代碼寫到我們指定的內存塊。

好,那讓我們試試看,可以這樣做

override protected void Render(System.Web.UI.HtmlTextWriter writer)
{
//MemoryStream ms = new MemoryStream();
//StreamWriter sww = new StreamWriter(ms);
StreamWriter swr = new StreamWriter(Server.MapPath("./") + "text.htm");
System.Web.UI.HtmlTextWriter htmlw = new HtmlTextWriter(swr);
base.Render(htmlw);
htmlw.Flush();
htmlw.Close();
//string strLL = System.Text.Encoding.UTF8.GetString(ms.ToArray());
//Response.Write(strLL);
}

這段代碼很好理解,無須多說,如果將輸出流換成註釋中的那些代碼,那HTML輸出將放到指定內存塊,然後又轉存到一個string對象中,最後用Response.Write寫到客戶端。一個很奇怪的過程,好象是無用功,其實,在這過程中,體現了我們對其能隨意操作了。爲什麼要將之存在內存塊裏,還要轉換成string對象?因爲,生成的HTML中,有ViewState,和一些無用的東西,我們最好將之去掉再輸出。

這樣子,每次請求這張頁面就再也不是在瀏覽器顯示,而是寫入了文件或我們指定的內存。 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章