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

             

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

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

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

            o_OOBase.gif

            封裝

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

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

            繼承

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

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

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

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

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

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

            ?

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

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

            ????????? 接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實(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 開發(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)單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。

            實(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ì)于編譯器來說是這樣的)。如,有兩個(gè)同名函數(shù): function func(p:integer):integer; function func(p:string):integer; 。那么編譯器做過修飾后的函數(shù)名稱可能是這樣的: int_func str_func 。對(duì)于這兩個(gè)函數(shù)的調(diào)用,在編譯器間就已經(jīng)確定了,是靜態(tài)的(記住:是靜態(tài))。也就是說,它們的地址在編譯期就綁定了(早綁定),因此,重載和多態(tài)無關(guān)!真正和多態(tài)相關(guān)的是 覆蓋 。當(dāng)子類重新定義了父類的虛函數(shù)后,父類指針根據(jù)賦給它的不同的子類指針,動(dòng)態(tài)(記住:是動(dòng)態(tài)!)的調(diào)用屬于子類的該函數(shù),這樣的函數(shù)調(diào)用在編譯期間是無法確定的(調(diào)用的子類的虛函數(shù)的地址無法給出)。因此,這樣的函數(shù)地址是在運(yùn)行期綁定的(晚邦定)。結(jié)論就是:重載只是一種語言特性,與多態(tài)無關(guān),與面向?qū)ο笠矡o關(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ù)語中,這種關(guān)系被稱為泛化( Generalization )。 Person( ) 是基類, Teacher( 教師 ) Student( 學(xué)生 ) Guest( 來賓 ) 是子類。

            若在邏輯上 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 組合而成,不是派生(繼承)而成。

            ?

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

            理解抽象類

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

            ?

            ?

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

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


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

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

            使用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的,不過在interface中一般不定義數(shù)據(jù)成員),所有的成員方法都是abstract的。從某種意義上說,interface是一種特殊形式的abstract class。

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

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

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

            在抽象類中不能定義默認(rèn)行為還存在另一個(gè)比較嚴(yán)重的問題,那就是可能會(huì)造成維護(hù)上的麻煩。因?yàn)槿绻髞硐胄薷念惖慕缑妫ㄒ话阃ㄟ^abstract class或者interface來表示)以適應(yīng)新的情況(比如,添加新的方法或者給已用的方法中添加新的參數(shù))時(shí),就會(huì)非常的麻煩,可能要花費(fèi)很多的時(shí)間(對(duì)于派生類很多的情況,尤為如此)。但是如果界面是通過abstract class來實(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

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

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

            考慮這樣一個(gè)例子,假設(shè)在我們的問題領(lǐng)域中有一個(gè)關(guān)于Door的抽象概念,該Door具有執(zhí)行兩個(gè)動(dòng)作open和close,此時(shí)我們可以通過abstract class或者interface來定義一個(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。看起來好像使用abstract class和interface沒有大的區(qū)別。

            如果現(xiàn)在要求Door還要具有報(bào)警的功能。我們?cè)撊绾卧O(shè)計(jì)針對(duì)該例子的類結(jié)構(gòu)呢(在本例中,主要是為了展示abstract class和interface反映在設(shè)計(jì)理念上的區(qū)別,其他方面無關(guā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è)問題是那些僅僅依賴于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語言不支持多重繼承,所以兩個(gè)概念都使用abstract class方式定義是不可行的。后面兩種方式都是可行的,但是對(duì)于它們的選擇卻反映出對(duì)于問題領(lǐng)域中的概念本質(zhì)的理解、對(duì)于設(shè)計(jì)意圖的反映是否正確、合理。我們一一來分析、說明。

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

            如果我們對(duì)于問題領(lǐng)域的理解是:AlarmDoor在概念本質(zhì)上是Door,同時(shí)它有具有報(bào)警的功能。我們?cè)撊绾蝸碓O(shè)計(jì)、實(shí)現(xiàn)來明確的反映出我們的意思呢?前面已經(jīng)說過,abstract class在Java語言中表示一種繼承關(guān)系,而繼承關(guān)系在本質(zhì)上是"is a"關(guān)系。所以對(duì)于Door這個(gè)概念,我們應(yīng)該使用abstarct class方式來定義。另外,AlarmDoor又具有報(bào)警功能,說明它又能夠完成報(bào)警概念中定義的行為,所以報(bào)警概念可以通過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ì)于問題領(lǐng)域的理解,正確的揭示我們的設(shè)計(jì)意圖。其實(shí)abstract class表示的是"is a"關(guān)系,interface表示的是"like a"關(guān)系,大家在選擇時(shí)可以作為一個(gè)依據(jù),當(dāng)然這是建立在對(duì)問題領(lǐng)域的理解上的,比如:如果我們認(rèn)為AlarmDoor在概念本質(zhì)上是報(bào)警器,同時(shí)又具有Door的功能,那么上述的定義方式就要反過來了。


            ==================游標(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ì)模式的研究。近來,隨著J2EE的成熟,它正在成為在J2EE平臺(tái)上推薦的一種設(shè)計(jì)模型,也是廣大Java開發(fā)者非常感興趣的設(shè)計(jì)模型。MVC模式也逐漸在PHP和ColdFusion開發(fā)者中運(yùn)用,并有增長(zhǎng)趨勢(shì)。隨著網(wǎng)絡(luò)應(yīng)用的快速增加,MVC模式對(duì)于Web應(yīng)用的開發(fā)無疑是一種非常先進(jìn)的設(shè)計(jì)思想,無論你選擇哪種語言,無論應(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)用來說,可以概括為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è)訂單的視圖只接受來自模型的數(shù)據(jù)并顯示給用戶,以及將用戶界面的輸入數(shù)據(jù)和請(qǐng)求傳遞給控制和模型。

            模型(Model):就是業(yè)務(wù)流程/狀態(tài)的處理以及業(yè)務(wù)規(guī)則的制定。業(yè)務(wù)流程的處理過程對(duì)其它層來說是黑箱操作,模型接受視圖請(qǐng)求的數(shù)據(jù),并返回最終的處理結(jié)果。業(yè)務(wù)模型的設(shè)計(jì)可以說是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è)開發(fā)者來說,就可以專注于業(yè)務(wù)模型的設(shè)計(jì)。MVC設(shè)計(jì)模式告訴我們,把應(yīng)用的模型按一定的規(guī)則抽取出來,抽取的層次很重要,這也是判斷開發(fā)人員是否優(yōu)秀的設(shè)計(jì)依據(jù)。抽象與具體不能隔得太遠(yuǎn),也不能太近。MVC并沒有提供模型的設(shè)計(jì)方法,而只告訴你應(yīng)該組織管理這些模型,以便于模型的重構(gòu)和提高重用性。我們可以用對(duì)象編程來做比喻,MVC定義了一個(gè)頂級(jí)類,告訴它的子類你只能做這些,但沒法限制你能做這些。這點(diǎn)對(duì)編程的開發(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)

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

            首先,最重要的是應(yīng)該有多個(gè)視圖對(duì)應(yīng)一個(gè)模型的能力。在目前用戶需求的快速變化下,可能有多種方式訪問應(yīng)用的要求。例如,訂單模型可能有本系統(tǒng)的訂單,也有網(wǎng)上訂單,或者其他系統(tǒng)的訂單,但對(duì)于訂單的處理都是一樣,也就是說訂單的處理是一致的。按MVC設(shè)計(jì)模式,一個(gè)訂單模型以及多個(gè)視圖即可解決問題。這樣減少了代碼的復(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)求,因此,控制層可以說是包含了用戶請(qǐng)求權(quán)限的概念。

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

            MVC的缺點(diǎn)

            MVC的設(shè)計(jì)實(shí)現(xiàn)并不十分容易, 理解起來比較容易,但對(duì)開發(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)用程序的輸入、處理和輸出分開。?


            ?·網(wǎng)絡(luò)上md5的java實(shí)現(xiàn).??? ?顯示摘要???? 摘要:無意間發(fā)現(xiàn)的.不過章章師兄研究的密碼學(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開發(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ì)模式帶來更好的軟件結(jié)構(gòu)和代碼重用
            mvc如何工作

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

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

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

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

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

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

            ? ?因?yàn)椴煌墓究赡軙?huì)開發(fā)出有相同名字的程序集來,如果這些程序集都被復(fù)制到同一 個(gè)相同的目錄下,最后一個(gè)安裝的程序集將會(huì)代替前面的程序集。這就是著名的Windows “DLL Hell”出現(xiàn)的原因。
            ??
            ? ?很明顯,簡(jiǎn)單的用文件名來區(qū)分程序集是不夠的,CLR需要支持某種機(jī)制來唯一的標(biāo)識(shí)一個(gè)程序集。這就是所謂的強(qiáng)命名程序集。
            ??
            ? ?一個(gè)強(qiáng)命名程序集包含四個(gè)唯一標(biāo)志程序集的特性:文件名(沒有擴(kuò)展名),版本號(hào),語言文化信息(如果有的話),公有秘鑰。
            ??
            ? ?這些信息存儲(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)建有著相同名稱,版本和語言文化信息的程序集,而不引起任何沖突。
            ??
            ? ?與強(qiáng)命名程序集對(duì)應(yīng)的就是所謂的弱命名程序集。(其實(shí)就是普通的沒有被強(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)說明在.net中常用的幾種頁面間傳遞參數(shù)的方法,并說出他們的優(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 頁面生命周期

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

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

            例:
            string gb_string;

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


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

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

            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;

            總結(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)該注意他的生命周期的問題.如果函數(shù)都在一個(gè)生命周期中,全局變量的值當(dāng)然是一致的.但是如果在"由客戶激發(fā)"的事件中,這就不同了,每個(gè)客戶事件的激發(fā),都會(huì)導(dǎo)致新的頁面生命周期的產(chǎn)生,全局變量的值會(huì)丟失,因?yàn)樗鼈儾辉谕豁撁嫔芷?就像上面出現(xiàn)的錯(cuò)誤1).


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

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

            方法 活動(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

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


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

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

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

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

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

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

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

            6. Page_
            預(yù)先呈遞對(duì)象,這里是在向用戶程序呈現(xiàn)數(shù)據(jù)的倒數(shù)第二步,我估計(jì)提供這個(gè)過程的意義,也就是在這里能對(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è)頁面都有一個(gè)隱藏的<input>,這里面的"__VIEWSTATE"就是我們服務(wù)器寫回來的頁面狀態(tài)信息,
            在這個(gè)之前,服務(wù)器要呈現(xiàn)頁面(也就是構(gòu)造HTML格式的文件),就是從這個(gè)"__VIEWSTATE"里面獲取的數(shù)據(jù),當(dāng)然大家也注意到了,這里有個(gè)Page.Render事件,我們可以添加自己的處理代碼,也就是說我們又可以更改數(shù)據(jù),不過這里推薦不要在這里修改,既然提供了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è)繼承頁面對(duì)象,也就是頁面的類,它繼承自System.Web.UI.Page.
            當(dāng)頁面對(duì)象從內(nèi)存中卸載時(shí)發(fā)生,將觸發(fā)該事件.

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

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

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

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

            注意上面灰色背景的文字,如果一個(gè)過程中有對(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è)沒有對(duì)應(yīng)事件的過程,比如2.Load ViewState,我們可以重載Page的虛函數(shù)protected override void LoadViewState(object savedState);來添加自己的控制代碼,不過切忌掉用基類的對(duì)應(yīng)方法,比如:
            protected override void LoadViewState(object savedState)
            {
            ? //自己處理VIEWSTATE
            ? base.LoadViewState (savedState);
            }

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

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

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

            階段

            頁面事件

            可重寫方法

            頁面初始化

            Init

            加載視圖狀態(tài)

            LoadViewState

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

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

            加載頁面

            Load

            回發(fā)更改通知

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

            處理回發(fā)事件

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

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

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

            PreRender

            保存視圖狀態(tài)

            SaveViewState

            呈現(xiàn)頁面

            Render

            卸載頁面

            Unload

            ?

            ?

            ?

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

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

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

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

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

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

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

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

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

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

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

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

            三.完成初始化(OnInitComplete)

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

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

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

            ?

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

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

            ?

            六.OnPreLoad

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

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

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

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

            ?

            八.RaisePostBackChanged事件(RaisePostDataChangedEvent)

            就像在上面提到的那樣,這個(gè)事件是發(fā)生在所有的控件執(zhí)行了IPostBackDataHandler接口操作并被正確的 postback數(shù)據(jù)更新后的。在這個(gè)過程中,每個(gè)控件都被賦予一個(gè)布爾值來標(biāo)志該控件有沒有被更新。然后,Asp.net就在整個(gè)頁面上尋找任何已被更 新過的控件并執(zhí)行RaisePostDataChanged事件操作。不過,這個(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)的處理代碼來體現(xiàn)事件驅(qū)動(dòng)這一面向?qū)ο螅∣OP)編程原則。由于要滿足呈現(xiàn)給瀏覽器的數(shù)據(jù)的精確性要求,在一系列 postback事件中RaisePostBackEvent事件是最后發(fā)生的。

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

            ?

            十.Page_OnLoadComplete

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

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

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

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

            在完成預(yù)呈現(xiàn)OnPreRender事件后觸發(fā)。這是完成頁面呈現(xiàn)的最后一道關(guān)卡,在此之后,頁面將無法再進(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ì)頁面控件的修改完成后viewstate就被保存了。對(duì)像的狀態(tài)數(shù)據(jù)還是保留在隱藏的<input> 控件里面,呈現(xiàn)給Html的對(duì)象狀態(tài)數(shù)據(jù)也是從這里取得的。在SaveViewState事件中,其值能被保存到viewstate對(duì)象,然而這時(shí)在頁面 上控件的修改卻不能了。你可以用SaveViewState來重載這一步,圖示如下:

            ?

            九.呈遞給Html(Render)

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

            ?

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

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

            全文總結(jié)

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

            方法 活動(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

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

            AspNet2.0頁面生命周期 ?

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

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

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

            03:預(yù)初始化(PreInit):
            ? 在頁面生命周期的預(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)用母版頁

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            21:呈現(xiàn):
            ? 在頁面生命周期的這個(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頁面的生命期單個(gè)用戶客戶端
            Cache任意大小可以根據(jù)需要設(shè)定所有用戶服務(wù)器端
            隱藏域小量,簡(jiǎn)單的數(shù)據(jù)一個(gè)Web頁面的生命期單個(gè)用戶客戶端
            查詢字符串小量,簡(jiǎn)單的數(shù)據(jù)直到下次頁面跳轉(zhuǎn)請(qǐng)求單個(gè)用戶客戶端
            Web.Config文件不變或極少改變的小量數(shù)據(jù)直到配置文件被更新單個(gè)用戶服務(wù)器端

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

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

            ? ?? ?? ?? Application["AllGuests"] =(int)Application["AllGuests"]+ 1;//訪問網(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ǎ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 = "正在訪問站點(diǎn)的用戶數(shù):" + Application["CurrentGuests"].ToString(); ? ?
            ? ? ?? ?? ? this.Label2.Text ="訪問過站點(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ù)器頁面的請(qǐng)求信息,程序員也可以用它存放非敏感性的用戶信息,信息保存的時(shí)間可以根據(jù)需要設(shè)置.如果沒有設(shè)置Cookie失效日期,它們僅保存到關(guān)閉瀏覽器程序?yàn)橹?如果將Cookie對(duì)象的Expires屬性設(shè)置為Minvalue,則表示Cookie永遠(yuǎn)不會(huì)過期.Cookie存儲(chǔ)的數(shù)據(jù)量很受限制,大多數(shù)瀏覽器支持最大容量為4096,因此不要用來保存數(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)信息,有效期等于頁面的生存期。ViewState容器可以保持大量的數(shù)據(jù),但是必須謹(jǐn)慎使用,因?yàn)檫^多使用會(huì)影響應(yīng)用程序的性能。所有Web服務(wù)器控件都使用ViewState在頁面回發(fā)期音保存自己的狀態(tài)信息。如果某個(gè)控件不需要在回發(fā)期間保存狀態(tài)信息,最好關(guān)閉該對(duì)象的ViewState,避免不必要的資源浪費(fèi)。通過給@Page指令添加“EnableViewState=false”屬性可以禁止整個(gè)頁面的ViewState。使用ViewState對(duì)象保存信息的代碼如下。
            ? //存放信息
            ? ViewState["nameID"]="0001";
            ? //讀取信息
            ? string NameID=ViewState["nameID"].ToString();
            5.Cache對(duì)象
            ? ?Cache對(duì)象用于在HTTP請(qǐng)求間保存頁面或數(shù)據(jù)。該對(duì)象的使用可以極大地提高整個(gè)應(yīng)用程序的效率。它允許將頻繁訪問的大量服務(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ù)器控件的使用沒有太大區(qū)別,只是它不會(huì)在用戶端的瀏覽器中顯示,始終處于隱藏狀態(tài)。但是每次頁面提交的時(shí)候,此控件和其它服務(wù)器控件一同提交到服務(wù)器端,因此在服務(wù)器端可以使用Value屬性獲取或保存一些數(shù)據(jù)信息。使用Hidden控件保存信息的代碼如下。
            ? //存放信息
            ? Hidden.Value="0001";
            ? //獲取信息
            ? string NameID=Hidden.Value; ?7.查詢字符串
            ? 查詢字符串的方式是將要傳遞的值連接在URL后面,然后通過Response.Redirect方法實(shí)現(xiàn)客戶端的重定向。這種方式可以實(shí)現(xiàn)在兩個(gè)頁面之間傳遞信息。由于URL的長(zhǎng)度有一定的限制,因此不能傳遞太大的信息,加外安全性也不是很好。
            ? 傳遞信息如下。
            ? Response.Redirect("List.aspx?nameID=0001&gradeID=002");
            ? //執(zhí)行上面的語句后在IE地址欄顯示的URL的代碼如下。
            ? http://localhost/List.aspx?nameID=0001&grade=002
            ? //當(dāng)跳轉(zhuǎn)到List.aspx后,可以通過以下代碼獲得所傳遞的信息。
            ? string NameID.GradeID;
            ? NameID=Request.Params["nameID"];
            ? GradeID=Request.Params["gradeID"];???

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

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

            viewstate/session/cache/application
            單頁級(jí)的自身狀態(tài)的保存建議用viewstate,??
            用戶級(jí)的重要的信息的保存建議用session(如每個(gè)用戶的狀態(tài))??
            用戶級(jí)的非重要性的信息的保存建議用cache??
            整個(gè)站級(jí)的狀態(tài)的保存建議用application.或用singleton模式的全局對(duì)象??
            cache和session的用法相同,不過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)站開發(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是一種比較好的使用方式,但是不要使用過大.比如在一個(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")??
            ? %>??
            ???
            ? 我在開發(fā)時(shí)只用1個(gè)session作為用戶的ID.


            Application

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

            2.???????? 在Asp時(shí)代,如果要保存的數(shù)據(jù)在應(yīng)用程序生存期內(nèi)不會(huì)或者很少發(fā)生改變,那么使用Application是理想的選擇。但是在Asp.net開發(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用來保存每一個(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用來保存客戶瀏覽器請(qǐng)求服務(wù)器頁面的請(qǐng)求信息

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

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

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

            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用來保存用戶的狀態(tài)信息,有效期等于頁面的生命周期

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

            3.???????? 所有的Web服務(wù)器控件都是用ViewState在頁面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)求期間保存頁面或者數(shù)據(jù)

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

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

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

            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ī)上無限期存在,這取決于客戶端的到期規(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)并使用它來訪問站點(diǎn)的用戶個(gè)性化結(jié)構(gòu)是足夠的了。

            4,Session存儲(chǔ)在會(huì)話狀態(tài)變量中的理想數(shù)據(jù)是特定于單獨(dú)的、短期的、敏感的數(shù)據(jù),應(yīng)該是安全的,但過多使用會(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)最常見的用途是與 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īng)用程序狀態(tài)中存儲(chǔ)信息可能意味著僅保留信息的一個(gè)副本(例如,相對(duì)于在會(huì)話狀態(tài)或在單獨(dú)頁中保存信息的多個(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)來存儲(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)中,則可以通過減少對(duì)數(shù)據(jù)庫(kù)的數(shù)據(jù)請(qǐng)求總數(shù)來提高站點(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ù)器資源來創(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ǔ)概念二十五問(轉(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 閱讀(10298) 評(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)論

            閱讀排行榜

            亚洲午夜精品久久久久久浪潮| 久久AV无码精品人妻糸列| 国产精品美女久久久久AV福利| 久久精品极品盛宴观看| 国产精品久久久久久久久久影院| 久久精品亚洲一区二区三区浴池| 久久水蜜桃亚洲av无码精品麻豆| 久久精品免费大片国产大片| 久久影院午夜理论片无码| 久久亚洲国产中v天仙www| www久久久天天com| 久久精品国产91久久麻豆自制| 三级片免费观看久久| 久久99精品综合国产首页| 久久久国产精品| 综合久久精品色| 一本色综合网久久| 亚洲午夜福利精品久久| 2021国产精品久久精品| 亚洲AV无码一区东京热久久| 久久久久这里只有精品 | 亚洲国产成人久久综合碰| 99国内精品久久久久久久 | 97精品伊人久久久大香线蕉 | 久久精品国产99国产精偷| 亚洲精品无码久久一线| 热久久这里只有精品| 狠狠色婷婷久久综合频道日韩| 亚洲午夜精品久久久久久人妖| 人妻无码久久精品| 品成人欧美大片久久国产欧美| 伊人久久国产免费观看视频| 亚洲精品乱码久久久久久中文字幕 | 伊人久久综合成人网| 精品久久久久久国产三级| 久久久久99精品成人片三人毛片 | 久久中文骚妇内射| 一本一道久久a久久精品综合 | 久久久亚洲裙底偷窥综合| 青青草国产精品久久久久| 亚洲熟妇无码另类久久久|