• <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
            重要的是這個(gè)磨練過(guò)程,而不是結(jié)果,要的是你粗壯的腿,而不是你身上背的那袋鹽巴

             

            面向?qū)ο蟮娜齻€(gè)基本特征(講解)

            面向?qū)ο蟮娜齻€(gè)基本特征(講解)

            面向?qū)ο蟮娜齻€(gè)基本特征是:封裝、繼承、多態(tài)。

            o_OOBase.gif

            封裝

            封裝最好理解了。封裝是面向?qū)ο蟮奶卣髦唬菍?duì)象和類概念的主要特性。

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

            繼承

            面向?qū)ο缶幊?/span> (OOP) 語(yǔ)言的一個(gè)主要功能就是 繼承 。繼承是指這樣一種能力:它可以使用現(xiàn)有類的所有功能,并在無(wú)需重新編寫原來(lái)的類的情況下對(duì)這些功能進(jìn)行擴(kuò)展。

            通過(guò)繼承創(chuàng)建的新類稱為“子類”或“派生類”。

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

            繼承的過(guò)程,就是從一般到特殊的過(guò)程。

            要實(shí)現(xiàn)繼承,可以通過(guò) 繼承 Inheritance )和 組合 Composition )來(lái)實(shí)現(xiàn)。

            在某些 OOP 語(yǔ)言中,一個(gè)子類可以繼承多個(gè)基類。但是一般情況下,一個(gè)子類只能有一個(gè)基類,要實(shí)現(xiàn)多重繼承,可以通過(guò)多級(jí)繼承來(lái)實(shí)現(xiàn)。

            ?

            繼承概念的實(shí)現(xiàn)方式有三類:實(shí)現(xiàn)繼承、接口繼承和可視繼承。

            ????????? 實(shí)現(xiàn)繼承是指使用基類的屬性和方法而無(wú)需額外編碼的能力;

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

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

            在考慮使用繼承時(shí),有一點(diǎn)需要注意,那就是兩個(gè)類之間的關(guān)系應(yīng)該是 屬于 關(guān)系。例如, Employee 是一個(gè)人, Manager 也是一個(gè)人,因此這兩個(gè)類都可以繼承 Person 類。但是 Leg 類卻不能繼承 Person 類,因?yàn)橥炔⒉皇且粋€(gè)人。

            抽象類僅定義將由子類創(chuàng)建的一般屬性和方法,創(chuàng)建抽象類時(shí),請(qǐng)使用關(guān)鍵字 Interface 而不是 Class 。

            OO 開(kāi)發(fā)范式大致為:劃分對(duì)象 抽象類 將類組織成為層次化結(jié)構(gòu) ( 繼承和合成 ) → 用類與實(shí)例進(jìn)行設(shè)計(jì)和實(shí)現(xiàn)幾個(gè)階段。

            ?

            多態(tài)

            多態(tài)性( polymorphisn )是允許你將父對(duì)象設(shè)置成為和一個(gè)或更多的他的子對(duì)象相等的技術(shù),賦值之后,父對(duì)象就可以根據(jù)當(dāng)前賦值給它的子對(duì)象的特性以不同的方式運(yùn)作。簡(jiǎn)單的說(shuō),就是一句話:允許將子類類型的指針賦值給父類類型的指針。

            實(shí)現(xiàn)多態(tài),有二種方式,覆蓋,重載。

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

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

            其實(shí),重載的概念并不屬于 面向?qū)ο缶幊?/span> ,重載的實(shí)現(xiàn)是:編譯器根據(jù)函數(shù)不同的參數(shù)表,對(duì)同名函數(shù)的名稱做修飾,然后這些同名函數(shù)就成了不同的函數(shù)(至少對(duì)于編譯器來(lái)說(shuō)是這樣的)。如,有兩個(gè)同名函數(shù): function func(p:integer):integer; function func(p:string):integer; 。那么編譯器做過(guò)修飾后的函數(shù)名稱可能是這樣的: int_func 、 str_func 。對(duì)于這兩個(gè)函數(shù)的調(diào)用,在編譯器間就已經(jīng)確定了,是靜態(tài)的(記住:是靜態(tài))。也就是說(shuō),它們的地址在編譯期就綁定了(早綁定),因此,重載和多態(tài)無(wú)關(guān)!真正和多態(tài)相關(guān)的是 覆蓋 。當(dāng)子類重新定義了父類的虛函數(shù)后,父類指針根據(jù)賦給它的不同的子類指針,動(dòng)態(tài)(記?。菏莿?dòng)態(tài)?。┑恼{(diào)用屬于子類的該函數(shù),這樣的函數(shù)調(diào)用在編譯期間是無(wú)法確定的(調(diào)用的子類的虛函數(shù)的地址無(wú)法給出)。因此,這樣的函數(shù)地址是在運(yùn)行期綁定的(晚邦定)。結(jié)論就是:重載只是一種語(yǔ)言特性,與多態(tài)無(wú)關(guān),與面向?qū)ο笠矡o(wú)關(guān)!引用一句 Bruce Eckel 的話: 不要犯傻,如果它不是晚邦定,它就不是多態(tài)。

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

            ?

            概念講解

            泛化( Generalization

            o_Generalization.gif

            圖表 1 泛化

            在上圖中,空心的三角表示繼承關(guān)系(類繼承),在 UML 的術(shù)語(yǔ)中,這種關(guān)系被稱為泛化( Generalization )。 Person( ) 是基類, Teacher( 教師 ) 、 Student( 學(xué)生 ) Guest( 來(lái)賓 ) 是子類。

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

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

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

            如果類 A 和類 B 毫不相關(guān),不可以為了使 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 應(yīng)該由類 Eye 、 Nose 、 Mouth 、 Ear 組合而成,不是派生(繼承)而成。

            ?

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

            ?

            聚合( aggregation

            ?

            o_aggregation.gif

            圖表 3 共享

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

            ?

            組合( composition

            o_composition.gif

            圖表 4 復(fù)合

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

            ?

            依賴 (Dependency)

            o_Dependency.gif

            圖表 5 依賴

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

            ==================接口與抽象類有什么區(qū)別==================
            abstract class和interface是Java語(yǔ)言中對(duì)于抽象類定義進(jìn)行支持的兩種機(jī)制,正是由于這兩種機(jī)制的存在,才賦予了Java強(qiáng)大的面向?qū)ο竽芰?。abstract class和interface之間在對(duì)于抽象類定義的支持方面具有很大的相似性,甚至可以相互替換,因此很多開(kāi)發(fā)者在進(jìn)行抽象類定義時(shí)對(duì)于abstract class和interface的選擇顯得比較隨意。其實(shí),兩者之間還是有很大的區(qū)別的,對(duì)于它們的選擇甚至反映出對(duì)于問(wèn)題領(lǐng)域本質(zhì)的理解、對(duì)于設(shè)計(jì)意圖的理解是否正確、合理。本文將對(duì)它們之間的區(qū)別進(jìn)行一番剖析,試圖給開(kāi)發(fā)者提供一個(gè)在二者之間進(jìn)行選擇的依據(jù)。

            理解抽象類

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

            ?

            ?

            在面向?qū)ο蟮母拍钪?,我們知道所有的?duì)象都是通過(guò)類來(lái)描繪的,但是反過(guò)來(lái)卻不是這樣。并不是所有的類都是用來(lái)描繪對(duì)象的,如果一個(gè)類中沒(méi)有包含足夠的信息來(lái)描繪一個(gè)具體的對(duì)象,這樣的類就是抽象類。抽象類往往用來(lái)表征我們?cè)趯?duì)問(wèn)題領(lǐng)域進(jìn)行分析、設(shè)計(jì)中得出的抽象概念,是對(duì)一系列看上去不同,但是本質(zhì)上相同的具體概念的抽象。比如:如果我們進(jìn)行一個(gè)圖形編輯軟件的開(kāi)發(fā),就會(huì)發(fā)現(xiàn)問(wèn)題領(lǐng)域存在著圓、三角形這樣一些具體概念,它們是不同的,但是它們又都屬于形狀這樣一個(gè)概念,形狀這個(gè)概念在問(wèn)題領(lǐng)域是不存在的,它就是一個(gè)抽象概念。正是因?yàn)槌橄蟮母拍钤趩?wèn)題領(lǐng)域沒(méi)有對(duì)應(yīng)的具體概念,所以用以表征抽象概念的抽象類是不能夠?qū)嵗摹?

            在面向?qū)ο箢I(lǐng)域,抽象類主要用來(lái)進(jìn)行類型隱藏。我們可以構(gòu)造出一個(gè)固定的一組行為的抽象描述,但是這組行為卻能夠有任意個(gè)可能的具體實(shí)現(xiàn)方式。這個(gè)抽象描述就是抽象類,而這一組任意個(gè)可能的具體實(shí)現(xiàn)則表現(xiàn)為所有可能的派生類。模塊可以操作一個(gè)抽象體。由于模塊依賴于一個(gè)固定的抽象體,因此它可以是不允許修改的;同時(shí),通過(guò)從這個(gè)抽象體派生,也可擴(kuò)展此模塊的行為功能。熟悉OCP的讀者一定知道,為了能夠?qū)崿F(xiàn)面向?qū)ο笤O(shè)計(jì)的一個(gè)最核心的原則OCP(Open-Closed Principle),抽象類是其中的關(guān)鍵所在。


            從語(yǔ)法定義層面看abstract class和interface

            在語(yǔ)法層面,Java語(yǔ)言對(duì)于abstract class和interface給出了不同的定義方式,下面以定義一個(gè)名為Demo的抽象類為例來(lái)說(shuō)明這種不同。

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

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

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

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

            }

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

            從編程的角度來(lái)看,abstract class和interface都可以用來(lái)實(shí)現(xiàn)"design by contract"的思想。但是在具體的使用上面還是有一些區(qū)別的。

            首先,abstract class在Java語(yǔ)言中表示的是一種繼承關(guān)系,一個(gè)類只能使用一次繼承關(guān)系。但是,一個(gè)類卻可以實(shí)現(xiàn)多個(gè)interface。也許,這是Java語(yǔ)言的設(shè)計(jì)者在考慮Java對(duì)于多重繼承的支持方面的一種折中考慮吧。

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

            在抽象類中不能定義默認(rèn)行為還存在另一個(gè)比較嚴(yán)重的問(wèn)題,那就是可能會(huì)造成維護(hù)上的麻煩。因?yàn)槿绻髞?lái)想修改類的界面(一般通過(guò)abstract class或者interface來(lái)表示)以適應(yīng)新的情況(比如,添加新的方法或者給已用的方法中添加新的參數(shù))時(shí),就會(huì)非常的麻煩,可能要花費(fèi)很多的時(shí)間(對(duì)于派生類很多的情況,尤為如此)。但是如果界面是通過(guò)abstract class來(lái)實(shí)現(xiàn)的,那么可能就只需要修改定義在abstract class中的默認(rèn)行為就可以了。

            同樣,如果不能在抽象類中定義默認(rèn)行為,就會(huì)導(dǎo)致同樣的方法實(shí)現(xiàn)出現(xiàn)在該抽象類的每一個(gè)派生類中,違反了"one rule,one place"原則,造成代碼重復(fù),同樣不利于以后的維護(hù)。因此,在abstract class和interface間進(jìn)行選擇時(shí)要非常的小心。


            從設(shè)計(jì)理念層面看abstract class和interface

            上面主要從語(yǔ)法定義和編程的角度論述了abstract class和interface的區(qū)別,這些層面的區(qū)別是比較低層次的、非本質(zhì)的。本小節(jié)將從另一個(gè)層面:abstract class和interface所反映出的設(shè)計(jì)理念,來(lái)分析一下二者的區(qū)別。作者認(rèn)為,從這個(gè)層面進(jìn)行分析才能理解二者概念的本質(zhì)所在。

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

            考慮這樣一個(gè)例子,假設(shè)在我們的問(wèn)題領(lǐng)域中有一個(gè)關(guān)于Door的抽象概念,該Door具有執(zhí)行兩個(gè)動(dòng)作open和close,此時(shí)我們可以通過(guò)abstract class或者interface來(lái)定義一個(gè)表示該抽象概念的類型,定義方式分別如下所示:

            使用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??雌饋?lái)好像使用abstract class和interface沒(méi)有大的區(qū)別。

            如果現(xiàn)在要求Door還要具有報(bào)警的功能。我們?cè)撊绾卧O(shè)計(jì)針對(duì)該例子的類結(jié)構(gòu)呢(在本例中,主要是為了展示abstract class和interface反映在設(shè)計(jì)理念上的區(qū)別,其他方面無(wú)關(guān)的問(wèn)題都做了簡(jiǎn)化或者忽略)?下面將羅列出可能的解決方案,并從設(shè)計(jì)理念層面對(duì)這些不同的方案進(jìn)行分析。

            解決方案一:

            簡(jiǎn)單的在Door的定義中增加一個(gè)alarm方法,如下:

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


            或者

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


            那么具有報(bào)警功能的AlarmDoor的定義方式如下:

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


            或者

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

            這種方法違反了面向?qū)ο笤O(shè)計(jì)中的一個(gè)核心原則ISP(Interface Segregation Priciple),在Door的定義中把Door概念本身固有的行為方法和另外一個(gè)概念"報(bào)警器"的行為方法混在了一起。這樣引起的一個(gè)問(wèn)題是那些僅僅依賴于Door這個(gè)概念的模塊會(huì)因?yàn)?報(bào)警器"這個(gè)概念的改變(比如:修改alarm方法的參數(shù))而改變,反之依然。

            解決方案二:

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

            顯然,由于Java語(yǔ)言不支持多重繼承,所以兩個(gè)概念都使用abstract class方式定義是不可行的。后面兩種方式都是可行的,但是對(duì)于它們的選擇卻反映出對(duì)于問(wèn)題領(lǐng)域中的概念本質(zhì)的理解、對(duì)于設(shè)計(jì)意圖的反映是否正確、合理。我們一一來(lái)分析、說(shuō)明。

            如果兩個(gè)概念都使用interface方式來(lái)定義,那么就反映出兩個(gè)問(wèn)題:1、我們可能沒(méi)有理解清楚問(wèn)題領(lǐng)域,AlarmDoor在概念本質(zhì)上到底是Door還是報(bào)警器?2、如果我們對(duì)于問(wèn)題領(lǐng)域的理解沒(méi)有問(wèn)題,比如:我們通過(guò)對(duì)于問(wèn)題領(lǐng)域的分析發(fā)現(xiàn)AlarmDoor在概念本質(zhì)上和Door是一致的,那么我們?cè)趯?shí)現(xiàn)時(shí)就沒(méi)有能夠正確的揭示我們的設(shè)計(jì)意圖,因?yàn)樵谶@兩個(gè)概念的定義上(均使用interface方式定義)反映不出上述含義。

            如果我們對(duì)于問(wèn)題領(lǐng)域的理解是:AlarmDoor在概念本質(zhì)上是Door,同時(shí)它有具有報(bào)警的功能。我們?cè)撊绾蝸?lái)設(shè)計(jì)、實(shí)現(xiàn)來(lái)明確的反映出我們的意思呢?前面已經(jīng)說(shuō)過(guò),abstract class在Java語(yǔ)言中表示一種繼承關(guān)系,而繼承關(guān)系在本質(zhì)上是"is a"關(guān)系。所以對(duì)于Door這個(gè)概念,我們應(yīng)該使用abstarct class方式來(lái)定義。另外,AlarmDoor又具有報(bào)警功能,說(shuō)明它又能夠完成報(bào)警概念中定義的行為,所以報(bào)警概念可以通過(guò)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() { … }
            }


            這種實(shí)現(xiàn)方式基本上能夠明確的反映出我們對(duì)于問(wèn)題領(lǐng)域的理解,正確的揭示我們的設(shè)計(jì)意圖。其實(shí)abstract class表示的是"is a"關(guān)系,interface表示的是"like a"關(guān)系,大家在選擇時(shí)可以作為一個(gè)依據(jù),當(dāng)然這是建立在對(duì)問(wèn)題領(lǐng)域的理解上的,比如:如果我們認(rèn)為AlarmDoor在概念本質(zhì)上是報(bào)警器,同時(shí)又具有Door的功能,那么上述的定義方式就要反過(guò)來(lái)了。


            ==================游標(biāo),可不可以嵌套,可以用什么辦法替換使用游標(biāo)==================
            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是一種目前廣泛流行的軟件設(shè)計(jì)模式,早在70年代,IBM就推出了Sanfronscisico項(xiàng)目計(jì)劃,其實(shí)就是MVC設(shè)計(jì)模式的研究。近來(lái),隨著J2EE的成熟,它正在成為在J2EE平臺(tái)上推薦的一種設(shè)計(jì)模型,也是廣大Java開(kāi)發(fā)者非常感興趣的設(shè)計(jì)模型。MVC模式也逐漸在PHP和ColdFusion開(kāi)發(fā)者中運(yùn)用,并有增長(zhǎng)趨勢(shì)。隨著網(wǎng)絡(luò)應(yīng)用的快速增加,MVC模式對(duì)于Web應(yīng)用的開(kāi)發(fā)無(wú)疑是一種非常先進(jìn)的設(shè)計(jì)思想,無(wú)論你選擇哪種語(yǔ)言,無(wú)論應(yīng)用多復(fù)雜,它都能為你理解分析應(yīng)用模型時(shí)提供最基本的分析方法,為你構(gòu)造產(chǎn)品提供清晰的設(shè)計(jì)框架,為你的軟件工程提供規(guī)范的依據(jù)?! ?

            MVC設(shè)計(jì)思想

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

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

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

            業(yè)務(wù)模型還有一個(gè)很重要的模型那就是數(shù)據(jù)模型。數(shù)據(jù)模型主要指實(shí)體對(duì)象的數(shù)據(jù)保存(持續(xù)化)。比如將一張訂單保存到數(shù)據(jù)庫(kù),從數(shù)據(jù)庫(kù)獲取訂單。我們可以將這個(gè)模型單獨(dú)列出,所有有關(guān)數(shù)據(jù)庫(kù)的操作只限制在該模型中。

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

            MVC的優(yōu)點(diǎn)

            大部分用過(guò)程語(yǔ)言比如ASP、PHP開(kāi)發(fā)出來(lái)的Web應(yīng)用,初始的開(kāi)發(fā)模板就是混合層的數(shù)據(jù)編程。例如,直接向數(shù)據(jù)庫(kù)發(fā)送請(qǐng)求并用HTML顯示,開(kāi)發(fā)速度往往比較快,但由于數(shù)據(jù)頁(yè)面的分離不是很直接,因而很難體現(xiàn)出業(yè)務(wù)模型的樣子或者模型的重用性。產(chǎn)品設(shè)計(jì)彈性力度很小,很難滿足用戶的變化性需求。MVC要求對(duì)應(yīng)用分層,雖然要花費(fèi)額外的工作,但產(chǎn)品的結(jié)構(gòu)清晰,產(chǎn)品的應(yīng)用通過(guò)模型可以得到更好地體現(xiàn)。

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



            MVC設(shè)計(jì)模型



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

            再次,由于一個(gè)應(yīng)用被分離為三層,因此有時(shí)改變其中的一層就能滿足應(yīng)用的改變。一個(gè)應(yīng)用的業(yè)務(wù)流程或者業(yè)務(wù)規(guī)則的改變只需改動(dòng)MVC的模型層。

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

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

            MVC的缺點(diǎn)

            MVC的設(shè)計(jì)實(shí)現(xiàn)并不十分容易, 理解起來(lái)比較容易,但對(duì)開(kāi)發(fā)人員的要求比較高。MVC只是一種基本的設(shè)計(jì)思想,還需要詳細(xì)的設(shè)計(jì)規(guī)劃。

            模型和視圖的嚴(yán)格分離可能使得調(diào)試?yán)щy一些,但比較容易發(fā)現(xiàn)錯(cuò)誤。

            經(jīng)驗(yàn)表明,MVC由于將應(yīng)用分為三層,意味著代碼文件增多,因此,對(duì)于文件的管理需要費(fèi)點(diǎn)心思。

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


            ?·網(wǎng)絡(luò)上md5的java實(shí)現(xiàn).??? ?顯示摘要???? 摘要:無(wú)意間發(fā)現(xiàn)的.不過(guò)章章師兄研究的密碼學(xué)里md5好象已經(jīng)用c++實(shí)現(xiàn)了.package com.sinosoftgroup.msd.util; /** * * <p>title: </p> * <p>description: </p> * <p>copyright: copyright (c) 2003</p> * <p...... ·jie server開(kāi)發(fā)指南??? ?顯示摘要???? 摘要: 一個(gè)簡(jiǎn)單的action,返回hello world  package org.jie.demo; import org.jie.server.action.standardaction;import javax.servlet.http.httpservletrequest; class testaction extends standardaction { publi......

            MVC設(shè)計(jì)模式帶來(lái)更好的軟件結(jié)構(gòu)和代碼重用
            mvc如何工作

            mvc是一個(gè)設(shè)計(jì)模式,它強(qiáng)制性的使應(yīng)用程序的輸入.處理與輸出分開(kāi).使用mvc應(yīng)用程序被分成三個(gè)核心部件:模型.視圖.控制器.它們各自處理自己的任務(wù).

            如何處理應(yīng)用程序的界面變得越來(lái)越有挑戰(zhàn)性.mvc一個(gè)大的好處是它能為你的應(yīng)用程序處理很多不同的視圖.在視圖中其實(shí)沒(méi)有真正的處理發(fā)生,不管這些數(shù)據(jù)是聯(lián)機(jī)存儲(chǔ)的還是一個(gè)雇員列表,作為視圖來(lái)講,它只是作為一種輸出數(shù)據(jù)并允許用戶操縱的方式. 【程序編程相關(guān):Hibernate middlegen中】

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

            控制器
            控制器接受用戶的輸入并調(diào)用模型與視圖去完成用戶的需求.所以當(dāng)單擊web頁(yè)面中的超鏈接與發(fā)送html表單時(shí),控制器本身不輸出任何東西與做任何處理.它只是接收請(qǐng)求并決定調(diào)用哪個(gè)模型構(gòu)件去處理請(qǐng)求,然后用確定用哪個(gè)視圖來(lái)顯示模型處理返回的數(shù)據(jù). 【擴(kuò)展信息:CruiseControl簡(jiǎn)介】

            模型
            模型表示企業(yè)數(shù)據(jù)與業(yè)務(wù)規(guī)則.在mvc的三個(gè)部件中,模型擁有最多的處理任務(wù).例如它可能用象ejbs與coldfusion components這樣的構(gòu)件對(duì)象來(lái)處理數(shù)據(jù)庫(kù).被模型返回的數(shù)據(jù)是中立的,就是說(shuō)模型與數(shù)據(jù)格式無(wú)關(guān),這樣一個(gè)模型能為多個(gè)視圖提供數(shù)據(jù).由于應(yīng)用于模型的代碼只需寫一次就可以被多個(gè)視圖重用,所以減少了代碼的重復(fù)性

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

            ? ?因?yàn)椴煌墓究赡軙?huì)開(kāi)發(fā)出有相同名字的程序集來(lái),如果這些程序集都被復(fù)制到同一 個(gè)相同的目錄下,最后一個(gè)安裝的程序集將會(huì)代替前面的程序集。這就是著名的Windows “DLL Hell”出現(xiàn)的原因。
            ??
            ? ?很明顯,簡(jiǎn)單的用文件名來(lái)區(qū)分程序集是不夠的,CLR需要支持某種機(jī)制來(lái)唯一的標(biāo)識(shí)一個(gè)程序集。這就是所謂的強(qiáng)命名程序集。
            ??
            ? ?一個(gè)強(qiáng)命名程序集包含四個(gè)唯一標(biāo)志程序集的特性:文件名(沒(méi)有擴(kuò)展名),版本號(hào),語(yǔ)言文化信息(如果有的話),公有秘鑰。
            ??
            ? ?這些信息存儲(chǔ)在程序集的清單(manifest)中。清單包含了程序集的元數(shù)據(jù),并嵌入在程序集的某個(gè)文件中。
            ??
            ? ?下面的字符串標(biāo)識(shí)了四個(gè)不同的程序集文件:
            ??
            ? ?“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”
            ??
            ? ?如果一個(gè)公司想唯一的標(biāo)識(shí)它的程序集,那么它必須首先獲取一個(gè)公鑰/私鑰對(duì),然后將共有秘鑰和程序集相關(guān)聯(lián)。不存在兩個(gè)兩個(gè)公司有同樣的公鑰/私鑰對(duì)的情況,正是這種區(qū)分使得我們可以創(chuàng)建有著相同名稱,版本和語(yǔ)言文化信息的程序集,而不引起任何沖突。
            ??
            ? ?與強(qiáng)命名程序集對(duì)應(yīng)的就是所謂的弱命名程序集。(其實(shí)就是普通的沒(méi)有被強(qiáng)命名的程序集)。兩種程序集在結(jié)構(gòu)上是相同的。都使用相同的PE文件格式,PE表頭,CLR表頭,元數(shù)據(jù),以及清單(manifest)。二者之間真正的區(qū)別在于:強(qiáng)命名程序集有一個(gè)發(fā)布者的公鑰/私鑰對(duì)簽名,其中的公鑰/私鑰對(duì)唯一的標(biāo)識(shí)了程序集的發(fā)布者。利用公鑰/私鑰對(duì),我們可以對(duì)程序集進(jìn)行唯一性識(shí)別、實(shí)施安全策略和版本控制策略,這種唯一標(biāo)識(shí)程序集的能力使得應(yīng)用程序在試圖綁定一個(gè)強(qiáng)命名程序集時(shí),CLR能夠?qū)嵤┠承耙汛_知安全”的策略(比如只信任某個(gè)公司的程序集)。
            請(qǐng)說(shuō)明在.net中常用的幾種頁(yè)面間傳遞參數(shù)的方法,并說(shuō)出他們的優(yōu)缺點(diǎn)。
            session(viewstate) 簡(jiǎn)單,但易丟失
            application 全局
            cookie 簡(jiǎn)單,但可能不支持,可能被偽造
            input type="hidden" 簡(jiǎn)單,可能被偽造
            url參數(shù) 簡(jiǎn)單,顯示于地址欄,長(zhǎng)度有限
            數(shù)據(jù)庫(kù) 穩(wěn)定,安全,但性能相對(duì)弱
            ===============================asp.net 頁(yè)面生命周期

            錯(cuò)誤:
            ??? 每個(gè)頁(yè)面的生命周期為用戶的訪問(wèn)開(kāi)始到結(jié)束,也就是說(shuō)程序中的全局變量同時(shí)生存到用戶的訪問(wèn)結(jié)束.

            正確:
            ??? 每個(gè)頁(yè)面的生命周期為用戶的每一次訪問(wèn),也就是說(shuō)每一次客戶端與服務(wù)器之間的一個(gè)往返過(guò)程.全局變量的生命周期在此之間.

            例:
            string gb_string;

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


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

            //跟第一次那個(gè)被賦值的字符串不是同一對(duì)象.
            }

            ASP.NET 頁(yè)面生命周期
            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;

            總結(jié):

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


            ???? 1.一般都是初始化web控件,因?yàn)檫@些控件的狀態(tài)(值),由系統(tǒng)自動(dòng)保存(__VIEWSTATE),
            下次返回時(shí),自動(dòng)賦值,這是ASP.NET保存"web控件"狀態(tài)的特性.
            ??

            ?? 2.但是初始的如果是程序中用到的全局變量,就應(yīng)該注意他的生命周期的問(wèn)題.如果函數(shù)都在一個(gè)生命周期中,全局變量的值當(dāng)然是一致的.但是如果在"由客戶激發(fā)"的事件中,這就不同了,每個(gè)客戶事件的激發(fā),都會(huì)導(dǎo)致新的頁(yè)面生命周期的產(chǎn)生,全局變量的值會(huì)丟失,因?yàn)樗鼈儾辉谕豁?yè)面生命周期(就像上面出現(xiàn)的錯(cuò)誤1).


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

            asp.net2.0 頁(yè)面生命周期方法

            方法 活動(dòng)

            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

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


            在以前寫個(gè)一篇關(guān)于ASP.NET頁(yè)面生命周期的草稿,最近又看了看ASP.NET,做個(gè)補(bǔ)充,看看頁(yè)面初始過(guò)程到底是怎么樣的
            下面是ASP.NET頁(yè)面初始的過(guò)程:
            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;

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

            對(duì)應(yīng)的事件Page.Init

            2. Load ViewState
            這個(gè)過(guò)程是載入VIEWSTATE和Postback數(shù)據(jù),比如我們上面的TextBox1,這時(shí)就賦了"哈哈",所以,在Post_Init()對(duì)控件賦值是無(wú)意義的,它都會(huì)
            在這個(gè)過(guò)程里被改寫,當(dāng)然第一次頁(yè)面載入例外,因?yàn)闆](méi)有VIEWSTATE數(shù)據(jù)。

            沒(méi)有對(duì)應(yīng)的事件

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

            ? //每次這里的都回執(zhí)行CODE HERE
            }

            對(duì)應(yīng)的事件Page.Load

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

            沒(méi)有對(duì)應(yīng)的事件(我們自己的事件函數(shù)都包括在這個(gè)過(guò)程里比如上面的ListBox1_SelectedIndexChanged)

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

            對(duì)應(yīng)的事件時(shí)Page.PreRender

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

            對(duì)應(yīng)的事件Page.Render

            8. Unload event;
            大家應(yīng)該明白,當(dāng)想服務(wù)器請(qǐng)求一個(gè)對(duì)象的時(shí)候,就會(huì)在內(nèi)存里生成一個(gè)繼承頁(yè)面對(duì)象,也就是頁(yè)面的類,它繼承自System.Web.UI.Page.
            當(dāng)頁(yè)面對(duì)象從內(nèi)存中卸載時(shí)發(fā)生,將觸發(fā)該事件.

            對(duì)應(yīng)的事件Page.Unload

            9. Dispose method called;
            銷毀所有的對(duì)象.當(dāng)從內(nèi)存釋放Page時(shí)發(fā)生,這是生存期的最后階段??赡艿?和9似乎有些模糊,不過(guò)我也沒(méi)怎么搞清楚,待研究!

            對(duì)應(yīng)的事件Dispose

            以上就是ASP.NET頁(yè)面周期的描述。

            注意上面灰色背景的文字,如果一個(gè)過(guò)程中有對(duì)應(yīng)的事件,我們可以自己定義一個(gè)函數(shù)(當(dāng)然先在MSDN中找到函數(shù)原型),然后在
            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);
            }

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

            初學(xué)ASP.NET,請(qǐng)各位不吝賜教!???
            ====================\

            Asp.net2.0頁(yè)面的生命周期

            表格 1. ASP.NET 頁(yè)面生存周期中的關(guān)鍵事件

            階段

            頁(yè)面事件

            可重寫方法

            頁(yè)面初始化

            Init

            加載視圖狀態(tài)

            LoadViewState

            處理回發(fā)數(shù)據(jù)

            實(shí)現(xiàn) IPostBackDataHandler 接口的任何控件中的 LoadPostData 方法

            加載頁(yè)面

            Load

            回發(fā)更改通知

            實(shí)現(xiàn) IPostBackDataHandler 接口的任何控件中的 RaisePostDataChangedEvent 方法

            處理回發(fā)事件

            控件所定義的任何回發(fā)事件

            實(shí)現(xiàn)了 IPostBackEventHandler 接口的任何控件的 RaisePostBackEvent 方法

            頁(yè)面呈現(xiàn)前階段

            PreRender

            保存視圖狀態(tài)

            SaveViewState

            呈現(xiàn)頁(yè)面

            Render

            卸載頁(yè)面

            Unload

            ?

            ?

            ?

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

            一.預(yù)初始化對(duì)象(OnPreInit)

            ?

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

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


            注意,我們只能在PreInit()事件中動(dòng)態(tài)的設(shè)置themes

            使用母版頁(yè)時(shí)的特例
            我們先要了解一個(gè)非常重要的知識(shí)點(diǎn)——母版頁(yè)被處理的過(guò)程就相當(dāng)于內(nèi)容頁(yè)中的一個(gè)控件。

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

            這 個(gè)原因就是內(nèi)容頁(yè)中的所有控件都包含在“ContentPlaceholder”里,而“ContentPlaceholder”其實(shí)就是母版頁(yè)的一個(gè)子 控件。現(xiàn)在母版頁(yè)被處理的過(guò)程就相當(dāng)于內(nèi)容頁(yè)中的一個(gè)控件,我們?cè)缦忍岬竭^(guò),除了Init()和Unload()之外的所有事件都是從最外面到最里面被激 發(fā)的。雖然頁(yè)的PreInit()是第一個(gè)被觸發(fā)的事件,但是用戶控件和母版頁(yè)是沒(méi)有這個(gè)事件的,所以在頁(yè)的Page_PreInit()方法中,母版頁(yè) 和用戶控件都不會(huì)被初始化,而是在Init()事件之后

            接下來(lái)讓我們來(lái)看一下Page_Init()事件之后控件的層次結(jié)構(gòu)

            在這個(gè)頁(yè)面級(jí)的事件中,所有在設(shè)計(jì)時(shí)創(chuàng)建的控件都將被用默認(rèn)值做初始化。例如,如果你有一個(gè)Text屬性值為“Hello”的TextBox控件,則此時(shí)這個(gè)屬性被設(shè)置。我們也可以在這里動(dòng)態(tài)的創(chuàng)建控件。

            這個(gè)事件僅僅發(fā)生在頁(yè)級(jí)別的類中,用戶控件和母版頁(yè)沒(méi)有這個(gè)事件

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

            二.初始化對(duì)象(OnInit)

            一個(gè)頁(yè)面的控件(以及頁(yè)面本身)最初應(yīng)被正確的初始化。通過(guò)在你的C#文件的構(gòu)造函數(shù) 中聲名所有對(duì)象,頁(yè)面就知道要?jiǎng)?chuàng)建多少對(duì)象以及它們的類型。一旦你在你的構(gòu)造函數(shù)中聲名了所有的對(duì)象,你就可以通過(guò)繼承類、方法、事件或是屬性訪問(wèn)它們。 然而,如果你的一些對(duì)象是在Aspx文件中指定的一些控件,那么這些控件就沒(méi)有屬性可言了。同時(shí),通過(guò)代碼訪問(wèn)它們會(huì)產(chǎn)生一些意外的錯(cuò)誤,因?yàn)檫@些控件實(shí) 例是沒(méi)有一個(gè)確定的創(chuàng)建順序的(如果它們是被一起創(chuàng)建的)。還有,你可以通過(guò)OnInit來(lái)重載初始化事件.

            在這個(gè)事件里,我們能讀出控件的屬性(在設(shè)計(jì)模式中設(shè)置的)。但是我們不能讀出用戶設(shè)置的值,因?yàn)榈玫接脩粼O(shè)置的值是在LoadPostData()事件被激發(fā)之后。不過(guò)在這個(gè)事件中我們可以得到POST數(shù)據(jù),如下

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

            三.完成初始化(OnInitComplete)

            完成初始化頁(yè)面OnInit事件后觸發(fā)。
            ?

            四.導(dǎo)入Viewstate數(shù)據(jù)(LoadViewState)

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

            ?

            五.用LoadPostData處理Postback數(shù)據(jù)(LoadPostData)

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

            ?

            六.OnPreLoad

            在加載頁(yè)面OnLoad事件前觸發(fā)??梢栽陧?yè)面里面通過(guò)Page_OnPreLoad事件綁定

            七.導(dǎo)入對(duì)象(OnLoad)

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

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

            ?

            八.RaisePostBackChanged事件(RaisePostDataChangedEvent)

            就像在上面提到的那樣,這個(gè)事件是發(fā)生在所有的控件執(zhí)行了IPostBackDataHandler接口操作并被正確的 postback數(shù)據(jù)更新后的。在這個(gè)過(guò)程中,每個(gè)控件都被賦予一個(gè)布爾值來(lái)標(biāo)志該控件有沒(méi)有被更新。然后,Asp.net就在整個(gè)頁(yè)面上尋找任何已被更 新過(guò)的控件并執(zhí)行RaisePostDataChanged事件操作。不過(guò),這個(gè)事件是要在所有的控件都被更新了以及Load事件完成后才進(jìn)行的。這樣就 保證了一個(gè)控件在被postback數(shù)據(jù)更新前,別的控件在RaisePostDataChanged事件中是不會(huì)被手動(dòng)改變的。

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

            當(dāng)由postback數(shù)據(jù)在服務(wù)器端引起的事件都完成后,產(chǎn)生postback數(shù)據(jù)的對(duì)象就執(zhí)行 RaisePostBackEvent事件操作??墒菚?huì)有這種情況,由于一個(gè)控件狀態(tài)的改變使得它將表單返回給服務(wù)器或是用戶點(diǎn)擊了提交按鈕使得表單返回 給服務(wù)器。在這種情況下應(yīng)該有相應(yīng)的處理代碼來(lái)體現(xiàn)事件驅(qū)動(dòng)這一面向?qū)ο螅∣OP)編程原則。由于要滿足呈現(xiàn)給瀏覽器的數(shù)據(jù)的精確性要求,在一系列 postback事件中RaisePostBackEvent事件是最后發(fā)生的。

            在postback過(guò)程中改變的控件不應(yīng)在執(zhí)行功能函數(shù)被調(diào)用后更新。也就是說(shuō),任何由于一個(gè)預(yù)期的事件而改變的數(shù)據(jù)應(yīng)該在最終的頁(yè)面上被反映出來(lái)。你可以通過(guò)修改RaisePostBackEvent函數(shù)來(lái)滿足你的要求,圖示如下:

            ?

            十.Page_OnLoadComplete

            完成頁(yè)面加載OnLoad事件后觸發(fā)。

            十一.預(yù)先呈遞對(duì)象

            可以改變對(duì)象并將改變保存的最后時(shí)刻就是這一步――預(yù)先呈遞對(duì)象。這樣,你可以在這一步對(duì)控件的屬性、控件樹(shù)結(jié)構(gòu)等作出最后的修改。同時(shí)還不用考慮 Asp.net對(duì)其作出任何改變,因?yàn)榇藭r(shí)已經(jīng)脫離了數(shù)據(jù)庫(kù)調(diào)用以及viewstate更新了。在這一步之后,對(duì)對(duì)象的所有修改將最終被確定,不能被保存 到頁(yè)面的viewstate中了。你可以通過(guò)OnPreRender來(lái)重載這一步。

            十二.完成預(yù)呈現(xiàn)(OnPreRenderComplete)

            在完成預(yù)呈現(xiàn)OnPreRender事件后觸發(fā)。這是完成頁(yè)面呈現(xiàn)的最后一道關(guān)卡,在此之后,頁(yè)面將無(wú)法再進(jìn)行任何呈現(xiàn)上的改動(dòng)。

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

            八.保存ViewState(SaveViewState)

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

            ?

            九.呈遞給Html(Render)

            運(yùn)用Html創(chuàng)建給瀏覽器輸出的頁(yè)面的時(shí)候Render事件就發(fā)生了。在Render事件過(guò)程中,頁(yè)面調(diào)用其中的對(duì)象將 它們呈遞給Html。然后,頁(yè)面就可以以Html的形式被用戶的瀏覽器訪問(wèn)了。當(dāng)Render事件被重載時(shí),開(kāi)發(fā)者可以編寫自定義的Html代碼使得原先 生成的Html都無(wú)效而按照新的Html來(lái)組織頁(yè)面。Render方法將一個(gè)HtmlTextWriter對(duì)象作為參數(shù)并用它將Html在瀏覽器上以網(wǎng)頁(yè) 的形式顯示。這時(shí)仍然可以做一些修改動(dòng)作,不過(guò)它們只是客戶端的一些變化而已了。你可以重載Render事件,圖示如下:

            ?

            十.銷毀對(duì)象(Page_UnLoad)

            在呈遞給Html完成后,所有的對(duì)象都應(yīng)被銷毀。在Dispose事件中,你應(yīng)該銷毀所有在建立這個(gè)頁(yè)面時(shí)創(chuàng)建的對(duì)象。這時(shí),所有的處理已經(jīng)完畢,所以銷毀任何剩下的對(duì)象都是不會(huì)產(chǎn)生錯(cuò)誤的,包括頁(yè)面對(duì)象。你可以重載Dispose事件。

            全文總結(jié)

            以上就是Asp.net頁(yè)面生命周期中的幾個(gè)主要事件。每次我們請(qǐng)求一個(gè)Asp.net頁(yè)面時(shí),我們都經(jīng)歷著同樣的過(guò)程:從初始化對(duì)象到銷毀對(duì)象。 通過(guò)了解Asp.net頁(yè)面的內(nèi)部運(yùn)行機(jī)制,我相信大家在編寫、調(diào)試代碼的時(shí)候會(huì)更加游刃有余的。不過(guò)整個(gè)頁(yè)面的生命周期的方法如下:

            方法 活動(dòng)

            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

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

            AspNet2.0頁(yè)面生命周期 ?

            頁(yè)面框架通過(guò)如下過(guò)程處理aspx文件請(qǐng)求:
            ??? 1:解析aspx文件,并創(chuàng)建一個(gè)控件樹(shù);
            ??? 2:使用控件樹(shù)動(dòng)態(tài)實(shí)現(xiàn)一個(gè)繼承自Page類的類或者控件 ;
            ??? 3:動(dòng)態(tài)編譯類;
            ??? 4:緩存編譯類,以備后用;
            ??? 5:動(dòng)態(tài)創(chuàng)建一個(gè)編譯類的實(shí)例。頁(yè)面開(kāi)始啟動(dòng)生命期,在這個(gè)過(guò)程中,頁(yè)面將通過(guò)生命周期的不同階段;=========================================================
            頁(yè)面經(jīng)歷了如下階段【其中一些階段標(biāo)記為僅僅回傳,是說(shuō)只有在被回傳到服務(wù)器時(shí),頁(yè)面才經(jīng)歷這些階段】:

            01:頁(yè)面首先從QueryString或者Request對(duì)象的Form集合中獲得回傳數(shù)據(jù)。

            02:頁(yè)面檢測(cè)回傳數(shù)據(jù)集合(NameValueCollection,Form或者QueryString)是否包含一個(gè)鍵為_(kāi)CallBackId的項(xiàng)。如? 果存在,那么設(shè)置其Boolean屬性IsCallBack為True,以便通過(guò)AspNet客戶端回調(diào)機(jī)制,標(biāo)明頁(yè)面已經(jīng)回傳到服務(wù)器。

            03:預(yù)初始化(PreInit):
            ? 在頁(yè)面生命周期的預(yù)初始化階段執(zhí)行如下操作:
            ?? a:調(diào)用OnPreInit方法引發(fā)PreInit事件。
            ?? b:利用App_Themes目錄中的內(nèi)容初始化主題,以動(dòng)態(tài)實(shí)現(xiàn)一個(gè)PageTheme類型的類,
            ??? 編譯該類,并創(chuàng)建一個(gè)編譯類的實(shí)例,接著將實(shí)例賦值給它的PageTheme屬性值
            ?? c:應(yīng)用母版頁(yè)

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

            05:完成初始化(InitComplete):
            ? 頁(yè)面調(diào)用OnInitComplete方法來(lái)引發(fā)InitComplete事件。該事件標(biāo)明了初始化階段的結(jié)束。
            此時(shí),頁(yè)面Controls集合的所有控件都被初始化了。


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

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

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

            09:預(yù)加載(PreLoad):
            ? 頁(yè)面調(diào)用OnPreLoad方法以引發(fā)PreLoad事件。該事件表示頁(yè)面生命周期將進(jìn)入加載階段。

            10:加載(Load):
            ? 頁(yè)面首先調(diào)用自身的OnLoad方法以引發(fā)自身的Load事件,接著遞歸調(diào)用Controls集合中控件的OnLoad方法以引發(fā)它們的Load事件。頁(yè)面開(kāi)發(fā)人員可以為L(zhǎng)oad事件注冊(cè)回調(diào),那么就可以通過(guò)編程將子控件添加到頁(yè)面的Controls集合中。

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

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

            13:引發(fā)回傳事件(Raise PostBack Event)[PostBack Only]:
            ? 頁(yè)面調(diào)用控件的RaisePostEvent方法,這些控件相關(guān)的Html元素用于提交表單。例如,Button控件的相關(guān)Html元素將頁(yè)面回傳到服務(wù)器??丶腞aisePostBackEvent方法必須將回傳事件映射到一個(gè)或多個(gè)服務(wù)器事件。例如,Button控件的 RaisePostBackEvent方法將事件映射到了服務(wù)器端事件Command和Click上。

            14:完成加載(Load Complete):
            ? 頁(yè)面調(diào)用OnLoadComplete方法來(lái)引發(fā)LoadComplete事件,這表示所有加載活動(dòng),包括加載回傳數(shù)據(jù),以及引發(fā)回傳數(shù)據(jù)修改事件,并以更新控件自身的活動(dòng)都完成了。

            15:引發(fā)回調(diào)事件(Raise CallBack Event)(PostBack And CallBack Only):
            ? 頁(yè)面調(diào)用控件的RaiseCallBackEvent方法。該控件可使用AspNet客戶端回調(diào)機(jī)制來(lái)允許客戶端方法(例如JavaScript函數(shù))調(diào)用服務(wù)器端方法,而無(wú)需將整個(gè)頁(yè)面回傳給服務(wù)器。
            RaiseCallBackEvent方法必須調(diào)用服務(wù)器端方法。如果頁(yè)面的回傳使用了客戶端回調(diào)機(jī)制,那么頁(yè)面將不會(huì)執(zhí)行剩余的頁(yè)面生命周期階段。

            16:預(yù)呈現(xiàn)(PreRender):
            ? 在頁(yè)面生命周期這個(gè)階段執(zhí)行一下操作。
            ?? a:調(diào)用EnsureChildControls方法來(lái)確保在頁(yè)面進(jìn)入呈現(xiàn)階段之前,創(chuàng)建其子控件。
            ?? b:調(diào)用自身的OnPreRender方法來(lái)引發(fā)PreRender事件。
            ?? c:遞歸調(diào)用Controls集合中控件的OnPreRender方法,以引發(fā)它們的PreRender事件。

            17:預(yù)呈現(xiàn)完成(PreRender Complete):
            ? 頁(yè)面調(diào)用OnPrerenderComplete方法來(lái)引發(fā)PreRenderComplete事件,這表示所有預(yù)呈現(xiàn)活動(dòng)完成了。

            18:保存控件狀態(tài)(Save Control State):
            ? 頁(yè)面遞歸調(diào)用Controls集合中控件的SaveControlState方法。這些控件已經(jīng)調(diào)用了Page類的RegisterRequiresControlState方法來(lái)保存它們的控件狀態(tài)。

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

            20:保存狀態(tài)完成(Save View Complete):
            ? 頁(yè)面調(diào)用OnSaveStateComplete方法以引發(fā)SaveStateComplete事件,這表示所有狀態(tài)保存活動(dòng)都完成了。

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



            ?

            新一篇:?單點(diǎn)登錄在ASP.NET上的簡(jiǎn)單實(shí)現(xiàn)

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

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

            1.Application對(duì)象
            ? ? Application用于保存所有用戶的公共的數(shù)據(jù)信息,如果使用Application對(duì)象,一個(gè)需要考慮的問(wèn)題是任何寫操作都要在Application_OnStart事件(global.asax)中完成.盡管使用Application.Lock和Applicaiton.Unlock方法來(lái)避免寫操作的同步,但是它串行化了對(duì)Application對(duì)象的請(qǐng)求,當(dāng)網(wǎng)站訪問(wèn)量大的時(shí)候會(huì)產(chǎn)生嚴(yán)重的性能瓶頸.因此最好不要用此對(duì)象保存大的數(shù)據(jù)集合. 下面我們做個(gè)在線用戶統(tǒng)計(jì)的例子來(lái)說(shuō)明這個(gè)問(wèn)題:
            ? ? (以文件的形式存放網(wǎng)站總訪問(wèn)量)
            ? ? (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 的摘要說(shuō)明。
            ? ?/// </summary>

            ? ?public class Global : System.Web.HttpApplication
            ? ?
            {
            ? ?? ? /**/
            /// <summary>
            ? ?? ? /// 必需的設(shè)計(jì)器變量。
            ? ?? ? /// </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);//文件不存在,創(chuàng)建文件
            ? ?? ?? ?? reader = new StreamReader(fileStream);//要讀取的完整路徑
            ? ?? ?? ?? Application["AllGuests"] = Convert.ToInt32(reader.ReadLine()); //從當(dāng)前流中讀取一行字符并將數(shù)據(jù)作為字符串返回
            ? ?? ?? ?? reader.Close();//關(guān)閉流
            ? ?? ? }

            ? ?? ?
            protected void Session_Start(Object sender, EventArgs e)//當(dāng)用戶訪問(wèn)網(wǎng)站時(shí),在線用戶+1,總訪問(wèn)數(shù)+1
            ? ?? ? {
            ? ?? ?? ?? Application.Lock();//同步,避免同時(shí)寫入

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

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

            ? ?? ?? ?? writer.WriteLine(Application["AllGuests"].ToString());//把訪問(wèn)網(wǎng)站的總用戶數(shù)再次寫入到文件
            ? ?? ?? ?? writer.Close();//關(guān)閉寫入流

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

            ? ?? ?
            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)//當(dāng)前用戶退出網(wǎng)站時(shí),在線用戶數(shù)量-1,
            ? ?? ? {
            ? ?? ?? ?? Application.Lock();
            ? ?? ?? ?? Application["CurrentGuests"] =(int)Application["CurrentGuests"] - 1;//總在線用戶數(shù)量-1

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

            ? ?? ? }

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

            ? ?? ? }

            ? ?? ?? ??
            ? ?? ?
            Web 窗體設(shè)計(jì)器生成的代碼#region Web 窗體設(shè)計(jì)器生成的代碼
            ? ?? ? /**//// <summary>
            ? ?? ? /// 設(shè)計(jì)器支持所需的方法 - 不要使用代碼編輯器修改
            ? ?? ? ///
            此方法的內(nèi)容。
            ? ?? ? /// </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 = "正在訪問(wèn)站點(diǎn)的用戶數(shù):" + Application["CurrentGuests"].ToString(); ? ?
            ? ? ?? ?? ? this.Label2.Text ="訪問(wèn)過(guò)站點(diǎn)的總用戶數(shù):" + Application["AllGuests"].ToString();
            ? ? ?? ?}
            2.Session對(duì)象
            ? ? Session用于保存每個(gè)用戶的專用信息.她的生存期是用戶持續(xù)請(qǐng)求時(shí)間再加上一段時(shí)間(一般是20分鐘左右).S
            ession中的信息保存在Web服務(wù)器內(nèi)容中,保存的數(shù)據(jù)量可大可小.當(dāng)Session超時(shí)或被關(guān)閉時(shí)將自動(dòng)釋放保存的數(shù)據(jù)信息.由于用戶停止使用應(yīng)用程序后它仍然在內(nèi)存中保持一段時(shí)間,因此使用Session對(duì)象使保存用戶數(shù)據(jù)的方法效率很低.對(duì)于小量的數(shù)據(jù),使用Session對(duì)象保存還是一個(gè)不錯(cuò)的選擇.使用Session對(duì)象保存信息的代碼如下: //存放信息
            Session["username"]="zhouhuan";
            //讀取數(shù)據(jù)
            string UserName=Session["username"].ToString();????

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

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

            6,QueryString多半是地址欄參數(shù),到下一頁(yè)使用,明文,無(wú)所謂安全;??

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

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


            我對(duì).NET技術(shù)不熟悉,因此對(duì)ViewState,Cache這兩個(gè)功能不清楚,但可以對(duì)其他三個(gè)Cookie,Session,Application提供一些實(shí)踐方面的建議.??
            ? 1)cookie是大家最喜歡的一種存儲(chǔ)方式,但不是好的存儲(chǔ)方法,我的建議是在商業(yè)性網(wǎng)站開(kāi)發(fā)中最好不用.典型的使用方法如下:??
            ? <%??
            ? 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是一種比較好的使用方式,但是不要使用過(guò)大.比如在一個(gè)商城的網(wǎng)站中,只有customerID用session保存,其他都從數(shù)據(jù)庫(kù)中獲得數(shù)據(jù).典型代碼如下:??
            ? <%??
            ? Session.Contents("FavColour")?? =?? Request.Form("txtColour")??
            ? Response.write?? "Your?? colour?? has?? been?? saved"??
            ? %>??
            ? 3)Application是一個(gè)全程對(duì)象,通常的一個(gè)應(yīng)用是做counter,看了國(guó)內(nèi)的許多代碼,好象大家不喜歡用這個(gè)對(duì)象.典型代碼如下:??
            ? <%??
            ? Application.Lock??
            ? Application("anotherVariable")=Application("anotherVariable")+1??
            ? Application.Unlock??
            ? Response.write?? Application("anotherVariable")??
            ? %>??
            ???
            ? 我在開(kāi)發(fā)時(shí)只用1個(gè)session作為用戶的ID.


            Application

            1.???????? Application用來(lái)保存所有用戶共用的信息

            2.???????? 在Asp時(shí)代,如果要保存的數(shù)據(jù)在應(yīng)用程序生存期內(nèi)不會(huì)或者很少發(fā)生改變,那么使用Application是理想的選擇。但是在Asp.net開(kāi)發(fā)環(huán)境中我們把類似的配置數(shù)據(jù)放在Web.config中。

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

            4.???????? 不要使用Application保存大數(shù)據(jù)量信息

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

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

            Session

            1.???????? Session用來(lái)保存每一個(gè)用戶的專有信息

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

            3.???????? Session信息是保存在Web服務(wù)器內(nèi)存中的,保存數(shù)據(jù)量可大可小

            4.???????? Session超時(shí)或者被關(guān)閉將自動(dòng)釋放數(shù)據(jù)信息

            5.???????? 由于用戶停止使用應(yīng)用程序之后它仍在內(nèi)存中存留一段時(shí)間,因此這種方法效率較低

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

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

            Cookie

            1.???????? Cookie用來(lái)保存客戶瀏覽器請(qǐng)求服務(wù)器頁(yè)面的請(qǐng)求信息

            2.???????? 我們可以存放非敏感的用戶信息,保存時(shí)間可以根據(jù)需要設(shè)置

            3.???????? 如果沒(méi)有設(shè)置Cookie失效日期,它的生命周期保存到關(guān)閉瀏覽器為止

            4.???????? Cookie對(duì)象的Expires屬性設(shè)置為MinValue表示永不過(guò)期

            5.???????? Cookie存儲(chǔ)的數(shù)據(jù)量受限制,大多數(shù)的瀏覽器為4K因此不要存放大數(shù)據(jù)

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

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

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

            ViewState

            1.???????? ViewState用來(lái)保存用戶的狀態(tài)信息,有效期等于頁(yè)面的生命周期

            2.???????? 可以保存大量數(shù)據(jù)但是要慎用,因?yàn)闀?huì)影響程序性能

            3.???????? 所有的Web服務(wù)器控件都是用ViewState在頁(yè)面PostBack期間保存狀態(tài)

            4.???????? 不需要?jiǎng)t關(guān)閉 @page 里面設(shè)置EnableViewState=false

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

            Cache

            1.???????? Cache用于在Http請(qǐng)求期間保存頁(yè)面或者數(shù)據(jù)

            2.???????? Cache的使用可以大大的提高整個(gè)應(yīng)用程序的效率

            3.???????? 它允許將頻繁訪問(wèn)的服務(wù)器資源存儲(chǔ)在內(nèi)存中,當(dāng)用戶發(fā)出相同的請(qǐng)求后
            服務(wù)器不是再次處理而是將Cache中保存的數(shù)據(jù)直接返回給用戶

            4.???????? 可以看出Cache節(jié)省的是時(shí)間—服務(wù)器處理時(shí)間

            5.???????? Cache實(shí)例是每一個(gè)應(yīng)用程序?qū)S械模渖芷?=該應(yīng)用程序周期
            應(yīng)用程序重啟將重新創(chuàng)建其實(shí)例

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

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

            Hidden

            1.???????? Hidden控件屬于Html類型的服務(wù)器控件,始終處于隱藏狀態(tài)

            2.???????? 每一次提交的時(shí)候它會(huì)和其他服務(wù)器控件一起提交到服務(wù)器端

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


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

            2,QueryString多半是地址欄參數(shù),到下一頁(yè)使用,明文,無(wú)所謂安全;

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

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

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

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

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

            ?

            posted on 2008-07-01 16:10 snowball 閱讀(10384) 評(píng)論(6)  編輯 收藏 引用 所屬分類: 文章轉(zhuǎn)載學(xué)習(xí)

            評(píng)論

            # re: 面向?qū)ο蟮娜齻€(gè)基本特征(講解) 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.   回復(fù)  更多評(píng)論   

            # re: 面向?qū)ο蟮娜齻€(gè)基本特征(講解) 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.   回復(fù)  更多評(píng)論   

            # re: 面向?qū)ο蟮娜齻€(gè)基本特征(講解) 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.   回復(fù)  更多評(píng)論   

            # re: 面向?qū)ο蟮娜齻€(gè)基本特征(講解) 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.   回復(fù)  更多評(píng)論   

            # re: 面向?qū)ο蟮娜齻€(gè)基本特征(講解) 2013-12-10 18:55 essays.mightystudents.com

            只記得你想完成的總體目標(biāo)是讓讀者認(rèn)同你,然後,希望把你的建議適當(dāng)?shù)男袆?dòng)。  回復(fù)  更多評(píng)論   

            # re: 面向?qū)ο蟮娜齻€(gè)基本特征(講解) 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.  回復(fù)  更多評(píng)論   

            導(dǎo)航

            留言簿(1)

            隨筆分類

            友情鏈接

            搜索

            最新隨筆

            最新評(píng)論

            閱讀排行榜

            日本道色综合久久影院| 久久国产精品久久| 99精品国产综合久久久久五月天| yy6080久久| 久久久久亚洲AV无码麻豆| 国产精品美女久久久久网| 久久精品国产黑森林| 亚洲∧v久久久无码精品| 99久久综合国产精品二区| 久久99久国产麻精品66| 久久综合九色综合97_久久久| 久久精品免费大片国产大片| 久久精品99久久香蕉国产色戒 | 久久亚洲高清观看| 中文字幕精品无码久久久久久3D日动漫| 亚洲熟妇无码另类久久久| 99久久精品久久久久久清纯| 亚洲第一极品精品无码久久| 国产成人精品久久亚洲高清不卡| 久久久久女人精品毛片| 香蕉久久夜色精品国产尤物| 99国内精品久久久久久久| 久久99精品久久久久久动态图| 久久久久亚洲?V成人无码| 91精品国产色综久久| 久久人人妻人人爽人人爽| 亚洲精品午夜国产va久久| 久久天天躁狠狠躁夜夜av浪潮| 久久亚洲国产午夜精品理论片| 热re99久久精品国99热| 99久久夜色精品国产网站| 国产精品久久久久久久久软件| 亚洲乱亚洲乱淫久久| 91亚洲国产成人久久精品| 国产精品一区二区久久精品无码 | 国产精品久久99| 久久国产高潮流白浆免费观看| 亚洲精品高清国产一线久久| 婷婷久久香蕉五月综合加勒比| 久久99久国产麻精品66| 久久亚洲精品成人av无码网站|