大家在用httphandler的時候,一般都會有兩個大的疑問(當然,前提是你有鑽研精神的話,呵呵)
1. isreusable到底什麼意思?
老實說,這個屬性很多人都感興趣,但搞懂的人確實不多。msdn中的介紹也是不知所以然。
獲取乙個值,該值指示其他請求是否可以使用 ihttphandler 例項。該屬性預設為false
我來這麼說吧,首先我們為什麼使用自定義的handler呢?簡單的說,我們是希望能接管掉某些請求,對吧?最常見的應用如下
對進行處理。例如所有都輸出乙個水印。或者防止盜鏈到設計
知道上述的需求之後,我們再來看一下後台的設計。httphandler其實就是實現了ihttphandler介面的乙個型別,它要工作,就必須通過 asp.net所提供的一些所謂的factory去建立例項,然後呼叫它的processrequest方法。其實就這麼簡單
因為建立物件例項在伺服器肯定是需要占用資源的,那麼我們就勢必要考慮這些請求能不能在一定程式上去復用。這就是isreusable的初衷
事實上,我們對這種復用並不會陌生。平常我們就知道物件池和連線池的技術。handler的reuse也是乙個池的概念。
好了,說了這麼一堆的概念,我們來講一講該屬性設定為true和設定為false的區別。
設定為true,則通常情況下,就建立一次例項
設定為false,則每次請求都需要建立例項
我們來看乙個例子。為了做測試,我寫了如下**
**很簡單,我通過乙個文字檔案的方式記錄物件什麼建立的,什麼時候發起請求和結束請求的。現在我先設定isreusable為false
在除錯之前,我們還需要設定一下web.config,新增乙個httphandler的註冊
這裡作為演示目的,我就犧牲一下自己,用這個handler來監聽所有字尾名為chenxizhang的請求
開啟瀏覽器,輸入類似下面這樣的**http://localhost:6994/test.chenxizhang
快速地重新整理幾次,然後關閉瀏覽器。找到**根目錄下面的乙個log.txt檔案,會看到下面的文字
2009/6/15 11:28:30物件例項被建立
2009/6/15 11:28:30當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:28:30結束呼叫
2009/6/15 11:28:31物件例項被建立
2009/6/15 11:28:31當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:28:31結束呼叫
2009/6/15 11:28:31物件例項被建立
2009/6/15 11:28:31當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:28:31結束呼叫
2009/6/15 11:28:32物件例項被建立
2009/6/15 11:28:32當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:28:32結束呼叫
2009/6/15 11:28:32物件例項被建立
2009/6/15 11:28:32當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:28:32結束呼叫
2009/6/15 11:28:32物件例項被建立
2009/6/15 11:28:32當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:28:32結束呼叫
2009/6/15 11:28:32物件例項被建立
2009/6/15 11:28:32當前被呼叫的請求是:/test.chenxizhang
我們可以看到,每次都請求都需要建立例項
然後,我們去修改一下isreusable屬性為true,再執行,就可以看到下面這樣的輸出結果了
2009/6/15 11:23:34物件例項被建立
2009/6/15 11:23:34當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:23:34結束呼叫
2009/6/15 11:24:40當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:24:40結束呼叫
2009/6/15 11:24:40當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:24:40結束呼叫
2009/6/15 11:24:40當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:24:40結束呼叫
2009/6/15 11:24:40當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:24:40結束呼叫
2009/6/15 11:24:40當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:24:40結束呼叫
2009/6/15 11:24:41當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:24:41結束呼叫
2009/6/15 11:24:41當前被呼叫的請求是:/test.chenxizhang
2009/6/15 11:24:41結束呼叫
也就是說,物件只被建立了一次。後面呼叫就重複利用了。這樣看起來是不是還不錯呢?
通常意義上說,isreusable設定為true可以提高效能,尤其是說這種handler初始化的時候需要做很多事情的情況下。但為什麼預設又設定為false呢?
因為如果設定為true,也就是所有有使用者,所有請求都共享乙個物件例項,那麼可能造成什麼問題呢?
最典型的問題就是你要注意這個型別中成員變數的執行緒安全性問題,例如某個請求上來之後,修改了某個變數;然後做其他的事情,緊接著其他請求也上來了,它又修改了變數,這可能就有問題。
這一點我倒認為沒有什麼大不了的,我也算是寫過一些handler的,但其實比較少真的複雜到要搞一堆變數。如果是那樣,是需要檢討的
我同時還想到另外乙個問題,假設isreusable是設定為true的,同時又假設它的processrequest卻又需要比較長時間才能完成。那麼會怎麼樣呢?
就是說前乙個請求還沒有完成,這時候又有第二個請求過來。該如何處理?
上面的**中,我加入乙個讓當前執行緒休眠的**:讓它休眠10秒鐘。此時,我們來重新整理瀏覽器看看會怎麼樣
2009/6/15 12:05:59物件例項被建立
2009/6/15 12:05:59當前被呼叫的請求是:/ie.chenxizhang
2009/6/15 12:06:02物件例項被建立
2009/6/15 12:06:02當前被呼叫的請求是:/google.chenxizhang
2009/6/15 12:06:09結束呼叫 //這一句是ie.chenxizhang結束了
2009/6/15 12:06:12結束呼叫 //這一句是google.chenxizhang結束了
我用了兩個瀏覽器來模擬兩個使用者的操作。你會驚奇地發現,雖然我們設定為true,但仍然建立了多個例項。這又是咋回事呢
這個問題要這麼理解了:因為現在是執行緒阻塞了,所以asp.net引擎會檢測到這一點,他必須建立另外例項出來,否則很顯然,第二個請求就必須等第乙個請求結束之後才能開始工作,這顯然是不可以接受的,這個現象,在大容量使用者併發的時候可能是乙個災難
好吧,再繞回來說,假如我們的操作時間比較長,但什麼時候又不需要建立多個例項呢?答案就是說,如果非同步的話。
也正因為可能會有非同步的情況,所以就出現了我們剛才所說的執行緒安全性問題。可以配合鎖定機制避免一些問題。
所以,針對isreusable屬性,我總結如下:
這個屬性預設為false(visual studio提供的模板預設將其設定為false)
如果設定為true,能提高效能,但要注意執行緒之間安全性問題
如果設定為false,則執行緒是安全的
2. 如何在handler中使用會話狀態(session)?
有些朋友在使用handler的時候,念念不忘原先在頁面程式設計中的會話狀態(session),乙個典型的問題就是:在handler裡面能不能使用我的使用者狀態資訊呀?
例如,能不能新增下面這樣的**呢
context.response.write("當前使用者的狀態值為:" + context.session["id"].tostring());
答案是:當然可以。
先別忙著樂,雖然可以新增這樣的**,但它預設卻無法工作。你會收到下面這樣的錯誤訊息:未將物件設定到引用的例項
但是,假設你就是認準了這個非用不可,那麼你也可以通過下面的方式來實現
為該型別實現乙個介面:irequiressessionstate
這個介面不需要有任何方法實現,只需要定義一下就可以了。所以整個案例的**,如下
HttpHandler開發的兩個重點問題
大家在用httphandler的時候,一般都會有兩個大的疑問 當然,前提是你有鑽研精神的話,呵呵 老實說,這個屬性很多人都感興趣,但搞懂的人確實不多。msdn中的介紹也是不知所以然。獲取乙個值,該值指示其他請求是否可以使用ihttphandler例項。該屬性預設為false 我來這麼說吧,首先我們為...
httphandler的配置幾個屬性介紹
偷懶。直接從微軟官網摘下來 屬性屬性 說明 path 必選的屬性。指定路徑屬性可以包含單個 url 路徑或簡單的萬用字元字串 如 aspx type 必選的屬性。指定逗號分隔的類 程式集組合。asp.net 首先在應用程式的專用 bin 目錄中搜尋程式集 dll,然後在系統程式集快取中搜尋程式集 d...
開發兩則小記
var wshshell newactivexobject wscript.shell var path if getosversion 64 path wshshell.regread hkey local machine software wow6432node pzdnsoft path el...