從語法定義層面看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).
*********************************************************
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ù)定的效果。
一個(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();
完成初始化頁面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事件了。
?
在加載頁面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來重載這一步,圖示如下: |
運(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事件,圖示如下: |
在呈遞給Html完成后,所有的對(duì)象都應(yīng)被銷毀。在Dispose事件中,你應(yīng)該銷毀所有在建立這個(gè)頁面時(shí)創(chuàng)建的對(duì)象。這時(shí),所有的處理已經(jīng)完畢,所以銷毀任何剩下的對(duì)象都是不會(huì)產(chǎn)生錯(cuò)誤的,包括頁面對(duì)象。你可以重載Dispose事件。 |
以上就是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)記文本。
我對(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
?