• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            C++ Jounior

            once setback,once inspiration,once self-awareness
            重要的是這個磨練過程,而不是結果,要的是你粗壯的腿,而不是你身上背的那袋鹽巴

             

            面向對象的三個基本特征(講解)

            面向對象的三個基本特征(講解)

            面向對象的三個基本特征是:封裝、繼承、多態。

            o_OOBase.gif

            封裝

            封裝最好理解了。封裝是面向對象的特征之一,是對象和類概念的主要特性。

            封裝,也就是把客觀事物封裝成抽象的類,并且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏。

            繼承

            面向對象編程 (OOP) 語言的一個主要功能就是 繼承 。繼承是指這樣一種能力:它可以使用現有類的所有功能,并在無需重新編寫原來的類的情況下對這些功能進行擴展。

            通過繼承創建的新類稱為“子類”或“派生類”。

            被繼承的類稱為 基類 父類 超類

            繼承的過程,就是從一般到特殊的過程。

            要實現繼承,可以通過 繼承 Inheritance )和 組合 Composition )來實現。

            在某些 OOP 語言中,一個子類可以繼承多個基類。但是一般情況下,一個子類只能有一個基類,要實現多重繼承,可以通過多級繼承來實現。

            ?

            繼承概念的實現方式有三類:實現繼承、接口繼承和可視繼承。

            ????????? 實現繼承是指使用基類的屬性和方法而無需額外編碼的能力;

            ????????? 接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力;

            ????????? 可視繼承是指子窗體(類)使用基窗體(類)的外觀和實現代碼的能力。

            在考慮使用繼承時,有一點需要注意,那就是兩個類之間的關系應該是 屬于 關系。例如, Employee 是一個人, Manager 也是一個人,因此這兩個類都可以繼承 Person 類。但是 Leg 類卻不能繼承 Person 類,因為腿并不是一個人。

            抽象類僅定義將由子類創建的一般屬性和方法,創建抽象類時,請使用關鍵字 Interface 而不是 Class

            OO 開發范式大致為:劃分對象 抽象類 將類組織成為層次化結構 ( 繼承和合成 ) → 用類與實例進行設計和實現幾個階段。

            ?

            多態

            多態性( polymorphisn )是允許你將父對象設置成為和一個或更多的他的子對象相等的技術,賦值之后,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。

            實現多態,有二種方式,覆蓋,重載。

            覆蓋,是指子類重新定義父類的虛函數的做法。

            重載,是指允許存在多個同名函數,而這些函數的參數表不同(或許參數個數不同,或許參數類型不同,或許兩者都不同)。

            其實,重載的概念并不屬于 面向對象編程 ,重載的實現是:編譯器根據函數不同的參數表,對同名函數的名稱做修飾,然后這些同名函數就成了不同的函數(至少對于編譯器來說是這樣的)。如,有兩個同名函數: function func(p:integer):integer; function func(p:string):integer; 。那么編譯器做過修飾后的函數名稱可能是這樣的: int_func str_func 。對于這兩個函數的調用,在編譯器間就已經確定了,是靜態的(記住:是靜態)。也就是說,它們的地址在編譯期就綁定了(早綁定),因此,重載和多態無關!真正和多態相關的是 覆蓋 。當子類重新定義了父類的虛函數后,父類指針根據賦給它的不同的子類指針,動態(記住:是動態!)的調用屬于子類的該函數,這樣的函數調用在編譯期間是無法確定的(調用的子類的虛函數的地址無法給出)。因此,這樣的函數地址是在運行期綁定的(晚邦定)。結論就是:重載只是一種語言特性,與多態無關,與面向對象也無關!引用一句 Bruce Eckel 的話: 不要犯傻,如果它不是晚邦定,它就不是多態。

            那么,多態的作用是什么呢?我們知道,封裝可以隱藏實現細節,使得代碼模塊化;繼承可以擴展已存在的代碼模塊(類);它們的目的都是為了 —— 代碼重用。而多態則是為了實現另一個目的 —— 接口重用!多態的作用,就是為了類在繼承和派生的時候,保證使用 家譜 中任一類的實例的某一屬性時的正確調用。

            ?

            概念講解

            泛化( Generalization

            o_Generalization.gif

            圖表 1 泛化

            在上圖中,空心的三角表示繼承關系(類繼承),在 UML 的術語中,這種關系被稱為泛化( Generalization )。 Person( ) 是基類, Teacher( 教師 ) Student( 學生 ) Guest( 來賓 ) 是子類。

            若在邏輯上 B A 的“一種”,并且 A 的所有功能和屬性對 B 而言都有意義,則允許 B 繼承 A 的功能和屬性。

            例如, 教師是人, Teacher Person 的“一種”( a kind of )。 那么類 Teacher 可以從類 Person 派生(繼承)。

            如果 A 是基類, B A 的派生類,那么 B 將繼承 A 的數據和函數。

            如果類 A 和類 B 毫不相關,不可以為了使 B 的功能更多些而讓 B 繼承 A 的功能和屬性。

            若在邏輯上 B A 的“一種”( a kind of ),則允許 B 繼承 A 的功能和屬性。

            ?

            聚合(組合)

            o_aggregationBase.gif

            圖表 2 組合

            若在邏輯上 A B 的“一部分”( a part of ),則不允許 B A 派生,而是要用 A 和其它東西組合出 B

            例如,眼( Eye )、鼻( Nose )、口( Mouth )、耳( Ear )是頭( Head )的一部分,所以類 Head 應該由類 Eye Nose Mouth Ear 組合而成,不是派生(繼承)而成。

            ?

            聚合的類型分為無、共享 ( 聚合 ) 、復合 ( 組合 ) 三類。

            ?

            聚合( aggregation

            ?

            o_aggregation.gif

            圖表 3 共享

            上面圖中,有一個菱形(空心)表示聚合( aggregation )(聚合類型為共享),聚合的意義表示 has-a 關系。聚合是一種相對松散的關系,聚合類 B 不需要對被聚合的類 A 負責。

            ?

            組合( composition

            o_composition.gif

            圖表 4 復合

            這幅圖與上面的唯一區別是菱形為實心的,它代表了一種更為堅固的關系 —— 組合( composition )(聚合類型為復合)。組合表示的關系也是 has-a ,不過在這里, A 的生命期受 B 控制。即 A 會隨著 B 的創建而創建,隨 B 的消亡而消亡。

            ?

            依賴 (Dependency)

            o_Dependency.gif

            圖表 5 依賴

            這里 B A 的關系只是一種依賴 (Dependency) 關系,這種關系表明,如果類 A 被修改,那么類 B 會受到影響。

            ==================接口與抽象類有什么區別==================
            abstract class和interface是Java語言中對于抽象類定義進行支持的兩種機制,正是由于這兩種機制的存在,才賦予了Java強大的面向對象能力。abstract class和interface之間在對于抽象類定義的支持方面具有很大的相似性,甚至可以相互替換,因此很多開發者在進行抽象類定義時對于abstract class和interface的選擇顯得比較隨意。其實,兩者之間還是有很大的區別的,對于它們的選擇甚至反映出對于問題領域本質的理解、對于設計意圖的理解是否正確、合理。本文將對它們之間的區別進行一番剖析,試圖給開發者提供一個在二者之間進行選擇的依據。

            理解抽象類

            abstract class和interface在Java語言中都是用來進行抽象類(本文中的抽象類并非從abstract class翻譯而來,它表示的是一個抽象體,而abstract class為Java語言中用于定義抽象類的一種方法,請讀者注意區分)定義的,那么什么是抽象類,使用抽象類能為我們帶來什么好處呢?

            ?

            ?

            在面向對象的概念中,我們知道所有的對象都是通過類來描繪的,但是反過來卻不是這樣。并不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。抽象類往往用來表征我們在對問題領域進行分析、設計中得出的抽象概念,是對一系列看上去不同,但是本質上相同的具體概念的抽象。比如:如果我們進行一個圖形編輯軟件的開發,就會發現問題領域存在著圓、三角形這樣一些具體概念,它們是不同的,但是它們又都屬于形狀這樣一個概念,形狀這個概念在問題領域是不存在的,它就是一個抽象概念。正是因為抽象的概念在問題領域沒有對應的具體概念,所以用以表征抽象概念的抽象類是不能夠實例化的。

            在面向對象領域,抽象類主要用來進行類型隱藏。我們可以構造出一個固定的一組行為的抽象描述,但是這組行為卻能夠有任意個可能的具體實現方式。這個抽象描述就是抽象類,而這一組任意個可能的具體實現則表現為所有可能的派生類。模塊可以操作一個抽象體。由于模塊依賴于一個固定的抽象體,因此它可以是不允許修改的;同時,通過從這個抽象體派生,也可擴展此模塊的行為功能。熟悉OCP的讀者一定知道,為了能夠實現面向對象設計的一個最核心的原則OCP(Open-Closed Principle),抽象類是其中的關鍵所在。


            從語法定義層面看abstract class和interface

            在語法層面,Java語言對于abstract class和interface給出了不同的定義方式,下面以定義一個名為Demo的抽象類為例來說明這種不同。

            使用abstract class的方式定義Demo抽象類的方式如下:

            abstract class Demo {
            abstract void method1();
            abstract void method2();

            使用interface的方式定義Demo抽象類的方式如下:

            interface Demo {
            void method1();
            void method2();

            }

            在abstract class方式中,Demo可以有自己的數據成員,也可以有非abstarct的成員方法,而在interface方式的實現中,Demo只能夠有靜態的不能被修改的數據成員(也就是必須是static final的,不過在interface中一般不定義數據成員),所有的成員方法都是abstract的。從某種意義上說,interface是一種特殊形式的abstract class。

            從編程的角度來看,abstract class和interface都可以用來實現"design by contract"的思想。但是在具體的使用上面還是有一些區別的。

            首先,abstract class在Java語言中表示的是一種繼承關系,一個類只能使用一次繼承關系。但是,一個類卻可以實現多個interface。也許,這是Java語言的設計者在考慮Java對于多重繼承的支持方面的一種折中考慮吧。

            其次,在abstract class的定義中,我們可以賦予方法的默認行為。但是在interface的定義中,方法卻不能擁有默認行為,為了繞過這個限制,必須使用委托,但是這會 增加一些復雜性,有時會造成很大的麻煩。

            在抽象類中不能定義默認行為還存在另一個比較嚴重的問題,那就是可能會造成維護上的麻煩。因為如果后來想修改類的界面(一般通過abstract class或者interface來表示)以適應新的情況(比如,添加新的方法或者給已用的方法中添加新的參數)時,就會非常的麻煩,可能要花費很多的時間(對于派生類很多的情況,尤為如此)。但是如果界面是通過abstract class來實現的,那么可能就只需要修改定義在abstract class中的默認行為就可以了。

            同樣,如果不能在抽象類中定義默認行為,就會導致同樣的方法實現出現在該抽象類的每一個派生類中,違反了"one rule,one place"原則,造成代碼重復,同樣不利于以后的維護。因此,在abstract class和interface間進行選擇時要非常的小心。


            從設計理念層面看abstract class和interface

            上面主要從語法定義和編程的角度論述了abstract class和interface的區別,這些層面的區別是比較低層次的、非本質的。本小節將從另一個層面:abstract class和interface所反映出的設計理念,來分析一下二者的區別。作者認為,從這個層面進行分析才能理解二者概念的本質所在。

            前面已經提到過,abstarct class在Java語言中體現了一種繼承關系,要想使得繼承關系合理,父類和派生類之間必須存在"is a"關系,即父類和派生類在概念本質上應該是相同的(參考文獻〔3〕中有關于"is a"關系的大篇幅深入的論述,有興趣的讀者可以參考)。對于interface 來說則不然,并不要求interface的實現者和interface定義在概念本質上是一致的,僅僅是實現了interface定義的契約而已。為了使論述便于理解,下面將通過一個簡單的實例進行說明。

            考慮這樣一個例子,假設在我們的問題領域中有一個關于Door的抽象概念,該Door具有執行兩個動作open和close,此時我們可以通過abstract class或者interface來定義一個表示該抽象概念的類型,定義方式分別如下所示:

            使用abstract class方式定義Door:

            abstract class Door {
            abstract void open();
            abstract void close();
            }


            使用interface方式定義Door:


            interface Door {
            void open();
            void close();
            }


            其他具體的Door類型可以extends使用abstract class方式定義的Door或者implements使用interface方式定義的Door。看起來好像使用abstract class和interface沒有大的區別。

            如果現在要求Door還要具有報警的功能。我們該如何設計針對該例子的類結構呢(在本例中,主要是為了展示abstract class和interface反映在設計理念上的區別,其他方面無關的問題都做了簡化或者忽略)?下面將羅列出可能的解決方案,并從設計理念層面對這些不同的方案進行分析。

            解決方案一:

            簡單的在Door的定義中增加一個alarm方法,如下:

            abstract class Door {
            abstract void open();
            abstract void close();
            abstract void alarm();
            }


            或者

            interface Door {
            void open();
            void close();
            void alarm();
            }


            那么具有報警功能的AlarmDoor的定義方式如下:

            class AlarmDoor extends Door {
            void open() { … }
            void close() { … }
            void alarm() { … }
            }


            或者

            class AlarmDoor implements Door {
            void open() { … }
            void close() { … }
            void alarm() { … }

            這種方法違反了面向對象設計中的一個核心原則ISP(Interface Segregation Priciple),在Door的定義中把Door概念本身固有的行為方法和另外一個概念"報警器"的行為方法混在了一起。這樣引起的一個問題是那些僅僅依賴于Door這個概念的模塊會因為"報警器"這個概念的改變(比如:修改alarm方法的參數)而改變,反之依然。

            解決方案二:

            既然open、close和alarm屬于兩個不同的概念,根據ISP原則應該把它們分別定義在代表這兩個概念的抽象類中。定義方式有:這兩個概念都使用abstract class方式定義;兩個概念都使用interface方式定義;一個概念使用abstract class方式定義,另一個概念使用interface方式定義。

            顯然,由于Java語言不支持多重繼承,所以兩個概念都使用abstract class方式定義是不可行的。后面兩種方式都是可行的,但是對于它們的選擇卻反映出對于問題領域中的概念本質的理解、對于設計意圖的反映是否正確、合理。我們一一來分析、說明。

            如果兩個概念都使用interface方式來定義,那么就反映出兩個問題:1、我們可能沒有理解清楚問題領域,AlarmDoor在概念本質上到底是Door還是報警器?2、如果我們對于問題領域的理解沒有問題,比如:我們通過對于問題領域的分析發現AlarmDoor在概念本質上和Door是一致的,那么我們在實現時就沒有能夠正確的揭示我們的設計意圖,因為在這兩個概念的定義上(均使用interface方式定義)反映不出上述含義。

            如果我們對于問題領域的理解是:AlarmDoor在概念本質上是Door,同時它有具有報警的功能。我們該如何來設計、實現來明確的反映出我們的意思呢?前面已經說過,abstract class在Java語言中表示一種繼承關系,而繼承關系在本質上是"is a"關系。所以對于Door這個概念,我們應該使用abstarct class方式來定義。另外,AlarmDoor又具有報警功能,說明它又能夠完成報警概念中定義的行為,所以報警概念可以通過interface方式定義。如下所示:

            abstract class Door {
            abstract void open();
            abstract void close();
            }
            interface Alarm {
            void alarm();
            }
            class AlarmDoor extends Door implements Alarm {
            void open() { … }
            void close() { … }
            void alarm() { … }
            }


            這種實現方式基本上能夠明確的反映出我們對于問題領域的理解,正確的揭示我們的設計意圖。其實abstract class表示的是"is a"關系,interface表示的是"like a"關系,大家在選擇時可以作為一個依據,當然這是建立在對問題領域的理解上的,比如:如果我們認為AlarmDoor在概念本質上是報警器,同時又具有Door的功能,那么上述的定義方式就要反過來了。


            ==================游標,可不可以嵌套,可以用什么辦法替換使用游標==================
            For standard SQL, it is surely that cursors can be nested, just like LOOPs can be nested.
            Below is an example written in PL/SQL:

            Declare
            ?? Cursor_H IS CURSOR AS SELECT * FROM customer_header;
            ?? Cursor_L (p_cust_id) IS CURSOR AS SELECT * FROM customer_detail WHERE customer_id = p_cust_id;
            Begin
            ?? For H in Cursor_H
            ?? Loop
            ???????? Print customer_header;
            ???????? For L in Cursor_L (H.customer_id)
            ???????? Loop
            ??????????????? Print_customer_detail;
            ???????? End loop;
            ?? End loop;
            End;


            In PL/SQL, you can use Direct-Loop instead of cursor;
            For example:

            Begin
            ?? For H in (SELECT * FROM customer_header)?????? -- instead of Cursor_H
            ?? Loop
            ???????? Print customer_header;
            ???????? For L in (SELECT * FROM customer_detail WHERE customer_id = H.customer_id)????? -- instead of Cursor_L
            ???????? Loop
            ??????????????? Print_customer_detail;
            ???????? End loop;
            ?? End loop;
            End;
            =======================
            MVC是一種目前廣泛流行的軟件設計模式,早在70年代,IBM就推出了Sanfronscisico項目計劃,其實就是MVC設計模式的研究。近來,隨著J2EE的成熟,它正在成為在J2EE平臺上推薦的一種設計模型,也是廣大Java開發者非常感興趣的設計模型。MVC模式也逐漸在PHP和ColdFusion開發者中運用,并有增長趨勢。隨著網絡應用的快速增加,MVC模式對于Web應用的開發無疑是一種非常先進的設計思想,無論你選擇哪種語言,無論應用多復雜,它都能為你理解分析應用模型時提供最基本的分析方法,為你構造產品提供清晰的設計框架,為你的軟件工程提供規范的依據。  

            MVC設計思想

            MVC英文即Model-View-Controller,即把一個應用的輸入、處理、輸出流程按照Model、View、Controller的方式進行分離,這樣一個應用被分成三個層——模型層、視圖層、控制層。

            視圖(View)代表用戶交互界面,對于Web應用來說,可以概括為HTML界面,但有可能為XHTML、XML和Applet。隨著應用的復雜性和規模性,界面的處理也變得具有挑戰性。一個應用可能有很多不同的視圖,MVC設計模式對于視圖的處理僅限于視圖上數據的采集和處理,以及用戶的請求,而不包括在視圖上的業務流程的處理。業務流程的處理交予模型(Model)處理。比如一個訂單的視圖只接受來自模型的數據并顯示給用戶,以及將用戶界面的輸入數據和請求傳遞給控制和模型。

            模型(Model):就是業務流程/狀態的處理以及業務規則的制定。業務流程的處理過程對其它層來說是黑箱操作,模型接受視圖請求的數據,并返回最終的處理結果。業務模型的設計可以說是MVC最主要的核心。目前流行的EJB模型就是一個典型的應用例子,它從應用技術實現的角度對模型做了進一步的劃分,以便充分利用現有的組件,但它不能作為應用設計模型的框架。它僅僅告訴你按這種模型設計就可以利用某些技術組件,從而減少了技術上的困難。對一個開發者來說,就可以專注于業務模型的設計。MVC設計模式告訴我們,把應用的模型按一定的規則抽取出來,抽取的層次很重要,這也是判斷開發人員是否優秀的設計依據。抽象與具體不能隔得太遠,也不能太近。MVC并沒有提供模型的設計方法,而只告訴你應該組織管理這些模型,以便于模型的重構和提高重用性。我們可以用對象編程來做比喻,MVC定義了一個頂級類,告訴它的子類你只能做這些,但沒法限制你能做這些。這點對編程的開發人員非常重要。

            業務模型還有一個很重要的模型那就是數據模型。數據模型主要指實體對象的數據保存(持續化)。比如將一張訂單保存到數據庫,從數據庫獲取訂單。我們可以將這個模型單獨列出,所有有關數據庫的操作只限制在該模型中。

            控制(Controller)可以理解為從用戶接收請求, 將模型與視圖匹配在一起,共同完成用戶的請求。劃分控制層的作用也很明顯,它清楚地告訴你,它就是一個分發器,選擇什么樣的模型,選擇什么樣的視圖,可以完成什么樣的用戶請求。控制層并不做任何的數據處理。例如,用戶點擊一個連接,控制層接受請求后, 并不處理業務信息,它只把用戶的信息傳遞給模型,告訴模型做什么,選擇符合要求的視圖返回給用戶。因此,一個模型可能對應多個視圖,一個視圖可能對應多個模型。

            MVC的優點

            大部分用過程語言比如ASP、PHP開發出來的Web應用,初始的開發模板就是混合層的數據編程。例如,直接向數據庫發送請求并用HTML顯示,開發速度往往比較快,但由于數據頁面的分離不是很直接,因而很難體現出業務模型的樣子或者模型的重用性。產品設計彈性力度很小,很難滿足用戶的變化性需求。MVC要求對應用分層,雖然要花費額外的工作,但產品的結構清晰,產品的應用通過模型可以得到更好地體現。

            首先,最重要的是應該有多個視圖對應一個模型的能力。在目前用戶需求的快速變化下,可能有多種方式訪問應用的要求。例如,訂單模型可能有本系統的訂單,也有網上訂單,或者其他系統的訂單,但對于訂單的處理都是一樣,也就是說訂單的處理是一致的。按MVC設計模式,一個訂單模型以及多個視圖即可解決問題。這樣減少了代碼的復制,即減少了代碼的維護量,一旦模型發生改變,也易于維護。



            MVC設計模型



            其次,由于模型返回的數據不帶任何顯示格式,因而這些模型也可直接應用于接口的使用。

            再次,由于一個應用被分離為三層,因此有時改變其中的一層就能滿足應用的改變。一個應用的業務流程或者業務規則的改變只需改動MVC的模型層。

            控制層的概念也很有效,由于它把不同的模型和不同的視圖組合在一起完成不同的請求,因此,控制層可以說是包含了用戶請求權限的概念。

            最后,它還有利于軟件工程化管理。由于不同的層各司其職,每一層不同的應用具有某些相同的特征,有利于通過工程化、工具化產生管理程序代碼。

            MVC的缺點

            MVC的設計實現并不十分容易, 理解起來比較容易,但對開發人員的要求比較高。MVC只是一種基本的設計思想,還需要詳細的設計規劃。

            模型和視圖的嚴格分離可能使得調試困難一些,但比較容易發現錯誤。

            經驗表明,MVC由于將應用分為三層,意味著代碼文件增多,因此,對于文件的管理需要費點心思。

            綜合上述,MVC是構筑軟件非常好的基本模式,至少將業務處理與顯示分離,強迫將應用分為模型、視圖以及控制層, 使得你會認真考慮應用的額外復雜性,把這些想法融進到架構中,增加了應用的可拓展性。如果能把握到這一點,MVC模式會使得你的應用更加強壯,更加有彈性,更加個性化。
            ??? 引言: MVC如何工作 MVC是一個設計模式,它強制性的使應用程序的輸入、處理和輸出分開。?


            ?·網絡上md5的java實現.??? ?顯示摘要???? 摘要:無意間發現的.不過章章師兄研究的密碼學里md5好象已經用c++實現了.package com.sinosoftgroup.msd.util; /** * * <p>title: </p> * <p>description: </p> * <p>copyright: copyright (c) 2003</p> * <p...... ·jie server開發指南??? ?顯示摘要???? 摘要: 一個簡單的action,返回hello world  package org.jie.demo; import org.jie.server.action.standardaction;import javax.servlet.http.httpservletrequest; class testaction extends standardaction { publi......

            MVC設計模式帶來更好的軟件結構和代碼重用
            mvc如何工作

            mvc是一個設計模式,它強制性的使應用程序的輸入.處理與輸出分開.使用mvc應用程序被分成三個核心部件:模型.視圖.控制器.它們各自處理自己的任務.

            如何處理應用程序的界面變得越來越有挑戰性.mvc一個大的好處是它能為你的應用程序處理很多不同的視圖.在視圖中其實沒有真正的處理發生,不管這些數據是聯機存儲的還是一個雇員列表,作為視圖來講,它只是作為一種輸出數據并允許用戶操縱的方式. 【程序編程相關:Hibernate middlegen中】

            視圖
            視圖是用戶看到并與之交互的界面.對老式的web應用程序來說,視圖就是由html元素組成的界面,在新式的web應用程序中,html依舊在視圖中扮演著重要的角色,但一些新的技術已層出不窮,它們包括macromedia flash與象xhtml,xml/xsl,wml等一些標識語言與web services. 【推薦閱讀:JAVA文件加密器(收藏)】

            控制器
            控制器接受用戶的輸入并調用模型與視圖去完成用戶的需求.所以當單擊web頁面中的超鏈接與發送html表單時,控制器本身不輸出任何東西與做任何處理.它只是接收請求并決定調用哪個模型構件去處理請求,然后用確定用哪個視圖來顯示模型處理返回的數據. 【擴展信息:CruiseControl簡介】

            模型
            模型表示企業數據與業務規則.在mvc的三個部件中,模型擁有最多的處理任務.例如它可能用象ejbs與coldfusion components這樣的構件對象來處理數據庫.被模型返回的數據是中立的,就是說模型與數據格式無關,這樣一個模型能為多個視圖提供數據.由于應用于模型的代碼只需寫一次就可以被多個視圖重用,所以減少了代碼的重復性

            -----------------
            強命名程序集(Strong Name Assembly)的概念

            ? ?因為不同的公司可能會開發出有相同名字的程序集來,如果這些程序集都被復制到同一 個相同的目錄下,最后一個安裝的程序集將會代替前面的程序集。這就是著名的Windows “DLL Hell”出現的原因。
            ??
            ? ?很明顯,簡單的用文件名來區分程序集是不夠的,CLR需要支持某種機制來唯一的標識一個程序集。這就是所謂的強命名程序集。
            ??
            ? ?一個強命名程序集包含四個唯一標志程序集的特性:文件名(沒有擴展名),版本號,語言文化信息(如果有的話),公有秘鑰。
            ??
            ? ?這些信息存儲在程序集的清單(manifest)中。清單包含了程序集的元數據,并嵌入在程序集的某個文件中。
            ??
            ? ?下面的字符串標識了四個不同的程序集文件:
            ??
            ? ?“MyType, Version=1.0.1.0,
            ? ?Culture=neutral, PublicKeyToken=bf5779af662fc055”
            ??
            ? ?“MyType, Version=1.0.1.0,
            ? ?Culture=en-us, PublicKeyToken=bf5779af662fc055”
            ??
            ? ?“MyType, Version=1.0.2.0,
            ? ?Culture=neturl, PublicKeyToken=bf5779af662fc055”
            ??
            ? ?“MyType, Version=1.0.2.0,
            ? ?Culture=neutral, PublicKeyToken=dbe4120289f9fd8a”
            ??
            ? ?如果一個公司想唯一的標識它的程序集,那么它必須首先獲取一個公鑰/私鑰對,然后將共有秘鑰和程序集相關聯。不存在兩個兩個公司有同樣的公鑰/私鑰對的情況,正是這種區分使得我們可以創建有著相同名稱,版本和語言文化信息的程序集,而不引起任何沖突。
            ??
            ? ?與強命名程序集對應的就是所謂的弱命名程序集。(其實就是普通的沒有被強命名的程序集)。兩種程序集在結構上是相同的。都使用相同的PE文件格式,PE表頭,CLR表頭,元數據,以及清單(manifest)。二者之間真正的區別在于:強命名程序集有一個發布者的公鑰/私鑰對簽名,其中的公鑰/私鑰對唯一的標識了程序集的發布者。利用公鑰/私鑰對,我們可以對程序集進行唯一性識別、實施安全策略和版本控制策略,這種唯一標識程序集的能力使得應用程序在試圖綁定一個強命名程序集時,CLR能夠實施某些“已確知安全”的策略(比如只信任某個公司的程序集)。
            請說明在.net中常用的幾種頁面間傳遞參數的方法,并說出他們的優缺點。
            session(viewstate) 簡單,但易丟失
            application 全局
            cookie 簡單,但可能不支持,可能被偽造
            input type="hidden" 簡單,可能被偽造
            url參數 簡單,顯示于地址欄,長度有限
            數據庫 穩定,安全,但性能相對弱
            ===============================asp.net 頁面生命周期

            錯誤:
            ??? 每個頁面的生命周期為用戶的訪問開始到結束,也就是說程序中的全局變量同時生存到用戶的訪問結束.

            正確:
            ??? 每個頁面的生命周期為用戶的每一次訪問,也就是說每一次客戶端與服務器之間的一個往返過程.全局變量的生命周期在此之間.

            例:
            string gb_string;

            void Page_Load()
            {
            ??? if(!IsPostBack)
            ??? {
            ????? //第一次被訪問的代碼
            ????? gb_string ="Test!";???
            ??? }
            }


            void btnSubmit_Click(Object sender, EventArgs e)
            {
            //在這里gb_string 為空,是這一次postback新建的字符串

            //跟第一次那個被賦值的字符串不是同一對象.
            }

            ASP.NET 頁面生命周期
            1. Page_Init();
            2. Load ViewState and Postback data;
            3. Page_Load();
            4. Handle control events;
            5. Page_PreRender();
            6. Page_Render();
            7. Unload event;
            8. Dispose method called;

            總結:

            在Page_Load()中執行的初始化工作


            ???? 1.一般都是初始化web控件,因為這些控件的狀態(值),由系統自動保存(__VIEWSTATE),
            下次返回時,自動賦值,這是ASP.NET保存"web控件"狀態的特性.
            ??

            ?? 2.但是初始的如果是程序中用到的全局變量,就應該注意他的生命周期的問題.如果函數都在一個生命周期中,全局變量的值當然是一致的.但是如果在"由客戶激發"的事件中,這就不同了,每個客戶事件的激發,都會導致新的頁面生命周期的產生,全局變量的值會丟失,因為它們不在同一頁面生命周期(就像上面出現的錯誤1).


            *********************************************************

            asp.net2.0 頁面生命周期方法

            方法 活動

            Constructor

            Always

            Construct

            Always

            TestDeviceFilter

            Always

            AddParsedSubObject

            Always

            DeterminePostBackMode

            Always

            OnPreInit

            Always

            LoadPersonalizationData

            Always

            InitializeThemes

            Always

            OnInit

            Always

            ApplyControlSkin

            Always

            ApplyPersonalization

            Always

            OnInitComplete

            Always

            LoadPageStateFromPersistenceMedium

            Always

            LoadControlState

            Always

            LoadViewState

            Always

            ProcessPostData1

            Always

            OnPreLoad

            Always

            OnLoad

            Always

            ProcessPostData2

            Always

            RaiseChangedEvents

            Always

            RaisePostBackEvent

            Always

            OnLoadComplete

            Always

            OnPreRender

            Always

            OnPreRenderComplete

            Always

            SavePersonalizationData

            Always

            SaveControlState

            Always

            SaveViewState

            Always

            SavePageStateToPersistenceMedium

            Always

            Render

            Always

            OnUnload

            Always

            查看頁面生命周期的底層細節,我們可以看到 ASP.NET 2.0 中提供的許多功能(例如主題和個性化)將在什么地方容易實現。例如,主題在 IntializeThemes 事件中處理,而個性化數據將在 LoadPersonalizationData 中加載并稍后用于 ApplyPersonalization 方法。請注意,就哪一個 UI 元素將決定 Web 應用程序的最終外觀和感覺而言,方法的順序非常重要。


            在以前寫個一篇關于ASP.NET頁面生命周期的草稿,最近又看了看ASP.NET,做個補充,看看頁面初始過程到底是怎么樣的
            下面是ASP.NET頁面初始的過程:
            1. Page_Init();
            2. Load ViewState;
            3. Load Postback data;
            4. Page_Load();
            5. Handle control events;
            6. Page_PreRender();
            7. Page_Render();
            8. Unload event;
            9. Dispose method called;

            下面對其中的一些過程作下描述:
            1. Page_Init();
            這個過程主要是初始化控件,每次頁面載入執行這個初始過程,包括第一次和以后的Postback(這里說下Postback,其實就可以簡單理解成用戶點
            擊SUBMIT按鈕之類的,把表單<Form>提交給服務器,這就是一次postback),在這里面可以訪問控件,但是這里面的控件值不是我們期待的控件里面 的值,他只是一個控件的初始值(默認值),舉例: 比如一個TextBox1,我們填入了"哈哈",在點擊SUBMIT提交了頁面后,在Page_Init()里面,我們訪 問到的TextBox1.Text不是我們的"哈哈",而是開始的""空字符串,如果TextBox1在我們設計的時候提供了默認值,這里訪問到的也就是提供的默 認值,為什么呢,這就要看下一個過程了.

            對應的事件Page.Init

            2. Load ViewState
            這個過程是載入VIEWSTATE和Postback數據,比如我們上面的TextBox1,這時就賦了"哈哈",所以,在Post_Init()對控件賦值是無意義的,它都會
            在這個過程里被改寫,當然第一次頁面載入例外,因為沒有VIEWSTATE數據。

            沒有對應的事件

            3.Load Postback data;
            上面說了,Postback可以理解成用戶提交表單數據,所以這里就是處理表單數據,當然這里要設計到控件的設計,一般情況不會要我們自己處理這
            個過程,我們暫且略過. (在以前那篇關于ASP.NET頁面生命周期的簡單描述中,把這個過程和Load ViewState放在了一起,其實那是微軟提供的生命周期過程,這里單獨提出來是為 了讓大家明白這是一個單獨的過程)
            ?
            沒有對應的事件
            4. Page_Load();
            這個過程也是每次頁面載入時一定會執行的,但是注意和Page_Init的區別,上面已經涉及了,這里注意的是一般都會用到Page.IsPostBack,該
            值指示該頁是否正為響應客戶端回發而加載,或者它是否正被首次加載和訪問。
            private void Page_Load(object sender, System.EventArgs e)
            {
            ? if(!Page.IsPostBack)
            ? {
            ???//第一次執行的CODE HERE
            ? }
            ? else
            ? {
            ??? //用戶提交FORM(即Postback)CODE HERE
            ? }

            ? //每次這里的都回執行CODE HERE
            }

            對應的事件Page.Load

            5. Handle control events;
            這個過程里,相應具體的控件事件,比如private void ListBox1_SelectedIndexChanged(object sender, System.EventArgs e)事件等等

            沒有對應的事件(我們自己的事件函數都包括在這個過程里比如上面的ListBox1_SelectedIndexChanged)

            6. Page_
            預先呈遞對象,這里是在向用戶程序呈現數據的倒數第二步,我估計提供這個過程的意義,也就是在這里能對控件屬性等等要呈現給用戶的數據進
            行修改,這也是最后的修改,以前的修改(比如在Page_Init里面)都可能被覆蓋.做完這了還會進行一個操作就是保存狀態,即SaveViewState.

            對應的事件時Page.PreRender

            7. Page_Render();
            大家可以在瀏纜器里View->Source查看到,每個頁面都有一個隱藏的<input>,這里面的"__VIEWSTATE"就是我們服務器寫回來的頁面狀態信息,
            在這個之前,服務器要呈現頁面(也就是構造HTML格式的文件),就是從這個"__VIEWSTATE"里面獲取的數據,當然大家也注意到了,這里有個Page.Render事件,我們可以添加自己的處理代碼,也就是說我們又可以更改數據,不過這里推薦不要在這里修改,既然提供了PreRender,就應該在里面做最后的修改,當然這不是必須的,只是推薦!

            對應的事件Page.Render

            8. Unload event;
            大家應該明白,當想服務器請求一個對象的時候,就會在內存里生成一個繼承頁面對象,也就是頁面的類,它繼承自System.Web.UI.Page.
            當頁面對象從內存中卸載時發生,將觸發該事件.

            對應的事件Page.Unload

            9. Dispose method called;
            銷毀所有的對象.當從內存釋放Page時發生,這是生存期的最后階段。可能第8和9似乎有些模糊,不過我也沒怎么搞清楚,待研究!

            對應的事件Dispose

            以上就是ASP.NET頁面周期的描述。

            注意上面灰色背景的文字,如果一個過程中有對應的事件,我們可以自己定義一個函數(當然先在MSDN中找到函數原型),然后在
            InitializeComponent中向事件的鏈表上添加上去,像下面:
            private void InitializeComponent()
            {???
            ? this.Unload += new System.EventHandler(this.MainWebForm_Unload);
            ? this.Load += new System.EventHandler(this.Page_Load);
            ? this.Init += new System.EventHandler(this.Page_Init);
            ? this.PreRender += new System.EventHandler(this.My_PreRender);
            }

            對于幾個沒有對應事件的過程,比如2.Load ViewState,我們可以重載Page的虛函數protected override void LoadViewState(object savedState);來添加自己的控制代碼,不過切忌掉用基類的對應方法,比如:
            protected override void LoadViewState(object savedState)
            {
            ? //自己處理VIEWSTATE
            ? base.LoadViewState (savedState);
            }

            初學ASP.NET,請各位不吝賜教!???
            ====================\

            Asp.net2.0頁面的生命周期

            表格 1. ASP.NET 頁面生存周期中的關鍵事件

            階段

            頁面事件

            可重寫方法

            頁面初始化

            Init

            加載視圖狀態

            LoadViewState

            處理回發數據

            實現 IPostBackDataHandler 接口的任何控件中的 LoadPostData 方法

            加載頁面

            Load

            回發更改通知

            實現 IPostBackDataHandler 接口的任何控件中的 RaisePostDataChangedEvent 方法

            處理回發事件

            控件所定義的任何回發事件

            實現了 IPostBackEventHandler 接口的任何控件的 RaisePostBackEvent 方法

            頁面呈現前階段

            PreRender

            保存視圖狀態

            SaveViewState

            呈現頁面

            Render

            卸載頁面

            Unload

            ?

            ?

            ?

            當一個獲取網頁的請求(可能是通過用戶提交完成的,也可能是通過超鏈接完成的)被發送到Web服務器后,這個頁面就會接著運行從創建到處理完成的一系列事件。在我們試圖建立Asp.net頁面的時候,這個執行周期是不必去考慮的,那樣只會自討苦吃。然而,如果被正確的操縱,一個頁面的執行周期將是一道有效而且功能強大的工具。許多開發者在編寫 Asp.net的頁面以及用戶控件的時候發現,如果知道整個過程中發生了什么以及在什么時候發生將對完成整個任務起到很重要的幫助作用。下面我就向大家介紹一下一個Asp.net頁面從創建到處理完成過程中的十個事件。同時,也向大家展示如何在這些事件中添加自己的代碼以達到預定的效果。

            一.預初始化對象(OnPreInit)

            ?

            protected ? override ? void ?OnPreInit(EventArgs?e)???????
            {
            ????
            // ?custom?code????????????

            ???? base .OnPreInit(e);
            }


            注意,我們只能在PreInit()事件中動態的設置themes

            使用母版頁時的特例
            我們先要了解一個非常重要的知識點——母版頁被處理的過程就相當于內容頁中的一個控件。

            所以如果一個頁有其相關聯的母版頁的話,那么在PreInit()事件里頁中的所有控件都不會被初始化。而只有在Init()事件開始之后,你才能直接訪問這些控件。為什么?

            這 個原因就是內容頁中的所有控件都包含在“ContentPlaceholder”里,而“ContentPlaceholder”其實就是母版頁的一個子 控件。現在母版頁被處理的過程就相當于內容頁中的一個控件,我們早先提到過,除了Init()和Unload()之外的所有事件都是從最外面到最里面被激 發的。雖然頁的PreInit()是第一個被觸發的事件,但是用戶控件和母版頁是沒有這個事件的,所以在頁的Page_PreInit()方法中,母版頁 和用戶控件都不會被初始化,而是在Init()事件之后

            接下來讓我們來看一下Page_Init()事件之后控件的層次結構

            在這個頁面級的事件中,所有在設計時創建的控件都將被用默認值做初始化。例如,如果你有一個Text屬性值為“Hello”的TextBox控件,則此時這個屬性被設置。我們也可以在這里動態的創建控件。

            這個事件僅僅發生在頁級別的類中,用戶控件和母版頁沒有這個事件

            下面的代碼示例了如何重寫這個方法以增加你的自定義代碼

            二.初始化對象(OnInit)

            一個頁面的控件(以及頁面本身)最初應被正確的初始化。通過在你的C#文件的構造函數 中聲名所有對象,頁面就知道要創建多少對象以及它們的類型。一旦你在你的構造函數中聲名了所有的對象,你就可以通過繼承類、方法、事件或是屬性訪問它們。 然而,如果你的一些對象是在Aspx文件中指定的一些控件,那么這些控件就沒有屬性可言了。同時,通過代碼訪問它們會產生一些意外的錯誤,因為這些控件實 例是沒有一個確定的創建順序的(如果它們是被一起創建的)。還有,你可以通過OnInit來重載初始化事件.

            在這個事件里,我們能讀出控件的屬性(在設計模式中設置的)。但是我們不能讀出用戶設置的值,因為得到用戶設置的值是在LoadPostData()事件被激發之后。不過在這個事件中我們可以得到POST數據,如下

            string ?selectedValue? = ?Request.Form[controlID].ToString();

            三.完成初始化(OnInitComplete)

            完成初始化頁面OnInit事件后觸發。
            ?

            四.導入Viewstate數據(LoadViewState)

            在初始化事件后,所有控件只可以通過它們的ID被引用訪問(因為還沒有相應的DOM可使用)。在 LoadViewState這個事件中,所有的控件將獲得它們的第一個屬性:Viewstate屬性。這個屬性最終將被返回給服務器以判斷這個頁面是已經 被用戶訪問完畢還是仍然在被用戶所訪問。Viewstate屬性以“名稱/值”對的字符串方式被保存,它包含了控件的文本以及值等信息。該屬性被存儲在一 個隱藏的<input>控件的值屬性里,在請求頁面時被傳遞。這種方式比起Asp3.0的維持、判斷頁面狀態的方式有了很大的進步啊。還有, 你可以重載LoadViewState事件函數來對相應的控件進行值設定。下圖是一個例子:

            ?

            五.用LoadPostData處理Postback數據(LoadPostData)

            在頁面創建的這個階段,服務器對頁面上的控件提交的表單數據(在Asp.net中稱postback數據)進行處理。當一個頁面提交一個表單時,框 架就在每個提交了數據的控件上執行一個IPostBackDataHandler接口操作。然后頁面執行LoadPostData事件,解析頁面,找到每 個執行了IpostBackDataHandler接口操作的控件,并用恰當的postback數據更新這些控件狀態。Asp.net是通過用 NameValue集中的“名稱/值”對和每個控件的唯一的ID匹配來實現這一操作的。所以,在Asp.net的頁面上每個控件必須有一個唯一的ID,不 可以出現幾個控件共有ID的情況。即使是用戶自定義的一些控件,框架也會賦予它們各自唯一的ID的。在LoadPostData事件后,就要執行下面的 RaisePostDataChanged事件了。

            ?

            六.OnPreLoad

            在加載頁面OnLoad事件前觸發。可以在頁面里面通過Page_OnPreLoad事件綁定

            七.導入對象(OnLoad)

            Page_Load是事件綁定得方法 ?
            ? page.load ? + ? = ? new ? eventhandler(Page_Load)???
            OnLoad()是引發Load事件主要是判斷事件是否為空,如果不為空就執行事件下綁定得方法

            在Load事件中,對象都實例化了。所有的對象第一次被布置在DOM頁面(在Asp.net中稱控件樹)里了并且可以通 過代碼或是相關的位置被引用。這樣,對象就可以很容易的從客戶端獲得諸如寬度、高度、值、可見性等在Html中的屬性值。在Load事件中,當然還有像設 置控件屬性等操作的發生。這個過程是整個生命周期中最重要、最主要的,你可以通過調用OnLoad來重載Load事件,圖示如下:

            ?

            八.RaisePostBackChanged事件(RaisePostDataChangedEvent)

            就像在上面提到的那樣,這個事件是發生在所有的控件執行了IPostBackDataHandler接口操作并被正確的 postback數據更新后的。在這個過程中,每個控件都被賦予一個布爾值來標志該控件有沒有被更新。然后,Asp.net就在整個頁面上尋找任何已被更 新過的控件并執行RaisePostDataChanged事件操作。不過,這個事件是要在所有的控件都被更新了以及Load事件完成后才進行的。這樣就 保證了一個控件在被postback數據更新前,別的控件在RaisePostDataChanged事件中是不會被手動改變的。

            九.處理客戶端PostBack事件(RaisePostBackEvent)

            當由postback數據在服務器端引起的事件都完成后,產生postback數據的對象就執行 RaisePostBackEvent事件操作。可是會有這種情況,由于一個控件狀態的改變使得它將表單返回給服務器或是用戶點擊了提交按鈕使得表單返回 給服務器。在這種情況下應該有相應的處理代碼來體現事件驅動這一面向對象(OOP)編程原則。由于要滿足呈現給瀏覽器的數據的精確性要求,在一系列 postback事件中RaisePostBackEvent事件是最后發生的。

            在postback過程中改變的控件不應在執行功能函數被調用后更新。也就是說,任何由于一個預期的事件而改變的數據應該在最終的頁面上被反映出來。你可以通過修改RaisePostBackEvent函數來滿足你的要求,圖示如下:

            ?

            十.Page_OnLoadComplete

            完成頁面加載OnLoad事件后觸發。

            十一.預先呈遞對象

            可以改變對象并將改變保存的最后時刻就是這一步――預先呈遞對象。這樣,你可以在這一步對控件的屬性、控件樹結構等作出最后的修改。同時還不用考慮 Asp.net對其作出任何改變,因為此時已經脫離了數據庫調用以及viewstate更新了。在這一步之后,對對象的所有修改將最終被確定,不能被保存 到頁面的viewstate中了。你可以通過OnPreRender來重載這一步。

            十二.完成預呈現(OnPreRenderComplete)

            在完成預呈現OnPreRender事件后觸發。這是完成頁面呈現的最后一道關卡,在此之后,頁面將無法再進行任何呈現上的改動。

            十三.保存ControlState(SaveControlState)
            ?
            保 存控件狀態ControlState。ControlState是ASP.NET2.0控件新增的一個屬性,類似ViewState作用,但它們區別在于 ControlState用于保存更加重要的控件狀態信息,以保證在禁用ViewState的情況下還可以對控件狀態進行讀寫操作。

            八.保存ViewState(SaveViewState)

            所有對頁面控件的修改完成后viewstate就被保存了。對像的狀態數據還是保留在隱藏的<input> 控件里面,呈現給Html的對象狀態數據也是從這里取得的。在SaveViewState事件中,其值能被保存到viewstate對象,然而這時在頁面 上控件的修改卻不能了。你可以用SaveViewState來重載這一步,圖示如下:

            ?

            九.呈遞給Html(Render)

            運用Html創建給瀏覽器輸出的頁面的時候Render事件就發生了。在Render事件過程中,頁面調用其中的對象將 它們呈遞給Html。然后,頁面就可以以Html的形式被用戶的瀏覽器訪問了。當Render事件被重載時,開發者可以編寫自定義的Html代碼使得原先 生成的Html都無效而按照新的Html來組織頁面。Render方法將一個HtmlTextWriter對象作為參數并用它將Html在瀏覽器上以網頁 的形式顯示。這時仍然可以做一些修改動作,不過它們只是客戶端的一些變化而已了。你可以重載Render事件,圖示如下:

            ?

            十.銷毀對象(Page_UnLoad)

            在呈遞給Html完成后,所有的對象都應被銷毀。在Dispose事件中,你應該銷毀所有在建立這個頁面時創建的對象。這時,所有的處理已經完畢,所以銷毀任何剩下的對象都是不會產生錯誤的,包括頁面對象。你可以重載Dispose事件。

            全文總結

            以上就是Asp.net頁面生命周期中的幾個主要事件。每次我們請求一個Asp.net頁面時,我們都經歷著同樣的過程:從初始化對象到銷毀對象。 通過了解Asp.net頁面的內部運行機制,我相信大家在編寫、調試代碼的時候會更加游刃有余的。不過整個頁面的生命周期的方法如下:

            方法 活動

            Constructor

            Always

            Construct

            Always

            TestDeviceFilter

            Always

            AddParsedSubObject

            Always

            DeterminePostBackMode

            Always

            OnPreInit

            Always

            LoadPersonalizationData

            Always

            InitializeThemes

            Always

            OnInit

            Always

            ApplyControlSkin

            Always

            ApplyPersonalization

            Always

            OnInitComplete

            Always

            LoadPageStateFromPersistenceMedium

            Always

            LoadControlState

            Always

            LoadViewState

            Always

            ProcessPostData1

            Always

            OnPreLoad

            Always

            OnLoad

            Always

            ProcessPostData2

            Always

            RaiseChangedEvents

            Always

            RaisePostBackEvent

            Always

            OnLoadComplete

            Always

            OnPreRender

            Always

            OnPreRenderComplete

            Always

            SavePersonalizationData

            Always

            SaveControlState

            Always

            SaveViewState

            Always

            SavePageStateToPersistenceMedium

            Always

            Render

            Always

            OnUnload

            Always

            查看頁面生命周期的底層細節,我們可以看到 ASP.NET 2.0 中提供的許多功能(例如主題和個性化)將在什么地方容易實現。例如,主題在 IntializeThemes 事件中處理,而個性化數據將在 LoadPersonalizationData 中加載并稍后用于 ApplyPersonalization 方法。請注意,就哪一個 UI 元素將決定 Web 應用程序的最終外觀和感覺而言,方法的順序非常重要。

            AspNet2.0頁面生命周期 ?

            頁面框架通過如下過程處理aspx文件請求:
            ??? 1:解析aspx文件,并創建一個控件樹;
            ??? 2:使用控件樹動態實現一個繼承自Page類的類或者控件 ;
            ??? 3:動態編譯類;
            ??? 4:緩存編譯類,以備后用;
            ??? 5:動態創建一個編譯類的實例。頁面開始啟動生命期,在這個過程中,頁面將通過生命周期的不同階段;=========================================================
            頁面經歷了如下階段【其中一些階段標記為僅僅回傳,是說只有在被回傳到服務器時,頁面才經歷這些階段】:

            01:頁面首先從QueryString或者Request對象的Form集合中獲得回傳數據。

            02:頁面檢測回傳數據集合(NameValueCollection,Form或者QueryString)是否包含一個鍵為_CallBackId的項。如? 果存在,那么設置其Boolean屬性IsCallBack為True,以便通過AspNet客戶端回調機制,標明頁面已經回傳到服務器。

            03:預初始化(PreInit):
            ? 在頁面生命周期的預初始化階段執行如下操作:
            ?? a:調用OnPreInit方法引發PreInit事件。
            ?? b:利用App_Themes目錄中的內容初始化主題,以動態實現一個PageTheme類型的類,
            ??? 編譯該類,并創建一個編譯類的實例,接著將實例賦值給它的PageTheme屬性值
            ?? c:應用母版頁

            04:初始化(Init):
            ? 在頁面生命周期的初始化階段執行以下操作
            ?? a:遞歸初始化Controls集合中的控件。初始化包括設置這些控件的屬性,
            ??? 例如:Page,Id和NameContainer等
            ?? b:遞歸應用控件皮膚
            ?? c:調用OnInit方法以引發自身的Init事件,接著遞歸調用子控件的OnInit方法來引發它們的Init事件
            ?? d:調用自身的TrackViewState方法來啟動自身的視圖狀態跟蹤,接著遞歸調用子控件
            ??? 的TrackViewState方法來啟動它們的視圖狀態跟蹤。

            05:完成初始化(InitComplete):
            ? 頁面調用OnInitComplete方法來引發InitComplete事件。該事件標明了初始化階段的結束。
            此時,頁面Controls集合的所有控件都被初始化了。


            06:加載控件狀態(Load Control State)[PostBack Only]:
            ? 頁面遞歸調用Control集合中控件的LoadControlState方法,這些控件已經調用了Page類
            的RegisterRequiresControlState方法,以使用它們的控件狀態。

            07:加載視圖狀態(Load View State)[PostBack Only]:
            ? 頁面首先調用自身的LoadViewState方法,接著遞歸調用Controls集合控件的LoadViewState方法,以允許它們加載它們的已經保存的視圖狀態。

            08:加載回傳數據(Load Post Data)[PostBack Only]:
            ? 頁面調用實現IPostBackDataHandler接口的控件的LoadPostData方法,并將回傳數據傳遞給該方法。每個控件的LoadPostDate方法都必須訪問回傳數據,并據此更新相應的控件屬性。
            例如:TextBox控件的LoadPostData方法將文本框的新值設置為TextBox控件的Text屬性值。

            09:預加載(PreLoad):
            ? 頁面調用OnPreLoad方法以引發PreLoad事件。該事件表示頁面生命周期將進入加載階段。

            10:加載(Load):
            ? 頁面首先調用自身的OnLoad方法以引發自身的Load事件,接著遞歸調用Controls集合中控件的OnLoad方法以引發它們的Load事件。頁面開發人員可以為Load事件注冊回調,那么就可以通過編程將子控件添加到頁面的Controls集合中。

            11:加載回傳數據(Load Post Data)[PostBack Only Second Try]:
            ? 頁面調用控件的LoadPostBack方法。這些控件如果實現了IPostBackDataHandler接口,那么在加載階段,它們已通過編程添加到Controls集合中。

            12:引發回傳數據修改事件(Raise Post Data Changed Event)[PostBack Only]:
            ? 頁面調用控件的RaisePostDataChangeEvent方法,這些控件的LoadPostData方法返回true。
            RaisePostDataChangeEvent方法引發了回傳數據修改事件。例如:當文本框的新值與舊值
            不同時,那么TextBox控件將引發該事件。

            13:引發回傳事件(Raise PostBack Event)[PostBack Only]:
            ? 頁面調用控件的RaisePostEvent方法,這些控件相關的Html元素用于提交表單。例如,Button控件的相關Html元素將頁面回傳到服務器。控件的RaisePostBackEvent方法必須將回傳事件映射到一個或多個服務器事件。例如,Button控件的 RaisePostBackEvent方法將事件映射到了服務器端事件Command和Click上。

            14:完成加載(Load Complete):
            ? 頁面調用OnLoadComplete方法來引發LoadComplete事件,這表示所有加載活動,包括加載回傳數據,以及引發回傳數據修改事件,并以更新控件自身的活動都完成了。

            15:引發回調事件(Raise CallBack Event)(PostBack And CallBack Only):
            ? 頁面調用控件的RaiseCallBackEvent方法。該控件可使用AspNet客戶端回調機制來允許客戶端方法(例如JavaScript函數)調用服務器端方法,而無需將整個頁面回傳給服務器。
            RaiseCallBackEvent方法必須調用服務器端方法。如果頁面的回傳使用了客戶端回調機制,那么頁面將不會執行剩余的頁面生命周期階段。

            16:預呈現(PreRender):
            ? 在頁面生命周期這個階段執行一下操作。
            ?? a:調用EnsureChildControls方法來確保在頁面進入呈現階段之前,創建其子控件。
            ?? b:調用自身的OnPreRender方法來引發PreRender事件。
            ?? c:遞歸調用Controls集合中控件的OnPreRender方法,以引發它們的PreRender事件。

            17:預呈現完成(PreRender Complete):
            ? 頁面調用OnPrerenderComplete方法來引發PreRenderComplete事件,這表示所有預呈現活動完成了。

            18:保存控件狀態(Save Control State):
            ? 頁面遞歸調用Controls集合中控件的SaveControlState方法。這些控件已經調用了Page類的RegisterRequiresControlState方法來保存它們的控件狀態。

            19:保存視圖狀態(Save View State):
            ? 頁面首先調用自身的SaveViewState方法,然后調用Controls集合中的SaveViewState方法,以允許它們來保存其視圖狀態。

            20:保存狀態完成(Save View Complete):
            ? 頁面調用OnSaveStateComplete方法以引發SaveStateComplete事件,這表示所有狀態保存活動都完成了。

            21:呈現:
            ? 在頁面生命周期的這個階段執行一下操作。
            ?? a:創建一個HtmlTextWriter類實例,該實例封裝了輸出響應流
            ?? b:調用RenderCOntrol方法,并將HtmlTextWriter實例傳遞給該方法。
            ? RenderControl方法遞歸調用子控件的RenderControl方法,以便允許每個控件能夠呈現其
            Html標記文本。子控件的Html標記文本組成了最終發送給客戶端瀏覽器的Html標記文本。



            ?

            新一篇:?單點登錄在ASP.NET上的簡單實現

            ?????在ASP.NET中,有很多種保存信息的對象.例如:APPlication,Session,Cookie,ViewState和Cache等,那么它們有什么區別呢?每一種對象應用的環境是什么?
            ? ? 為了更清楚的了解,我們總結出每一種對象應用的具體環境,如下表所示: ?
            方法信息量大小保存時間應用范圍保存位置
            Application任意大小整個應用程序的生命期服務器端
            Session小量,簡單的數據用戶活動時間+一段延遲時間(一般
            為20分鐘)

            單個用戶服務器端
            Cookie小量,簡單的數據可以根據需要設定單個用戶客戶端
            Viewstate小量,簡單的數據一個Web頁面的生命期單個用戶客戶端
            Cache任意大小可以根據需要設定所有用戶服務器端
            隱藏域小量,簡單的數據一個Web頁面的生命期單個用戶客戶端
            查詢字符串小量,簡單的數據直到下次頁面跳轉請求單個用戶客戶端
            Web.Config文件不變或極少改變的小量數據直到配置文件被更新單個用戶服務器端

            1.Application對象
            ? ? Application用于保存所有用戶的公共的數據信息,如果使用Application對象,一個需要考慮的問題是任何寫操作都要在Application_OnStart事件(global.asax)中完成.盡管使用Application.Lock和Applicaiton.Unlock方法來避免寫操作的同步,但是它串行化了對Application對象的請求,當網站訪問量大的時候會產生嚴重的性能瓶頸.因此最好不要用此對象保存大的數據集合. 下面我們做個在線用戶統計的例子來說明這個問題:
            ? ? (以文件的形式存放網站總訪問量)
            ? ? (1)Global.asax類 using System;
            using
            System.Collections;
            using
            System.ComponentModel;
            using
            System.Web;
            using
            System.Web.SessionState;
            using
            System.IO;

            namespace
            WebAppCounter
            {
            ? ?/**/
            /// <summary>
            ? ?/// Global 的摘要說明。
            ? ?/// </summary>

            ? ?public class Global : System.Web.HttpApplication
            ? ?
            {
            ? ?? ? /**/
            /// <summary>
            ? ?? ? /// 必需的設計器變量。
            ? ?? ? /// </summary>

            ? ?? ? private System.ComponentModel.IContainer components = null;

            ? ?? ? private
            FileStream fileStream;
            ? ?? ? private StreamReader reader;//讀字符流

            ? ?? ? private StreamWriter writer;//寫字符流
            ? ?? ?
            ? ?? ? public
            Global()
            ? ?? ?
            {
            ? ?? ?? ?? InitializeComponent();
            ? ?? ? }
            ? ?

            ? ?? ? protected void
            Application_Start(Object sender, EventArgs e)
            ? ?? ?
            {
            ? ?? ?? ?? Application["CurrentGuests"]=0;//初始花為0;

            ? ?? ?? ?? fileStream = File.Open(Server.MapPath("counts.text"),FileMode.OpenOrCreate);//文件不存在,創建文件
            ? ?? ?? ?? reader = new StreamReader(fileStream);//要讀取的完整路徑
            ? ?? ?? ?? Application["AllGuests"] = Convert.ToInt32(reader.ReadLine()); //從當前流中讀取一行字符并將數據作為字符串返回
            ? ?? ?? ?? reader.Close();//關閉流
            ? ?? ? }

            ? ?? ?
            protected void Session_Start(Object sender, EventArgs e)//當用戶訪問網站時,在線用戶+1,總訪問數+1
            ? ?? ? {
            ? ?? ?? ?? Application.Lock();//同步,避免同時寫入

            ? ?? ?? ??
            ? ?? ?? ?? Application["CurrentGuests"] =(int)Application["CurrentGuests"]+ 1;//總在線用戶數

            ? ?? ?? ?? Application["AllGuests"] =(int)Application["AllGuests"]+ 1;//訪問網站的總用戶數
            ? ?? ?? ?? fileStream = new FileStream(Server.MapPath("counts.text"),FileMode.OpenOrCreate,FileAccess.ReadWrite);//
            ? ?? ?? ?? writer = new StreamWriter(fileStream);//實現一個寫入流,使其以一種特定的編碼向流中寫入字符

            ? ?? ?? ?? writer.WriteLine(Application["AllGuests"].ToString());//把訪問網站的總用戶數再次寫入到文件
            ? ?? ?? ?? writer.Close();//關閉寫入流

            ? ?? ?? ?? Application.UnLock();//同步結束
            ? ?? ? }

            ? ?? ?
            protected void Application_BeginRequest(Object sender, EventArgs e)
            ? ?? ?
            {
            ? ?? ?? ?? ?
            ? ?? ? }


            ? ?? ?
            protected void Application_EndRequest(Object sender, EventArgs e)
            ? ?? ?
            {
            ? ?? ?? ??
            ? ?? ? }


            ? ?? ?
            protected void Application_AuthenticateRequest(Object sender, EventArgs e)
            ? ?? ?
            {

            ? ?? ? }


            ? ?? ?
            protected void Application_Error(Object sender, EventArgs e)
            ? ?? ?
            {

            ? ?? ? }


            ? ?? ?
            protected void Session_End(Object sender, EventArgs e)//當前用戶退出網站時,在線用戶數量-1,
            ? ?? ? {
            ? ?? ?? ?? Application.Lock();
            ? ?? ?? ?? Application["CurrentGuests"] =(int)Application["CurrentGuests"] - 1;//總在線用戶數量-1

            ? ?? ?? ?? Application.UnLock(); ? ?

            ? ?? ? }

            ? ?? ?
            protected void Application_End(Object sender, EventArgs e)
            ? ?? ?
            {

            ? ?? ? }

            ? ?? ?? ??
            ? ?? ?
            Web 窗體設計器生成的代碼#region Web 窗體設計器生成的代碼
            ? ?? ? /**//// <summary>
            ? ?? ? /// 設計器支持所需的方法 - 不要使用代碼編輯器修改
            ? ?? ? ///
            此方法的內容。
            ? ?? ? /// </summary>

            ? ?? ? private void InitializeComponent()
            ? ?? ?
            { ? ?
            ? ?? ?? ?? this.components = new
            System.ComponentModel.Container();
            ? ?? ? }

            ? ?? ? #endregion
            ? ?}
            }



            bifek,2007-07-19 15:24:23

            ?? ?(2) WebForm1.aspx private void Page_Load(object sender, System.EventArgs e)
            ? ? ?? ?{
            ? ? ?? ?? ? this.Label1.Text = "正在訪問站點的用戶數:" + Application["CurrentGuests"].ToString(); ? ?
            ? ? ?? ?? ? this.Label2.Text ="訪問過站點的總用戶數:" + Application["AllGuests"].ToString();
            ? ? ?? ?}
            2.Session對象
            ? ? Session用于保存每個用戶的專用信息.她的生存期是用戶持續請求時間再加上一段時間(一般是20分鐘左右).S
            ession中的信息保存在Web服務器內容中,保存的數據量可大可小.當Session超時或被關閉時將自動釋放保存的數據信息.由于用戶停止使用應用程序后它仍然在內存中保持一段時間,因此使用Session對象使保存用戶數據的方法效率很低.對于小量的數據,使用Session對象保存還是一個不錯的選擇.使用Session對象保存信息的代碼如下: //存放信息
            Session["username"]="zhouhuan";
            //讀取數據
            string UserName=Session["username"].ToString();????

            3.Cookie對象
            ? ? Cookie用于保存客戶瀏覽器請求服務器頁面的請求信息,程序員也可以用它存放非敏感性的用戶信息,信息保存的時間可以根據需要設置.如果沒有設置Cookie失效日期,它們僅保存到關閉瀏覽器程序為止.如果將Cookie對象的Expires屬性設置為Minvalue,則表示Cookie永遠不會過期.Cookie存儲的數據量很受限制,大多數瀏覽器支持最大容量為4096,因此不要用來保存數據集及其他大量數據.由于并非所有的瀏覽器都支持Cookie,并且數據信息是以明文文本的形式保存在客戶端的計算機中,因此最好不要保存敏感的,未加密的數據,否則會影響網站的安全性.使用Cookie對象保存的代碼如下: //存放信息
            Response.Cookies["UserID"].Value="0001";
            //讀取信息
            string UserID=Response.Cookies["UserID"].Value;????

            4.ViewState對象
            ? ? ViewState 常用于保存單個用戶的狀態信息,有效期等于頁面的生存期。ViewState容器可以保持大量的數據,但是必須謹慎使用,因為過多使用會影響應用程序的性能。所有Web服務器控件都使用ViewState在頁面回發期音保存自己的狀態信息。如果某個控件不需要在回發期間保存狀態信息,最好關閉該對象的ViewState,避免不必要的資源浪費。通過給@Page指令添加“EnableViewState=false”屬性可以禁止整個頁面的ViewState。使用ViewState對象保存信息的代碼如下。
            ? //存放信息
            ? ViewState["nameID"]="0001";
            ? //讀取信息
            ? string NameID=ViewState["nameID"].ToString();
            5.Cache對象
            ? ?Cache對象用于在HTTP請求間保存頁面或數據。該對象的使用可以極大地提高整個應用程序的效率。它允許將頻繁訪問的大量服務器資源存儲在內存中,當用戶發出相同的請求后服務器不再次處理而是將Cache中保存的信息返回給用戶,節省了服務器處理請求的時間。此對象的實例是每個應用程序專用的,其生存期依賴于該應用程序的生存期。當重新啟動應用程序時,將重新創建其Cache對象的實例。使用Cache對象保存信息的代碼如下。 ? //存放信息
            ? Cache["nameID"]="0001";
            ? //存放信息
            ? Cache.Insert("nameID","0001"1);
            ? //讀取信息
            ? string NameID=Cache["nameID"].ToString(); ? 6.隱藏域
            ? Hidden控件是屬于HTML類型的服務器控件,使用此控件可以實現隱藏域的功能。其實此控件和其它服務器控件的使用沒有太大區別,只是它不會在用戶端的瀏覽器中顯示,始終處于隱藏狀態。但是每次頁面提交的時候,此控件和其它服務器控件一同提交到服務器端,因此在服務器端可以使用Value屬性獲取或保存一些數據信息。使用Hidden控件保存信息的代碼如下。
            ? //存放信息
            ? Hidden.Value="0001";
            ? //獲取信息
            ? string NameID=Hidden.Value; ?7.查詢字符串
            ? 查詢字符串的方式是將要傳遞的值連接在URL后面,然后通過Response.Redirect方法實現客戶端的重定向。這種方式可以實現在兩個頁面之間傳遞信息。由于URL的長度有一定的限制,因此不能傳遞太大的信息,加外安全性也不是很好。
            ? 傳遞信息如下。
            ? Response.Redirect("List.aspx?nameID=0001&gradeID=002");
            ? //執行上面的語句后在IE地址欄顯示的URL的代碼如下。
            ? http://localhost/List.aspx?nameID=0001&grade=002
            ? //當跳轉到List.aspx后,可以通過以下代碼獲得所傳遞的信息。
            ? string NameID.GradeID;
            ? NameID=Request.Params["nameID"];
            ? GradeID=Request.Params["gradeID"];???

            6,QueryString多半是地址欄參數,到下一頁使用,明文,無所謂安全;??

            除了以上介紹的幾種對象外,還可以使用Context對象和Web.Config配置文件。它們也都可以實現保存用戶信息的功能,在這里不再詳細介紹。至于使用何種對象保存信息可以根據以下的原則進行選定:

            viewstate/session/cache/application
            單頁級的自身狀態的保存建議用viewstate,??
            用戶級的重要的信息的保存建議用session(如每個用戶的狀態)??
            用戶級的非重要性的信息的保存建議用cache??
            整個站級的狀態的保存建議用application.或用singleton模式的全局對象??
            cache和session的用法相同,不過cache中的信息在內存緊張時會消失,所以cache的使用時需如下形式??
            if(cache["key"]==null)??
            {????
            ?? //重新檢索數據;??
            ?? cache["key"]=檢索到的數據;??
            }
            所需數據=cache["key"]
            全局變量的讀寫建議"加鎖",不然會出現不正常的.


            我對.NET技術不熟悉,因此對ViewState,Cache這兩個功能不清楚,但可以對其他三個Cookie,Session,Application提供一些實踐方面的建議.??
            ? 1)cookie是大家最喜歡的一種存儲方式,但不是好的存儲方法,我的建議是在商業性網站開發中最好不用.典型的使用方法如下:??
            ? <%??
            ? Dim?? strUserID,?? strPassword,?? blnAutoLogin??
            ???
            ? strUserID?? =?? Request.Form("txtUserID")??
            ? strPassword?? =?? Request.Form("txtPassword")??
            ? blnAutoLogin?? =?? Request.Form("chkAutoLogin")??
            ???
            ? if?? blnAutoLogin?? =?? "on"?? then??
            ? 'Save?? Username?? and?? password?? to?? cookie??
            ? Response.Cookies("Credentials")("userid")?? =?? strUserID??
            ? Response.Cookies("Credentials")("password")?? =?? strPassword??
            ? Response.Cookies("Address")?? =?? "123?? Main?? Street"??
            ? End?? If??
            ? %>??
            ???
            ? 2)session是一種比較好的使用方式,但是不要使用過大.比如在一個商城的網站中,只有customerID用session保存,其他都從數據庫中獲得數據.典型代碼如下:??
            ? <%??
            ? Session.Contents("FavColour")?? =?? Request.Form("txtColour")??
            ? Response.write?? "Your?? colour?? has?? been?? saved"??
            ? %>??
            ? 3)Application是一個全程對象,通常的一個應用是做counter,看了國內的許多代碼,好象大家不喜歡用這個對象.典型代碼如下:??
            ? <%??
            ? Application.Lock??
            ? Application("anotherVariable")=Application("anotherVariable")+1??
            ? Application.Unlock??
            ? Response.write?? Application("anotherVariable")??
            ? %>??
            ???
            ? 我在開發時只用1個session作為用戶的ID.


            Application

            1.???????? Application用來保存所有用戶共用的信息

            2.???????? 在Asp時代,如果要保存的數據在應用程序生存期內不會或者很少發生改變,那么使用Application是理想的選擇。但是在Asp.net開發環境中我們把類似的配置數據放在Web.config中。

            3.???????? 如果要使用Application 要注意的是所有的寫操作都要在Application_OnStart事件中完成(global.Asax),盡管可以使用Application.Lock()避免了沖突,但是它串行化了對Application的請求,會產生嚴重的性能瓶頸。

            4.???????? 不要使用Application保存大數據量信息

            5.???????? 代碼:Application[“UserID”]=”test”;

            ??????? String UserName=Application[“UserID”].ToString();

            Session

            1.???????? Session用來保存每一個用戶的專有信息

            2.???????? Session的生存期是用戶持續請求時間加上一段時間(一般是20分鐘左右)

            3.???????? Session信息是保存在Web服務器內存中的,保存數據量可大可小

            4.???????? Session超時或者被關閉將自動釋放數據信息

            5.???????? 由于用戶停止使用應用程序之后它仍在內存中存留一段時間,因此這種方法效率較低

            6.???????? 代碼:Session[“UserID”]=”test”;

            ??????? String UserName=Session[“UserID”].ToString();

            Cookie

            1.???????? Cookie用來保存客戶瀏覽器請求服務器頁面的請求信息

            2.???????? 我們可以存放非敏感的用戶信息,保存時間可以根據需要設置

            3.???????? 如果沒有設置Cookie失效日期,它的生命周期保存到關閉瀏覽器為止

            4.???????? Cookie對象的Expires屬性設置為MinValue表示永不過期

            5.???????? Cookie存儲的數據量受限制,大多數的瀏覽器為4K因此不要存放大數據

            6.???????? 由于并非所有的瀏覽器都支持Cookie,數據將以明文的形式保存在客戶端

            7.???????? 代碼:Resopnse.Cookies[“UserID”]=”test”;

            ??????? String UserName= Resopnse.Cookies [“UserID”].ToString();

            ViewState

            1.???????? ViewState用來保存用戶的狀態信息,有效期等于頁面的生命周期

            2.???????? 可以保存大量數據但是要慎用,因為會影響程序性能

            3.???????? 所有的Web服務器控件都是用ViewState在頁面PostBack期間保存狀態

            4.???????? 不需要則關閉 @page 里面設置EnableViewState=false

            5.???????? 代碼:ViewState[‘”ID”]=”yiner”;
            ?? String ID =ViewState[“ID”].ToString();

            Cache

            1.???????? Cache用于在Http請求期間保存頁面或者數據

            2.???????? Cache的使用可以大大的提高整個應用程序的效率

            3.???????? 它允許將頻繁訪問的服務器資源存儲在內存中,當用戶發出相同的請求后
            服務器不是再次處理而是將Cache中保存的數據直接返回給用戶

            4.???????? 可以看出Cache節省的是時間—服務器處理時間

            5.???????? Cache實例是每一個應用程序專有的,其生命周期==該應用程序周期
            應用程序重啟將重新創建其實例

            6.???????? 注意:如果要使用緩存的清理、到期管理、依賴項等功能必須使用Insert 或者Add方法方法添加信息

            7.???????? 代碼:Cache[‘”ID”]=”yiner”;或者Cache.Insert(“ID”,”test”);
            ?? String ID =Cache[“ID”].ToString();

            Hidden

            1.???????? Hidden控件屬于Html類型的服務器控件,始終處于隱藏狀態

            2.???????? 每一次提交的時候它會和其他服務器控件一起提交到服務器端

            3.???????? 代碼如下:Hidden.Value=”king”;
            string id=Hidden.Value; 要使用Runat=server


            1,ViewState多半存儲本頁內的信息,適用少量數據,具有基本安全性; 使用視圖狀態的優點是: a, 不需要任何服務器資源。視圖狀態包含在頁代碼內的結構中。 b, 簡單的實現。 c, 頁和控件狀態的自動保持。 d, 增強的安全功能。視圖狀態中的值是散列的、壓縮的并且是為 Unicode 實現而編碼的,這意味著比隱藏域具有更高的安全性狀態。 使用視圖狀態的缺點是: a, 性能。由于視圖狀態存儲在頁本身,因此如果存儲較大的值,在用戶顯示頁和發送頁時,頁的速度就可能會減慢。 b, 安全性。視圖狀態存儲在頁上的隱藏域中。雖然視圖狀態以哈希格式存儲數據,但它可以被篡改。如果直接查看頁輸出源,可以看到隱藏域中的信息,這導致潛在的安全性問題。

            2,QueryString多半是地址欄參數,到下一頁使用,明文,無所謂安全;

            3,Cookies需要在客戶端存儲少量信息,不需要較高的安全性; 使用 Cookie 的優點是: a, 不需要任何服務器資源。Cookie 存儲在客戶端并在發送后由服務器讀取。 b, 簡單。Cookie 是具有簡單鍵值對的輕量的、基于文本的結構。 c,可配置到期時間。Cookie 可以在瀏覽器會話結束時到期,或者可以在客戶端計算機上無限期存在,這取決于客戶端的到期規則。 使用 Cookie 的缺點是: a, 大小受到限制。 b, 用戶配置為拒絕接受。有些用戶禁用了瀏覽器或客戶端設備接收 Cookie 的能力,因此限制了這一功能。 c, 安全性。Cookie 可能會受到篡改。用戶可能會操縱其計算機上的 Cookie,這可能意味著安全性會受到影響或者導致依賴于 Cookie 的應用程序失敗。 d, 持久性。客戶端計算機上 Cookie 的持久性受到客戶端 Cookie 到期進程以及用戶干預的制約。 e, Cookie 通常用于為已知用戶自定義內容的個性化情況。在大多數此類情況中,Cookie 是作為“標識”而不是“身份驗證”,所以在 Cookie 中只存儲用戶名、賬戶名或唯一用戶 ID(例如 GUID)并使用它來訪問站點的用戶個性化結構是足夠的了。

            4,Session存儲在會話狀態變量中的理想數據是特定于單獨的、短期的、敏感的數據,應該是安全的,但過多使用會降低服務其性能; 使用會話狀態的優點是: a, 易于實現。會話狀態功能易于使用。 b, 會話特定的事件。會話管理事件可以由應用程序引發和使用。 c, 持久性。放置于會話狀態變量中的數據可以經受得住 Internet 信息服務 (IIS) 重新啟動和輔助進程重新啟動,而不丟失會話數據,這是因為這些數據存儲在另一個進程空間中。 d, 平臺可縮放性。會話狀態對象可在多計算機和多進程配置中使用,因而優化了可縮放性方案。 e, 盡管會話狀態最常見的用途是與 Cookie 一起向 Web 應用程序提供用戶標識功能,但會話狀態可用于不支持 HTTP Cookie 的瀏覽器。 使用會話狀態的缺點是: a, 性能。會話狀態變量在被移除或替換前保留在內存中,因而可能降低服務器性能。如果會話狀態變量包含類似大型數據集的信息塊,則可能會因服務器負荷的增加影響 Web 服務器的性能。

            5,Application插入到應用程序狀態變量的理想數據是那些由多個會話共享并且不經常更改的數據使用應用程序狀態的優點是: a, 易于實現。應用程序狀態易于使用。 b, 全局范圍。由于應用程序狀態可供應用程序中的所有頁來訪問,因此在應用程序狀態中存儲信息可能意味著僅保留信息的一個副本(例如,相對于在會話狀態或在單獨頁中保存信息的多個副本)。 使用應用程序狀態的缺點是: a, 全局范圍。應用程序狀態的全局性可能也是一項缺點。在應用程序狀態中存儲的變量僅對于該應用程序正在其中運行的特定進程而言是全局的,并且每一應用程序進程可能具有不同的值。因此,不能依賴應用程序狀態來存儲唯一值或更新網絡園和網絡場配置中的全局計數器。 b, 持久性。因為在應用程序狀態中存儲的全局數據是易失的,所以如果包含這些數據的 Web 服務器進程被損壞(最有可能是因服務器崩潰、升級或關閉而損壞),將丟失這些數據。 c, 資源要求。應用程序狀態需要服務器內存,這可能會影響服務器的性能以及應用程序的可縮放性。應用程序狀態的精心設計和實現可以提高 Web 應用程序性能。例如,如果將常用的、相關的靜態數據集放置到應用程序狀態中,則可以通過減少對數據庫的數據請求總數來提高站點性能。但是,這里存在一種性能平衡。當服務器負載增加時,包含大塊信息的應用程序狀態變量就會降低 Web 服務器的性能。在移除或替換值之前,將不釋放在應用程序狀態中存儲的變量所占用的內存。因此,最好只將應用程序狀態變量用于更改不頻繁的小型數據集。

            6,Cache,.NET 為您提供了一個強大的、便于使用的緩存機制,允許您將需要大量的服務器資源來創建的對象存儲在內存中。其生存期依賴于該應用程序的生存期。重新啟動應用程序后,將重新創建 Cache 對象。他的作用比較豐富,機制也比較多,請參閱相關的資料。
            Web Service安全機制探討
            http://hi.baidu.com/%D3%F1%D3%E3/blog/item/99f3ec4ac8fe832608f7ef57.html
            net面試題大全(有答案) & asp.net面試集合
            C#基礎概念二十五問(轉)
            http://www.cnblogs.com/jiayong/archive/2008/01/07/1029138.html

            .net工程師必懂題(筆試題目)轉
            http://www.cnblogs.com/jiayong/archive/2008/01/08/1030175.html

            ?

            posted on 2008-07-01 16:10 snowball 閱讀(10298) 評論(6)  編輯 收藏 引用 所屬分類: 文章轉載學習

            評論

            # re: 面向對象的三個基本特征(講解) 2010-07-30 08:52 KERI25BURTON

            When you are in a not good position and have got no cash to go out from that point, you will need to receive the <a href="http://bestfinance-blog.com/topics/personal-loans">personal loans</a>. Just because it will help you emphatically. I get car loan every time I need and feel OK just because of it.   回復  更多評論   

            # re: 面向對象的三個基本特征(講解) 2010-08-05 19:44 custom papers

            Study process requires good writing skills, nevertheless, students, which are short of time can destroy their academic success. Hence, to buy the academic essay from the narrative essay writing service will be a perfect decision.   回復  更多評論   

            # re: 面向對象的三個基本特征(講解) 2010-08-12 03:36 custom essay writing

            One, who knows someth. just about essay writing should appreciate your fantastic article. I think that the buy essay paper service could use it for the research paper blogs.   回復  更多評論   

            # re: 面向對象的三個基本特征(講解) 2010-08-23 12:10 essay papers

            Some students need a long time to realize the key issue of the customized essay. But when students do not have time, that will be the best to buy papers online. Then this will be available to save time.   回復  更多評論   

            # re: 面向對象的三個基本特征(講解) 2013-12-10 18:55 essays.mightystudents.com

            只記得你想完成的總體目標是讓讀者認同你,然後,希望把你的建議適當的行動。  回復  更多評論   

            # re: 面向對象的三個基本特征(講解) 2014-07-29 02:34 Friv 1000

            very nice article and it is quite interesting also for me personally. thank you so much for sharing this very interesting information. I will try to come back here again if in case there have been new and interesting article.  回復  更多評論   

            導航

            留言簿(1)

            隨筆分類

            友情鏈接

            搜索

            最新隨筆

            最新評論

            閱讀排行榜

            AV无码久久久久不卡网站下载| 99国产欧美精品久久久蜜芽| 国产欧美一区二区久久| 久久人人爽人人爽人人片AV不| 久久久久这里只有精品| 99久久国产综合精品成人影院 | 99久久99久久精品国产| WWW婷婷AV久久久影片| 蜜臀久久99精品久久久久久小说| 国产成人精品综合久久久| 久久久久久久免费视频| 久久久国产视频| 香蕉久久夜色精品国产2020| 国产精品久久久久久久人人看| 亚洲va久久久久| 久久人妻少妇嫩草AV蜜桃| 久久久久久久久波多野高潮| 一级做a爰片久久毛片看看| yy6080久久| 精品国产乱码久久久久久呢 | 日本免费久久久久久久网站 | 久久久久九九精品影院| 久久国产高清一区二区三区| 久久天天躁狠狠躁夜夜2020老熟妇 | 久久综合一区二区无码| 一97日本道伊人久久综合影院| 久久婷婷五月综合成人D啪| 亚洲综合精品香蕉久久网| 久久久久久久97| 99久久久久| 国内精品久久久久影院亚洲| 伊人久久综合精品无码AV专区 | 午夜不卡888久久| 青青草国产97免久久费观看| 2020国产成人久久精品| 色偷偷88888欧美精品久久久| 国产亚洲欧美成人久久片| 香蕉久久夜色精品国产2020| 久久久久久久97| 最新久久免费视频| 久久99精品国产99久久|