從語法定義層面看abstract class和interface
在語法層面,Java語言對于abstract class和interface給出了不同的定義方式,下面以定義一個名為Demo的抽象類為例來說明這種不同。
使用abstract class的方式定義Demo抽象類的方式如下:
abstract class Demo {
abstract void method1();
abstract void method2();
…
}
使用interface的方式定義Demo抽象類的方式如下:
interface Demo {
void method1();
void method2();
…
}
在abstract class方式中,Demo可以有自己的數據成員,也可以有非abstarct的成員方法,而在interface方式的實現中,Demo只能夠有靜態的不能被修改的數據成員(也就是必須是static final的,不過在interface中一般不定義數據成員),所有的成員方法都是abstract的。從某種意義上說,interface是一種特殊形式的abstract class。
從編程的角度來看,abstract class和interface都可以用來實現"design by contract"的思想。但是在具體的使用上面還是有一些區別的。
首先,abstract class在Java語言中表示的是一種繼承關系,一個類只能使用一次繼承關系。但是,一個類卻可以實現多個interface。也許,這是Java語言的設計者在考慮Java對于多重繼承的支持方面的一種折中考慮吧。
其次,在abstract class的定義中,我們可以賦予方法的默認行為。但是在interface的定義中,方法卻不能擁有默認行為,為了繞過這個限制,必須使用委托,但是這會 增加一些復雜性,有時會造成很大的麻煩。
在抽象類中不能定義默認行為還存在另一個比較嚴重的問題,那就是可能會造成維護上的麻煩。因為如果后來想修改類的界面(一般通過abstract class或者interface來表示)以適應新的情況(比如,添加新的方法或者給已用的方法中添加新的參數)時,就會非常的麻煩,可能要花費很多的時間(對于派生類很多的情況,尤為如此)。但是如果界面是通過abstract class來實現的,那么可能就只需要修改定義在abstract class中的默認行為就可以了。
同樣,如果不能在抽象類中定義默認行為,就會導致同樣的方法實現出現在該抽象類的每一個派生類中,違反了"one rule,one place"原則,造成代碼重復,同樣不利于以后的維護。因此,在abstract class和interface間進行選擇時要非常的小心。
從設計理念層面看abstract class和interface
上面主要從語法定義和編程的角度論述了abstract class和interface的區別,這些層面的區別是比較低層次的、非本質的。本小節將從另一個層面:abstract class和interface所反映出的設計理念,來分析一下二者的區別。作者認為,從這個層面進行分析才能理解二者概念的本質所在。
前面已經提到過,abstarct class在Java語言中體現了一種繼承關系,要想使得繼承關系合理,父類和派生類之間必須存在"is a"關系,即父類和派生類在概念本質上應該是相同的(參考文獻〔3〕中有關于"is a"關系的大篇幅深入的論述,有興趣的讀者可以參考)。對于interface 來說則不然,并不要求interface的實現者和interface定義在概念本質上是一致的,僅僅是實現了interface定義的契約而已。為了使論述便于理解,下面將通過一個簡單的實例進行說明。
考慮這樣一個例子,假設在我們的問題領域中有一個關于Door的抽象概念,該Door具有執行兩個動作open和close,此時我們可以通過abstract class或者interface來定義一個表示該抽象概念的類型,定義方式分別如下所示:
使用abstract class方式定義Door:
abstract class Door {
abstract void open();
abstract void close();
}
使用interface方式定義Door:
interface Door {
void open();
void close();
}
其他具體的Door類型可以extends使用abstract class方式定義的Door或者implements使用interface方式定義的Door。看起來好像使用abstract class和interface沒有大的區別。
如果現在要求Door還要具有報警的功能。我們該如何設計針對該例子的類結構呢(在本例中,主要是為了展示abstract class和interface反映在設計理念上的區別,其他方面無關的問題都做了簡化或者忽略)?下面將羅列出可能的解決方案,并從設計理念層面對這些不同的方案進行分析。
解決方案一:
簡單的在Door的定義中增加一個alarm方法,如下:
abstract class Door {
abstract void open();
abstract void close();
abstract void alarm();
}
或者
interface Door {
void open();
void close();
void alarm();
}
那么具有報警功能的AlarmDoor的定義方式如下:
class AlarmDoor extends Door {
void open() { … }
void close() { … }
void alarm() { … }
}
或者
class AlarmDoor implements Door {
void open() { … }
void close() { … }
void alarm() { … }
}
這種方法違反了面向對象設計中的一個核心原則ISP(Interface Segregation Priciple),在Door的定義中把Door概念本身固有的行為方法和另外一個概念"報警器"的行為方法混在了一起。這樣引起的一個問題是那些僅僅依賴于Door這個概念的模塊會因為"報警器"這個概念的改變(比如:修改alarm方法的參數)而改變,反之依然。
解決方案二:
既然open、close和alarm屬于兩個不同的概念,根據ISP原則應該把它們分別定義在代表這兩個概念的抽象類中。定義方式有:這兩個概念都使用abstract class方式定義;兩個概念都使用interface方式定義;一個概念使用abstract class方式定義,另一個概念使用interface方式定義。
顯然,由于Java語言不支持多重繼承,所以兩個概念都使用abstract class方式定義是不可行的。后面兩種方式都是可行的,但是對于它們的選擇卻反映出對于問題領域中的概念本質的理解、對于設計意圖的反映是否正確、合理。我們一一來分析、說明。
如果兩個概念都使用interface方式來定義,那么就反映出兩個問題:1、我們可能沒有理解清楚問題領域,AlarmDoor在概念本質上到底是Door還是報警器?2、如果我們對于問題領域的理解沒有問題,比如:我們通過對于問題領域的分析發現AlarmDoor在概念本質上和Door是一致的,那么我們在實現時就沒有能夠正確的揭示我們的設計意圖,因為在這兩個概念的定義上(均使用interface方式定義)反映不出上述含義。
如果我們對于問題領域的理解是:AlarmDoor在概念本質上是Door,同時它有具有報警的功能。我們該如何來設計、實現來明確的反映出我們的意思呢?前面已經說過,abstract class在Java語言中表示一種繼承關系,而繼承關系在本質上是"is a"關系。所以對于Door這個概念,我們應該使用abstarct class方式來定義。另外,AlarmDoor又具有報警功能,說明它又能夠完成報警概念中定義的行為,所以報警概念可以通過interface方式定義。如下所示:
abstract class Door {
abstract void open();
abstract void close();
}
interface Alarm {
void alarm();
}
class AlarmDoor extends Door implements Alarm {
void open() { … }
void close() { … }
void alarm() { … }
}
這種實現方式基本上能夠明確的反映出我們對于問題領域的理解,正確的揭示我們的設計意圖。其實abstract class表示的是"is a"關系,interface表示的是"like a"關系,大家在選擇時可以作為一個依據,當然這是建立在對問題領域的理解上的,比如:如果我們認為AlarmDoor在概念本質上是報警器,同時又具有Door的功能,那么上述的定義方式就要反過來了。
==================游標,可不可以嵌套,可以用什么辦法替換使用游標==================
For standard SQL, it is surely that cursors can be nested, just like LOOPs can be nested.
Below is an example written in PL/SQL:
Declare
?? Cursor_H IS CURSOR AS SELECT * FROM customer_header;
?? Cursor_L (p_cust_id) IS CURSOR AS SELECT * FROM customer_detail WHERE customer_id = p_cust_id;
Begin
?? For H in Cursor_H
?? Loop
???????? Print customer_header;
???????? For L in Cursor_L (H.customer_id)
???????? Loop
??????????????? Print_customer_detail;
???????? End loop;
?? End loop;
End;
In PL/SQL, you can use Direct-Loop instead of cursor;
For example:
Begin
?? For H in (SELECT * FROM customer_header)?????? -- instead of Cursor_H
?? Loop
???????? Print customer_header;
???????? For L in (SELECT * FROM customer_detail WHERE customer_id = H.customer_id)????? -- instead of Cursor_L
???????? Loop
??????????????? Print_customer_detail;
???????? End loop;
?? End loop;
End;
=======================
MVC是一種目前廣泛流行的軟件設計模式,早在70年代,IBM就推出了Sanfronscisico項目計劃,其實就是MVC設計模式的研究。近來,隨著J2EE的成熟,它正在成為在J2EE平臺上推薦的一種設計模型,也是廣大Java開發者非常感興趣的設計模型。MVC模式也逐漸在PHP和ColdFusion開發者中運用,并有增長趨勢。隨著網絡應用的快速增加,MVC模式對于Web應用的開發無疑是一種非常先進的設計思想,無論你選擇哪種語言,無論應用多復雜,它都能為你理解分析應用模型時提供最基本的分析方法,為你構造產品提供清晰的設計框架,為你的軟件工程提供規范的依據。
MVC設計思想
MVC英文即Model-View-Controller,即把一個應用的輸入、處理、輸出流程按照Model、View、Controller的方式進行分離,這樣一個應用被分成三個層——模型層、視圖層、控制層。
視圖(View)代表用戶交互界面,對于Web應用來說,可以概括為HTML界面,但有可能為XHTML、XML和Applet。隨著應用的復雜性和規模性,界面的處理也變得具有挑戰性。一個應用可能有很多不同的視圖,MVC設計模式對于視圖的處理僅限于視圖上數據的采集和處理,以及用戶的請求,而不包括在視圖上的業務流程的處理。業務流程的處理交予模型(Model)處理。比如一個訂單的視圖只接受來自模型的數據并顯示給用戶,以及將用戶界面的輸入數據和請求傳遞給控制和模型。
模型(Model):就是業務流程/狀態的處理以及業務規則的制定。業務流程的處理過程對其它層來說是黑箱操作,模型接受視圖請求的數據,并返回最終的處理結果。業務模型的設計可以說是MVC最主要的核心。目前流行的EJB模型就是一個典型的應用例子,它從應用技術實現的角度對模型做了進一步的劃分,以便充分利用現有的組件,但它不能作為應用設計模型的框架。它僅僅告訴你按這種模型設計就可以利用某些技術組件,從而減少了技術上的困難。對一個開發者來說,就可以專注于業務模型的設計。MVC設計模式告訴我們,把應用的模型按一定的規則抽取出來,抽取的層次很重要,這也是判斷開發人員是否優秀的設計依據。抽象與具體不能隔得太遠,也不能太近。MVC并沒有提供模型的設計方法,而只告訴你應該組織管理這些模型,以便于模型的重構和提高重用性。我們可以用對象編程來做比喻,MVC定義了一個頂級類,告訴它的子類你只能做這些,但沒法限制你能做這些。這點對編程的開發人員非常重要。
業務模型還有一個很重要的模型那就是數據模型。數據模型主要指實體對象的數據保存(持續化)。比如將一張訂單保存到數據庫,從數據庫獲取訂單。我們可以將這個模型單獨列出,所有有關數據庫的操作只限制在該模型中。
控制(Controller)可以理解為從用戶接收請求, 將模型與視圖匹配在一起,共同完成用戶的請求。劃分控制層的作用也很明顯,它清楚地告訴你,它就是一個分發器,選擇什么樣的模型,選擇什么樣的視圖,可以完成什么樣的用戶請求。控制層并不做任何的數據處理。例如,用戶點擊一個連接,控制層接受請求后, 并不處理業務信息,它只把用戶的信息傳遞給模型,告訴模型做什么,選擇符合要求的視圖返回給用戶。因此,一個模型可能對應多個視圖,一個視圖可能對應多個模型。
MVC的優點
大部分用過程語言比如ASP、PHP開發出來的Web應用,初始的開發模板就是混合層的數據編程。例如,直接向數據庫發送請求并用HTML顯示,開發速度往往比較快,但由于數據頁面的分離不是很直接,因而很難體現出業務模型的樣子或者模型的重用性。產品設計彈性力度很小,很難滿足用戶的變化性需求。MVC要求對應用分層,雖然要花費額外的工作,但產品的結構清晰,產品的應用通過模型可以得到更好地體現。
首先,最重要的是應該有多個視圖對應一個模型的能力。在目前用戶需求的快速變化下,可能有多種方式訪問應用的要求。例如,訂單模型可能有本系統的訂單,也有網上訂單,或者其他系統的訂單,但對于訂單的處理都是一樣,也就是說訂單的處理是一致的。按MVC設計模式,一個訂單模型以及多個視圖即可解決問題。這樣減少了代碼的復制,即減少了代碼的維護量,一旦模型發生改變,也易于維護。
MVC設計模型
其次,由于模型返回的數據不帶任何顯示格式,因而這些模型也可直接應用于接口的使用。
再次,由于一個應用被分離為三層,因此有時改變其中的一層就能滿足應用的改變。一個應用的業務流程或者業務規則的改變只需改動MVC的模型層。
控制層的概念也很有效,由于它把不同的模型和不同的視圖組合在一起完成不同的請求,因此,控制層可以說是包含了用戶請求權限的概念。
最后,它還有利于軟件工程化管理。由于不同的層各司其職,每一層不同的應用具有某些相同的特征,有利于通過工程化、工具化產生管理程序代碼。
MVC的缺點
MVC的設計實現并不十分容易, 理解起來比較容易,但對開發人員的要求比較高。MVC只是一種基本的設計思想,還需要詳細的設計規劃。
模型和視圖的嚴格分離可能使得調試困難一些,但比較容易發現錯誤。
經驗表明,MVC由于將應用分為三層,意味著代碼文件增多,因此,對于文件的管理需要費點心思。
綜合上述,MVC是構筑軟件非常好的基本模式,至少將業務處理與顯示分離,強迫將應用分為模型、視圖以及控制層, 使得你會認真考慮應用的額外復雜性,把這些想法融進到架構中,增加了應用的可拓展性。如果能把握到這一點,MVC模式會使得你的應用更加強壯,更加有彈性,更加個性化。
??? 引言: MVC如何工作 MVC是一個設計模式,它強制性的使應用程序的輸入、處理和輸出分開。?
?·網絡上md5的java實現.??? ?顯示摘要???? 摘要:無意間發現的.不過章章師兄研究的密碼學里md5好象已經用c++實現了.package com.sinosoftgroup.msd.util; /** * * <p>title: </p> * <p>description: </p> * <p>copyright: copyright (c) 2003</p> * <p...... ·jie server開發指南??? ?顯示摘要???? 摘要: 一個簡單的action,返回hello world package org.jie.demo; import org.jie.server.action.standardaction;import javax.servlet.http.httpservletrequest; class testaction extends standardaction { publi......
MVC設計模式帶來更好的軟件結構和代碼重用
mvc如何工作
mvc是一個設計模式,它強制性的使應用程序的輸入.處理與輸出分開.使用mvc應用程序被分成三個核心部件:模型.視圖.控制器.它們各自處理自己的任務.
如何處理應用程序的界面變得越來越有挑戰性.mvc一個大的好處是它能為你的應用程序處理很多不同的視圖.在視圖中其實沒有真正的處理發生,不管這些數據是聯機存儲的還是一個雇員列表,作為視圖來講,它只是作為一種輸出數據并允許用戶操縱的方式. 【程序編程相關:Hibernate middlegen中】
視圖
視圖是用戶看到并與之交互的界面.對老式的web應用程序來說,視圖就是由html元素組成的界面,在新式的web應用程序中,html依舊在視圖中扮演著重要的角色,但一些新的技術已層出不窮,它們包括macromedia flash與象xhtml,xml/xsl,wml等一些標識語言與web services. 【推薦閱讀:JAVA文件加密器(收藏)】
控制器
控制器接受用戶的輸入并調用模型與視圖去完成用戶的需求.所以當單擊web頁面中的超鏈接與發送html表單時,控制器本身不輸出任何東西與做任何處理.它只是接收請求并決定調用哪個模型構件去處理請求,然后用確定用哪個視圖來顯示模型處理返回的數據. 【擴展信息:CruiseControl簡介】
模型
模型表示企業數據與業務規則.在mvc的三個部件中,模型擁有最多的處理任務.例如它可能用象ejbs與coldfusion components這樣的構件對象來處理數據庫.被模型返回的數據是中立的,就是說模型與數據格式無關,這樣一個模型能為多個視圖提供數據.由于應用于模型的代碼只需寫一次就可以被多個視圖重用,所以減少了代碼的重復性
-----------------
強命名程序集(Strong Name Assembly)的概念
? ?因為不同的公司可能會開發出有相同名字的程序集來,如果這些程序集都被復制到同一 個相同的目錄下,最后一個安裝的程序集將會代替前面的程序集。這就是著名的Windows “DLL Hell”出現的原因。
??
? ?很明顯,簡單的用文件名來區分程序集是不夠的,CLR需要支持某種機制來唯一的標識一個程序集。這就是所謂的強命名程序集。
??
? ?一個強命名程序集包含四個唯一標志程序集的特性:文件名(沒有擴展名),版本號,語言文化信息(如果有的話),公有秘鑰。
??
? ?這些信息存儲在程序集的清單(manifest)中。清單包含了程序集的元數據,并嵌入在程序集的某個文件中。
??
? ?下面的字符串標識了四個不同的程序集文件:
??
? ?“MyType, Version=1.0.1.0,
? ?Culture=neutral, PublicKeyToken=bf5779af662fc055”
??
? ?“MyType, Version=1.0.1.0,
? ?Culture=en-us, PublicKeyToken=bf5779af662fc055”
??
? ?“MyType, Version=1.0.2.0,
? ?Culture=neturl, PublicKeyToken=bf5779af662fc055”
??
? ?“MyType, Version=1.0.2.0,
? ?Culture=neutral, PublicKeyToken=dbe4120289f9fd8a”
??
? ?如果一個公司想唯一的標識它的程序集,那么它必須首先獲取一個公鑰/私鑰對,然后將共有秘鑰和程序集相關聯。不存在兩個兩個公司有同樣的公鑰/私鑰對的情況,正是這種區分使得我們可以創建有著相同名稱,版本和語言文化信息的程序集,而不引起任何沖突。
??
? ?與強命名程序集對應的就是所謂的弱命名程序集。(其實就是普通的沒有被強命名的程序集)。兩種程序集在結構上是相同的。都使用相同的PE文件格式,PE表頭,CLR表頭,元數據,以及清單(manifest)。二者之間真正的區別在于:強命名程序集有一個發布者的公鑰/私鑰對簽名,其中的公鑰/私鑰對唯一的標識了程序集的發布者。利用公鑰/私鑰對,我們可以對程序集進行唯一性識別、實施安全策略和版本控制策略,這種唯一標識程序集的能力使得應用程序在試圖綁定一個強命名程序集時,CLR能夠實施某些“已確知安全”的策略(比如只信任某個公司的程序集)。
請說明在.net中常用的幾種頁面間傳遞參數的方法,并說出他們的優缺點。
session(viewstate) 簡單,但易丟失
application 全局
cookie 簡單,但可能不支持,可能被偽造
input type="hidden" 簡單,可能被偽造
url參數 簡單,顯示于地址欄,長度有限
數據庫 穩定,安全,但性能相對弱
===============================asp.net 頁面生命周期
錯誤:
??? 每個頁面的生命周期為用戶的訪問開始到結束,也就是說程序中的全局變量同時生存到用戶的訪問結束.
正確:
??? 每個頁面的生命周期為用戶的每一次訪問,也就是說每一次客戶端與服務器之間的一個往返過程.全局變量的生命周期在此之間.
例:
string gb_string;
void Page_Load()
{
??? if(!IsPostBack)
??? {
????? //第一次被訪問的代碼
????? gb_string ="Test!";???
??? }
}
void btnSubmit_Click(Object sender, EventArgs e)
{
//在這里gb_string 為空,是這一次postback新建的字符串
//跟第一次那個被賦值的字符串不是同一對象.
}
ASP.NET 頁面生命周期
1. Page_Init();
2. Load ViewState and Postback data;
3. Page_Load();
4. Handle control events;
5. Page_PreRender();
6. Page_Render();
7. Unload event;
8. Dispose method called;
總結:
在Page_Load()中執行的初始化工作
???? 1.一般都是初始化web控件,因為這些控件的狀態(值),由系統自動保存(__VIEWSTATE),
下次返回時,自動賦值,這是ASP.NET保存"web控件"狀態的特性.
??
?? 2.但是初始的如果是程序中用到的全局變量,就應該注意他的生命周期的問題.如果函數都在一個生命周期中,全局變量的值當然是一致的.但是如果在"由客戶激發"的事件中,這就不同了,每個客戶事件的激發,都會導致新的頁面生命周期的產生,全局變量的值會丟失,因為它們不在同一頁面生命周期(就像上面出現的錯誤1).
*********************************************************
Constructor
|
Always
|
Construct
|
Always
|
TestDeviceFilter
|
Always
|
AddParsedSubObject
|
Always
|
DeterminePostBackMode
|
Always
|
OnPreInit
|
Always
|
LoadPersonalizationData
|
Always
|
InitializeThemes
|
Always
|
OnInit
|
Always
|
ApplyControlSkin
|
Always
|
ApplyPersonalization
|
Always
|
OnInitComplete
|
Always
|
LoadPageStateFromPersistenceMedium
|
Always
|
LoadControlState
|
Always
|
LoadViewState
|
Always
|
ProcessPostData1
|
Always
|
OnPreLoad
|
Always
|
OnLoad
|
Always
|
ProcessPostData2
|
Always
|
RaiseChangedEvents
|
Always
|
RaisePostBackEvent
|
Always
|
OnLoadComplete
|
Always
|
OnPreRender
|
Always
|
OnPreRenderComplete
|
Always
|
SavePersonalizationData
|
Always
|
SaveControlState
|
Always
|
SaveViewState
|
Always
|
SavePageStateToPersistenceMedium
|
Always
|
Render
|
Always
|
OnUnload
|
Always
|
查看頁面生命周期的底層細節,我們可以看到 ASP.NET 2.0 中提供的許多功能(例如主題和個性化)將在什么地方容易實現。例如,主題在 IntializeThemes 事件中處理,而個性化數據將在 LoadPersonalizationData 中加載并稍后用于 ApplyPersonalization 方法。請注意,就哪一個 UI 元素將決定 Web 應用程序的最終外觀和感覺而言,方法的順序非常重要。
在以前寫個一篇關于ASP.NET頁面生命周期的草稿,最近又看了看ASP.NET,做個補充,看看頁面初始過程到底是怎么樣的
下面是ASP.NET頁面初始的過程:
1. Page_Init();
2. Load ViewState;
3. Load Postback data;
4. Page_Load();
5. Handle control events;
6. Page_PreRender();
7. Page_Render();
8. Unload event;
9. Dispose method called;
下面對其中的一些過程作下描述:
1. Page_Init();
這個過程主要是初始化控件,每次頁面載入執行這個初始過程,包括第一次和以后的Postback(這里說下Postback,其實就可以簡單理解成用戶點
擊SUBMIT按鈕之類的,把表單<Form>提交給服務器,這就是一次postback),在這里面可以訪問控件,但是這里面的控件值不是我們期待的控件里面
的值,他只是一個控件的初始值(默認值),舉例: 比如一個TextBox1,我們填入了"哈哈",在點擊SUBMIT提交了頁面后,在Page_Init()里面,我們訪
問到的TextBox1.Text不是我們的"哈哈",而是開始的""空字符串,如果TextBox1在我們設計的時候提供了默認值,這里訪問到的也就是提供的默
認值,為什么呢,這就要看下一個過程了.
對應的事件Page.Init
2. Load ViewState
這個過程是載入VIEWSTATE和Postback數據,比如我們上面的TextBox1,這時就賦了"哈哈",所以,在Post_Init()對控件賦值是無意義的,它都會
在這個過程里被改寫,當然第一次頁面載入例外,因為沒有VIEWSTATE數據。
沒有對應的事件
3.Load Postback data;
上面說了,Postback可以理解成用戶提交表單數據,所以這里就是處理表單數據,當然這里要設計到控件的設計,一般情況不會要我們自己處理這
個過程,我們暫且略過. (在以前那篇關于ASP.NET頁面生命周期的簡單描述中,把這個過程和Load ViewState放在了一起,其實那是微軟提供的生命周期過程,這里單獨提出來是為
了讓大家明白這是一個單獨的過程)
?
沒有對應的事件
4. Page_Load();
這個過程也是每次頁面載入時一定會執行的,但是注意和Page_Init的區別,上面已經涉及了,這里注意的是一般都會用到Page.IsPostBack,該
值指示該頁是否正為響應客戶端回發而加載,或者它是否正被首次加載和訪問。
private void Page_Load(object sender, System.EventArgs e)
{
? if(!Page.IsPostBack)
? {
???//第一次執行的CODE HERE
? }
? else
? {
??? //用戶提交FORM(即Postback)CODE HERE
? }
? //每次這里的都回執行CODE HERE
}
對應的事件Page.Load
5. Handle control events;
這個過程里,相應具體的控件事件,比如private void ListBox1_SelectedIndexChanged(object sender, System.EventArgs e)事件等等
沒有對應的事件(我們自己的事件函數都包括在這個過程里比如上面的ListBox1_SelectedIndexChanged)
6. Page_
預先呈遞對象,這里是在向用戶程序呈現數據的倒數第二步,我估計提供這個過程的意義,也就是在這里能對控件屬性等等要呈現給用戶的數據進
行修改,這也是最后的修改,以前的修改(比如在Page_Init里面)都可能被覆蓋.做完這了還會進行一個操作就是保存狀態,即SaveViewState.
對應的事件時Page.PreRender
7. Page_Render();
大家可以在瀏纜器里View->Source查看到,每個頁面都有一個隱藏的<input>,這里面的"__VIEWSTATE"就是我們服務器寫回來的頁面狀態信息,
在這個之前,服務器要呈現頁面(也就是構造HTML格式的文件),就是從這個"__VIEWSTATE"里面獲取的數據,當然大家也注意到了,這里有個Page.Render事件,我們可以添加自己的處理代碼,也就是說我們又可以更改數據,不過這里推薦不要在這里修改,既然提供了PreRender,就應該在里面做最后的修改,當然這不是必須的,只是推薦!
對應的事件Page.Render
8. Unload event;
大家應該明白,當想服務器請求一個對象的時候,就會在內存里生成一個繼承頁面對象,也就是頁面的類,它繼承自System.Web.UI.Page.
當頁面對象從內存中卸載時發生,將觸發該事件.
對應的事件Page.Unload
9. Dispose method called;
銷毀所有的對象.當從內存釋放Page時發生,這是生存期的最后階段。可能第8和9似乎有些模糊,不過我也沒怎么搞清楚,待研究!
對應的事件Dispose
以上就是ASP.NET頁面周期的描述。
注意上面灰色背景的文字,如果一個過程中有對應的事件,我們可以自己定義一個函數(當然先在MSDN中找到函數原型),然后在
InitializeComponent中向事件的鏈表上添加上去,像下面:
private void InitializeComponent()
{???
? this.Unload += new System.EventHandler(this.MainWebForm_Unload);
? this.Load += new System.EventHandler(this.Page_Load);
? this.Init += new System.EventHandler(this.Page_Init);
? this.PreRender += new System.EventHandler(this.My_PreRender);
}
對于幾個沒有對應事件的過程,比如2.Load ViewState,我們可以重載Page的虛函數protected override void LoadViewState(object
savedState);來添加自己的控制代碼,不過切忌掉用基類的對應方法,比如:
protected override void LoadViewState(object savedState)
{
? //自己處理VIEWSTATE
? base.LoadViewState (savedState);
}
初學ASP.NET,請各位不吝賜教!???
====================\
Asp.net2.0頁面的生命周期
表格 1. ASP.NET 頁面生存周期中的關鍵事件
階段
|
頁面事件
|
可重寫方法
|
頁面初始化
|
Init
|
|
加載視圖狀態
|
|
LoadViewState
|
處理回發數據
|
|
實現 IPostBackDataHandler 接口的任何控件中的 LoadPostData 方法
|
加載頁面
|
Load
|
|
回發更改通知
|
|
實現 IPostBackDataHandler 接口的任何控件中的 RaisePostDataChangedEvent 方法
|
處理回發事件
|
控件所定義的任何回發事件
|
實現了 IPostBackEventHandler 接口的任何控件的 RaisePostBackEvent 方法
|
頁面呈現前階段
|
PreRender
|
|
保存視圖狀態
|
|
SaveViewState
|
呈現頁面
|
|
Render
|
卸載頁面
|
Unload
|
?
?
?
當一個獲取網頁的請求(可能是通過用戶提交完成的,也可能是通過超鏈接完成的)被發送到Web服務器后,這個頁面就會接著運行從創建到處理完成的一系列事件。在我們試圖建立Asp.net頁面的時候,這個執行周期是不必去考慮的,那樣只會自討苦吃。然而,如果被正確的操縱,一個頁面的執行周期將是一道有效而且功能強大的工具。許多開發者在編寫 Asp.net的頁面以及用戶控件的時候發現,如果知道整個過程中發生了什么以及在什么時候發生將對完成整個任務起到很重要的幫助作用。下面我就向大家介紹一下一個Asp.net頁面從創建到處理完成過程中的十個事件。同時,也向大家展示如何在這些事件中添加自己的代碼以達到預定的效果。
一個頁面的控件(以及頁面本身)最初應被正確的初始化。通過在你的C#文件的構造函數 中聲名所有對象,頁面就知道要創建多少對象以及它們的類型。一旦你在你的構造函數中聲名了所有的對象,你就可以通過繼承類、方法、事件或是屬性訪問它們。 然而,如果你的一些對象是在Aspx文件中指定的一些控件,那么這些控件就沒有屬性可言了。同時,通過代碼訪問它們會產生一些意外的錯誤,因為這些控件實 例是沒有一個確定的創建順序的(如果它們是被一起創建的)。還有,你可以通過OnInit來重載初始化事件.
|
在這個事件里,我們能讀出控件的屬性(在設計模式中設置的)。但是我們不能讀出用戶設置的值,因為得到用戶設置的值是在LoadPostData()事件被激發之后。不過在這個事件中我們可以得到POST數據,如下
string
?selectedValue?
=
?Request.Form[controlID].ToString();
完成初始化頁面OnInit事件后觸發。 ?
|
四.導入Viewstate數據(LoadViewState)
|
在初始化事件后,所有控件只可以通過它們的ID被引用訪問(因為還沒有相應的DOM可使用)。在 LoadViewState這個事件中,所有的控件將獲得它們的第一個屬性:Viewstate屬性。這個屬性最終將被返回給服務器以判斷這個頁面是已經 被用戶訪問完畢還是仍然在被用戶所訪問。Viewstate屬性以“名稱/值”對的字符串方式被保存,它包含了控件的文本以及值等信息。該屬性被存儲在一 個隱藏的<input>控件的值屬性里,在請求頁面時被傳遞。這種方式比起Asp3.0的維持、判斷頁面狀態的方式有了很大的進步啊。還有, 你可以重載LoadViewState事件函數來對相應的控件進行值設定。下圖是一個例子: |
五.用LoadPostData處理Postback數據(LoadPostData)
|
在頁面創建的這個階段,服務器對頁面上的控件提交的表單數據(在Asp.net中稱postback數據)進行處理。當一個頁面提交一個表單時,框 架就在每個提交了數據的控件上執行一個IPostBackDataHandler接口操作。然后頁面執行LoadPostData事件,解析頁面,找到每 個執行了IpostBackDataHandler接口操作的控件,并用恰當的postback數據更新這些控件狀態。Asp.net是通過用 NameValue集中的“名稱/值”對和每個控件的唯一的ID匹配來實現這一操作的。所以,在Asp.net的頁面上每個控件必須有一個唯一的ID,不 可以出現幾個控件共有ID的情況。即使是用戶自定義的一些控件,框架也會賦予它們各自唯一的ID的。在LoadPostData事件后,就要執行下面的 RaisePostDataChanged事件了。
?
在加載頁面OnLoad事件前觸發。可以在頁面里面通過Page_OnPreLoad事件綁定 |
七.導入對象(OnLoad)
Page_Load是事件綁定得方法 ? ? page.load ? + ? = ? new ? eventhandler(Page_Load)??? OnLoad()是引發Load事件主要是判斷事件是否為空,如果不為空就執行事件下綁定得方法
|
在Load事件中,對象都實例化了。所有的對象第一次被布置在DOM頁面(在Asp.net中稱控件樹)里了并且可以通 過代碼或是相關的位置被引用。這樣,對象就可以很容易的從客戶端獲得諸如寬度、高度、值、可見性等在Html中的屬性值。在Load事件中,當然還有像設 置控件屬性等操作的發生。這個過程是整個生命周期中最重要、最主要的,你可以通過調用OnLoad來重載Load事件,圖示如下: |
八.RaisePostBackChanged事件(RaisePostDataChangedEvent)
|
就像在上面提到的那樣,這個事件是發生在所有的控件執行了IPostBackDataHandler接口操作并被正確的 postback數據更新后的。在這個過程中,每個控件都被賦予一個布爾值來標志該控件有沒有被更新。然后,Asp.net就在整個頁面上尋找任何已被更 新過的控件并執行RaisePostDataChanged事件操作。不過,這個事件是要在所有的控件都被更新了以及Load事件完成后才進行的。這樣就 保證了一個控件在被postback數據更新前,別的控件在RaisePostDataChanged事件中是不會被手動改變的。 |
九.處理客戶端PostBack事件(RaisePostBackEvent)
|
當由postback數據在服務器端引起的事件都完成后,產生postback數據的對象就執行 RaisePostBackEvent事件操作。可是會有這種情況,由于一個控件狀態的改變使得它將表單返回給服務器或是用戶點擊了提交按鈕使得表單返回 給服務器。在這種情況下應該有相應的處理代碼來體現事件驅動這一面向對象(OOP)編程原則。由于要滿足呈現給瀏覽器的數據的精確性要求,在一系列 postback事件中RaisePostBackEvent事件是最后發生的。 |
在postback過程中改變的控件不應在執行功能函數被調用后更新。也就是說,任何由于一個預期的事件而改變的數據應該在最終的頁面上被反映出來。你可以通過修改RaisePostBackEvent函數來滿足你的要求,圖示如下: |
十.Page_OnLoadComplete
完成頁面加載OnLoad事件后觸發。
十一.預先呈遞對象
|
可以改變對象并將改變保存的最后時刻就是這一步――預先呈遞對象。這樣,你可以在這一步對控件的屬性、控件樹結構等作出最后的修改。同時還不用考慮 Asp.net對其作出任何改變,因為此時已經脫離了數據庫調用以及viewstate更新了。在這一步之后,對對象的所有修改將最終被確定,不能被保存 到頁面的viewstate中了。你可以通過OnPreRender來重載這一步。
十二.完成預呈現(OnPreRenderComplete)
在完成預呈現OnPreRender事件后觸發。這是完成頁面呈現的最后一道關卡,在此之后,頁面將無法再進行任何呈現上的改動。
十三.保存ControlState(SaveControlState) ? 保 存控件狀態ControlState。ControlState是ASP.NET2.0控件新增的一個屬性,類似ViewState作用,但它們區別在于 ControlState用于保存更加重要的控件狀態信息,以保證在禁用ViewState的情況下還可以對控件狀態進行讀寫操作。
|
八.保存ViewState(SaveViewState)
|
所有對頁面控件的修改完成后viewstate就被保存了。對像的狀態數據還是保留在隱藏的<input> 控件里面,呈現給Html的對象狀態數據也是從這里取得的。在SaveViewState事件中,其值能被保存到viewstate對象,然而這時在頁面 上控件的修改卻不能了。你可以用SaveViewState來重載這一步,圖示如下: |
運用Html創建給瀏覽器輸出的頁面的時候Render事件就發生了。在Render事件過程中,頁面調用其中的對象將 它們呈遞給Html。然后,頁面就可以以Html的形式被用戶的瀏覽器訪問了。當Render事件被重載時,開發者可以編寫自定義的Html代碼使得原先 生成的Html都無效而按照新的Html來組織頁面。Render方法將一個HtmlTextWriter對象作為參數并用它將Html在瀏覽器上以網頁 的形式顯示。這時仍然可以做一些修改動作,不過它們只是客戶端的一些變化而已了。你可以重載Render事件,圖示如下: |
在呈遞給Html完成后,所有的對象都應被銷毀。在Dispose事件中,你應該銷毀所有在建立這個頁面時創建的對象。這時,所有的處理已經完畢,所以銷毀任何剩下的對象都是不會產生錯誤的,包括頁面對象。你可以重載Dispose事件。 |
以上就是Asp.net頁面生命周期中的幾個主要事件。每次我們請求一個Asp.net頁面時,我們都經歷著同樣的過程:從初始化對象到銷毀對象。 通過了解Asp.net頁面的內部運行機制,我相信大家在編寫、調試代碼的時候會更加游刃有余的。不過整個頁面的生命周期的方法如下:
方法
|
活動
|
Constructor
|
Always
|
Construct
|
Always
|
TestDeviceFilter
|
Always
|
AddParsedSubObject
|
Always
|
DeterminePostBackMode
|
Always
|
OnPreInit
|
Always
|
LoadPersonalizationData
|
Always
|
InitializeThemes
|
Always
|
OnInit
|
Always
|
ApplyControlSkin
|
Always
|
ApplyPersonalization
|
Always
|
OnInitComplete
|
Always
|
LoadPageStateFromPersistenceMedium
|
Always
|
LoadControlState
|
Always
|
LoadViewState
|
Always
|
ProcessPostData1
|
Always
|
OnPreLoad
|
Always
|
OnLoad
|
Always
|
ProcessPostData2
|
Always
|
RaiseChangedEvents
|
Always
|
RaisePostBackEvent
|
Always
|
OnLoadComplete
|
Always
|
OnPreRender
|
Always
|
OnPreRenderComplete
|
Always
|
SavePersonalizationData
|
Always
|
SaveControlState
|
Always
|
SaveViewState
|
Always
|
SavePageStateToPersistenceMedium
|
Always
|
Render
|
Always
|
OnUnload
|
Always
|
查看頁面生命周期的底層細節,我們可以看到 ASP.NET 2.0 中提供的許多功能(例如主題和個性化)將在什么地方容易實現。例如,主題在 IntializeThemes 事件中處理,而個性化數據將在 LoadPersonalizationData 中加載并稍后用于 ApplyPersonalization 方法。請注意,就哪一個 UI 元素將決定 Web 應用程序的最終外觀和感覺而言,方法的順序非常重要。
AspNet2.0頁面生命周期
?
|
頁面框架通過如下過程處理aspx文件請求:
??? 1:解析aspx文件,并創建一個控件樹;
??? 2:使用控件樹動態實現一個繼承自Page類的類或者控件 ;
??? 3:動態編譯類;
??? 4:緩存編譯類,以備后用;
??? 5:動態創建一個編譯類的實例。頁面開始啟動生命期,在這個過程中,頁面將通過生命周期的不同階段;=========================================================
頁面經歷了如下階段【其中一些階段標記為僅僅回傳,是說只有在被回傳到服務器時,頁面才經歷這些階段】:
01:頁面首先從QueryString或者Request對象的Form集合中獲得回傳數據。
02:頁面檢測回傳數據集合(NameValueCollection,Form或者QueryString)是否包含一個鍵為_CallBackId的項。如? 果存在,那么設置其Boolean屬性IsCallBack為True,以便通過AspNet客戶端回調機制,標明頁面已經回傳到服務器。
03:預初始化(PreInit):
? 在頁面生命周期的預初始化階段執行如下操作:
?? a:調用OnPreInit方法引發PreInit事件。
?? b:利用App_Themes目錄中的內容初始化主題,以動態實現一個PageTheme類型的類,
??? 編譯該類,并創建一個編譯類的實例,接著將實例賦值給它的PageTheme屬性值
?? c:應用母版頁
04:初始化(Init):
? 在頁面生命周期的初始化階段執行以下操作
?? a:遞歸初始化Controls集合中的控件。初始化包括設置這些控件的屬性,
??? 例如:Page,Id和NameContainer等
?? b:遞歸應用控件皮膚
?? c:調用OnInit方法以引發自身的Init事件,接著遞歸調用子控件的OnInit方法來引發它們的Init事件
?? d:調用自身的TrackViewState方法來啟動自身的視圖狀態跟蹤,接著遞歸調用子控件
??? 的TrackViewState方法來啟動它們的視圖狀態跟蹤。
05:完成初始化(InitComplete):
? 頁面調用OnInitComplete方法來引發InitComplete事件。該事件標明了初始化階段的結束。
此時,頁面Controls集合的所有控件都被初始化了。
06:加載控件狀態(Load Control State)[PostBack Only]:
? 頁面遞歸調用Control集合中控件的LoadControlState方法,這些控件已經調用了Page類
的RegisterRequiresControlState方法,以使用它們的控件狀態。
07:加載視圖狀態(Load View State)[PostBack Only]:
? 頁面首先調用自身的LoadViewState方法,接著遞歸調用Controls集合控件的LoadViewState方法,以允許它們加載它們的已經保存的視圖狀態。
08:加載回傳數據(Load Post Data)[PostBack Only]:
? 頁面調用實現IPostBackDataHandler接口的控件的LoadPostData方法,并將回傳數據傳遞給該方法。每個控件的LoadPostDate方法都必須訪問回傳數據,并據此更新相應的控件屬性。
例如:TextBox控件的LoadPostData方法將文本框的新值設置為TextBox控件的Text屬性值。
09:預加載(PreLoad):
? 頁面調用OnPreLoad方法以引發PreLoad事件。該事件表示頁面生命周期將進入加載階段。
10:加載(Load):
? 頁面首先調用自身的OnLoad方法以引發自身的Load事件,接著遞歸調用Controls集合中控件的OnLoad方法以引發它們的Load事件。頁面開發人員可以為Load事件注冊回調,那么就可以通過編程將子控件添加到頁面的Controls集合中。
11:加載回傳數據(Load Post Data)[PostBack Only Second Try]:
? 頁面調用控件的LoadPostBack方法。這些控件如果實現了IPostBackDataHandler接口,那么在加載階段,它們已通過編程添加到Controls集合中。
12:引發回傳數據修改事件(Raise Post Data Changed Event)[PostBack Only]:
? 頁面調用控件的RaisePostDataChangeEvent方法,這些控件的LoadPostData方法返回true。
RaisePostDataChangeEvent方法引發了回傳數據修改事件。例如:當文本框的新值與舊值
不同時,那么TextBox控件將引發該事件。
13:引發回傳事件(Raise PostBack Event)[PostBack Only]:
? 頁面調用控件的RaisePostEvent方法,這些控件相關的Html元素用于提交表單。例如,Button控件的相關Html元素將頁面回傳到服務器。控件的RaisePostBackEvent方法必須將回傳事件映射到一個或多個服務器事件。例如,Button控件的 RaisePostBackEvent方法將事件映射到了服務器端事件Command和Click上。
14:完成加載(Load Complete):
? 頁面調用OnLoadComplete方法來引發LoadComplete事件,這表示所有加載活動,包括加載回傳數據,以及引發回傳數據修改事件,并以更新控件自身的活動都完成了。
15:引發回調事件(Raise CallBack Event)(PostBack And CallBack Only):
? 頁面調用控件的RaiseCallBackEvent方法。該控件可使用AspNet客戶端回調機制來允許客戶端方法(例如JavaScript函數)調用服務器端方法,而無需將整個頁面回傳給服務器。
RaiseCallBackEvent方法必須調用服務器端方法。如果頁面的回傳使用了客戶端回調機制,那么頁面將不會執行剩余的頁面生命周期階段。
16:預呈現(PreRender):
? 在頁面生命周期這個階段執行一下操作。
?? a:調用EnsureChildControls方法來確保在頁面進入呈現階段之前,創建其子控件。
?? b:調用自身的OnPreRender方法來引發PreRender事件。
?? c:遞歸調用Controls集合中控件的OnPreRender方法,以引發它們的PreRender事件。
17:預呈現完成(PreRender Complete):
? 頁面調用OnPrerenderComplete方法來引發PreRenderComplete事件,這表示所有預呈現活動完成了。
18:保存控件狀態(Save Control State):
? 頁面遞歸調用Controls集合中控件的SaveControlState方法。這些控件已經調用了Page類的RegisterRequiresControlState方法來保存它們的控件狀態。
19:保存視圖狀態(Save View State):
? 頁面首先調用自身的SaveViewState方法,然后調用Controls集合中的SaveViewState方法,以允許它們來保存其視圖狀態。
20:保存狀態完成(Save View Complete):
? 頁面調用OnSaveStateComplete方法以引發SaveStateComplete事件,這表示所有狀態保存活動都完成了。
21:呈現:
? 在頁面生命周期的這個階段執行一下操作。
?? a:創建一個HtmlTextWriter類實例,該實例封裝了輸出響應流
?? b:調用RenderCOntrol方法,并將HtmlTextWriter實例傳遞給該方法。
? RenderControl方法遞歸調用子控件的RenderControl方法,以便允許每個控件能夠呈現其
Html標記文本。子控件的Html標記文本組成了最終發送給客戶端瀏覽器的Html標記文本。
我對.NET技術不熟悉,因此對ViewState,Cache這兩個功能不清楚,但可以對其他三個Cookie,Session,Application提供一些實踐方面的建議.??
? 1)cookie是大家最喜歡的一種存儲方式,但不是好的存儲方法,我的建議是在商業性網站開發中最好不用.典型的使用方法如下:??
? <%??
? Dim?? strUserID,?? strPassword,?? blnAutoLogin??
???
? strUserID?? =?? Request.Form("txtUserID")??
? strPassword?? =?? Request.Form("txtPassword")??
? blnAutoLogin?? =?? Request.Form("chkAutoLogin")??
???
? if?? blnAutoLogin?? =?? "on"?? then??
? 'Save?? Username?? and?? password?? to?? cookie??
? Response.Cookies("Credentials")("userid")?? =?? strUserID??
? Response.Cookies("Credentials")("password")?? =?? strPassword??
? Response.Cookies("Address")?? =?? "123?? Main?? Street"??
? End?? If??
? %>??
???
? 2)session是一種比較好的使用方式,但是不要使用過大.比如在一個商城的網站中,只有customerID用session保存,其他都從數據庫中獲得數據.典型代碼如下:??
? <%??
? Session.Contents("FavColour")?? =?? Request.Form("txtColour")??
? Response.write?? "Your?? colour?? has?? been?? saved"??
? %>??
? 3)Application是一個全程對象,通常的一個應用是做counter,看了國內的許多代碼,好象大家不喜歡用這個對象.典型代碼如下:??
? <%??
? Application.Lock??
? Application("anotherVariable")=Application("anotherVariable")+1??
? Application.Unlock??
? Response.write?? Application("anotherVariable")??
? %>??
???
? 我在開發時只用1個session作為用戶的ID.
Application
1.???????? Application用來保存所有用戶共用的信息
2.???????? 在Asp時代,如果要保存的數據在應用程序生存期內不會或者很少發生改變,那么使用Application是理想的選擇。但是在Asp.net開發環境中我們把類似的配置數據放在Web.config中。
3.???????? 如果要使用Application 要注意的是所有的寫操作都要在Application_OnStart事件中完成(global.Asax),盡管可以使用Application.Lock()避免了沖突,但是它串行化了對Application的請求,會產生嚴重的性能瓶頸。
4.???????? 不要使用Application保存大數據量信息
5.???????? 代碼:Application[“UserID”]=”test”;
??????? String UserName=Application[“UserID”].ToString();
Session
1.???????? Session用來保存每一個用戶的專有信息
2.???????? Session的生存期是用戶持續請求時間加上一段時間(一般是20分鐘左右)
3.???????? Session信息是保存在Web服務器內存中的,保存數據量可大可小
4.???????? Session超時或者被關閉將自動釋放數據信息
5.???????? 由于用戶停止使用應用程序之后它仍在內存中存留一段時間,因此這種方法效率較低
6.???????? 代碼:Session[“UserID”]=”test”;
??????? String UserName=Session[“UserID”].ToString();
Cookie
1.???????? Cookie用來保存客戶瀏覽器請求服務器頁面的請求信息
2.???????? 我們可以存放非敏感的用戶信息,保存時間可以根據需要設置
3.???????? 如果沒有設置Cookie失效日期,它的生命周期保存到關閉瀏覽器為止
4.???????? Cookie對象的Expires屬性設置為MinValue表示永不過期
5.???????? Cookie存儲的數據量受限制,大多數的瀏覽器為4K因此不要存放大數據
6.???????? 由于并非所有的瀏覽器都支持Cookie,數據將以明文的形式保存在客戶端
7.???????? 代碼:Resopnse.Cookies[“UserID”]=”test”;
??????? String UserName= Resopnse.Cookies [“UserID”].ToString();
ViewState
1.???????? ViewState用來保存用戶的狀態信息,有效期等于頁面的生命周期
2.???????? 可以保存大量數據但是要慎用,因為會影響程序性能
3.???????? 所有的Web服務器控件都是用ViewState在頁面PostBack期間保存狀態
4.???????? 不需要則關閉 @page 里面設置EnableViewState=false
5.???????? 代碼:ViewState[‘”ID”]=”yiner”;
?? String ID =ViewState[“ID”].ToString();
Cache
1.???????? Cache用于在Http請求期間保存頁面或者數據
2.???????? Cache的使用可以大大的提高整個應用程序的效率
3.???????? 它允許將頻繁訪問的服務器資源存儲在內存中,當用戶發出相同的請求后
服務器不是再次處理而是將Cache中保存的數據直接返回給用戶
4.???????? 可以看出Cache節省的是時間—服務器處理時間
5.???????? Cache實例是每一個應用程序專有的,其生命周期==該應用程序周期
應用程序重啟將重新創建其實例
6.???????? 注意:如果要使用緩存的清理、到期管理、依賴項等功能必須使用Insert 或者Add方法方法添加信息
7.???????? 代碼:Cache[‘”ID”]=”yiner”;或者Cache.Insert(“ID”,”test”);
?? String ID =Cache[“ID”].ToString();
Hidden
1.???????? Hidden控件屬于Html類型的服務器控件,始終處于隱藏狀態
2.???????? 每一次提交的時候它會和其他服務器控件一起提交到服務器端
3.???????? 代碼如下:Hidden.Value=”king”;
string id=Hidden.Value; 要使用Runat=server
1,ViewState多半存儲本頁內的信息,適用少量數據,具有基本安全性; 使用視圖狀態的優點是: a, 不需要任何服務器資源。視圖狀態包含在頁代碼內的結構中。 b, 簡單的實現。 c, 頁和控件狀態的自動保持。 d, 增強的安全功能。視圖狀態中的值是散列的、壓縮的并且是為 Unicode 實現而編碼的,這意味著比隱藏域具有更高的安全性狀態。 使用視圖狀態的缺點是: a, 性能。由于視圖狀態存儲在頁本身,因此如果存儲較大的值,在用戶顯示頁和發送頁時,頁的速度就可能會減慢。 b, 安全性。視圖狀態存儲在頁上的隱藏域中。雖然視圖狀態以哈希格式存儲數據,但它可以被篡改。如果直接查看頁輸出源,可以看到隱藏域中的信息,這導致潛在的安全性問題。
2,QueryString多半是地址欄參數,到下一頁使用,明文,無所謂安全;
3,Cookies需要在客戶端存儲少量信息,不需要較高的安全性; 使用 Cookie 的優點是: a, 不需要任何服務器資源。Cookie 存儲在客戶端并在發送后由服務器讀取。 b, 簡單。Cookie 是具有簡單鍵值對的輕量的、基于文本的結構。 c,可配置到期時間。Cookie 可以在瀏覽器會話結束時到期,或者可以在客戶端計算機上無限期存在,這取決于客戶端的到期規則。 使用 Cookie 的缺點是: a, 大小受到限制。 b, 用戶配置為拒絕接受。有些用戶禁用了瀏覽器或客戶端設備接收 Cookie 的能力,因此限制了這一功能。 c, 安全性。Cookie 可能會受到篡改。用戶可能會操縱其計算機上的 Cookie,這可能意味著安全性會受到影響或者導致依賴于 Cookie 的應用程序失敗。 d, 持久性。客戶端計算機上 Cookie 的持久性受到客戶端 Cookie 到期進程以及用戶干預的制約。 e, Cookie 通常用于為已知用戶自定義內容的個性化情況。在大多數此類情況中,Cookie 是作為“標識”而不是“身份驗證”,所以在 Cookie 中只存儲用戶名、賬戶名或唯一用戶 ID(例如 GUID)并使用它來訪問站點的用戶個性化結構是足夠的了。
4,Session存儲在會話狀態變量中的理想數據是特定于單獨的、短期的、敏感的數據,應該是安全的,但過多使用會降低服務其性能; 使用會話狀態的優點是: a, 易于實現。會話狀態功能易于使用。 b, 會話特定的事件。會話管理事件可以由應用程序引發和使用。 c, 持久性。放置于會話狀態變量中的數據可以經受得住 Internet 信息服務 (IIS) 重新啟動和輔助進程重新啟動,而不丟失會話數據,這是因為這些數據存儲在另一個進程空間中。 d, 平臺可縮放性。會話狀態對象可在多計算機和多進程配置中使用,因而優化了可縮放性方案。 e, 盡管會話狀態最常見的用途是與 Cookie 一起向 Web 應用程序提供用戶標識功能,但會話狀態可用于不支持 HTTP Cookie 的瀏覽器。 使用會話狀態的缺點是: a, 性能。會話狀態變量在被移除或替換前保留在內存中,因而可能降低服務器性能。如果會話狀態變量包含類似大型數據集的信息塊,則可能會因服務器負荷的增加影響 Web 服務器的性能。
5,Application插入到應用程序狀態變量的理想數據是那些由多個會話共享并且不經常更改的數據使用應用程序狀態的優點是: a, 易于實現。應用程序狀態易于使用。 b, 全局范圍。由于應用程序狀態可供應用程序中的所有頁來訪問,因此在應用程序狀態中存儲信息可能意味著僅保留信息的一個副本(例如,相對于在會話狀態或在單獨頁中保存信息的多個副本)。 使用應用程序狀態的缺點是: a, 全局范圍。應用程序狀態的全局性可能也是一項缺點。在應用程序狀態中存儲的變量僅對于該應用程序正在其中運行的特定進程而言是全局的,并且每一應用程序進程可能具有不同的值。因此,不能依賴應用程序狀態來存儲唯一值或更新網絡園和網絡場配置中的全局計數器。 b, 持久性。因為在應用程序狀態中存儲的全局數據是易失的,所以如果包含這些數據的 Web 服務器進程被損壞(最有可能是因服務器崩潰、升級或關閉而損壞),將丟失這些數據。 c, 資源要求。應用程序狀態需要服務器內存,這可能會影響服務器的性能以及應用程序的可縮放性。應用程序狀態的精心設計和實現可以提高 Web 應用程序性能。例如,如果將常用的、相關的靜態數據集放置到應用程序狀態中,則可以通過減少對數據庫的數據請求總數來提高站點性能。但是,這里存在一種性能平衡。當服務器負載增加時,包含大塊信息的應用程序狀態變量就會降低 Web 服務器的性能。在移除或替換值之前,將不釋放在應用程序狀態中存儲的變量所占用的內存。因此,最好只將應用程序狀態變量用于更改不頻繁的小型數據集。
6,Cache,.NET 為您提供了一個強大的、便于使用的緩存機制,允許您將需要大量的服務器資源來創建的對象存儲在內存中。其生存期依賴于該應用程序的生存期。重新啟動應用程序后,將重新創建 Cache 對象。他的作用比較豐富,機制也比較多,請參閱相關的資料。
Web Service安全機制探討
http://hi.baidu.com/%D3%F1%D3%E3/blog/item/99f3ec4ac8fe832608f7ef57.html
net面試題大全(有答案) & asp.net面試集合
C#基礎概念二十五問(轉)
http://www.cnblogs.com/jiayong/archive/2008/01/07/1029138.html
.net工程師必懂題(筆試題目)轉
http://www.cnblogs.com/jiayong/archive/2008/01/08/1030175.html
?