亚洲日韩中文无码久久,亚洲av一综合av一区,亚洲精品伊人久久久久http://m.tkk7.com/forget/<h2>能吃能睡是福;能忘是大福......</h2>zh-cnMon, 12 May 2025 15:10:22 GMTMon, 12 May 2025 15:10:22 GMT6061條面向對象設計的經驗原則http://m.tkk7.com/forget/archive/2011/05/12/350101.html橘子橘子Thu, 12 May 2011 08:50:00 GMThttp://m.tkk7.com/forget/archive/2011/05/12/350101.htmlhttp://m.tkk7.com/forget/comments/350101.htmlhttp://m.tkk7.com/forget/archive/2011/05/12/350101.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/350101.htmlhttp://m.tkk7.com/forget/services/trackbacks/350101.html     (1)所有數據都應該隱藏在所在的類的內部。
  
  (2)類的使用者必須依靠類的共有接口,但類不能依靠它的使用者。
  
  (3)盡量減少類的協議中的消息。
  
  (4)實現所有類都理解的最基本公有接口[例如,拷貝操作(深拷貝和淺拷貝)、相等性判定、正確輸出內容、從ASCII描述解析等等]。
  
  (5)不要把實現細節(例如放置共用代碼的私有函數)放到類的公有接口中。
  
  假如類的兩個方法有一段公共代碼,那么就可以創建一個防止這些公共代碼的私有函數。
  
  (6)不要以用戶無法使用或不感愛好的東西擾亂類的公有接口。
  
  (7)類之間應該零耦合,或者只有導出耦合關系。也即,一個類要么同另一個類毫無關系,要么只使用另一個類的公有接口中的操作。
  
  (8)類應該只表示一個要害抽象。
  
  包中的所有類對于同一類性質的變化應該是共同封閉的。一個變化若對一個包影響,則將對包中的所有類產生影響,而對其他的包不造成任何影響 。
  
  (9)把相關的數據和行為集中放置。
  
  設計者應當留意那些通過get之類操作從別的對象中獲取數據的對象。這種類型的行為暗示著這條經驗原則被違反了。
  
  (10)把不相關的信息放在另一個類中(也即:互不溝通的行為)。
  
  朝著穩定的方向進行依靠。
  
  (11)確保你為之建模的抽象概念是類,而不只是對象扮演的角色。
  
  (12)在水平方向上盡可能統一地分布系統功能,也即:按照設計,頂層類應當統一地共享工作。
  
  (13)在你的系統中不要創建全能類/對象。對名字包含Driver、Manager、System、Susystem的類要非凡多加小心。
  
  規劃一個接口而不是實現一個接口。
  
  (14)對公共接口中定義了大量訪問方法的類多加小心。大量訪問方法意味著相關數據和行為沒有集中存放。
  
  (15)對包含太多互不溝通的行為的類多加小心。
  
  這個問題的另一表現是在你的應用程序中的類的公有接口中創建了很多的get和set函數。
  
  (16)在由同用戶界面交互的面向對象模型構成的應用程序中,模型不應該依靠于界面,界面則應當依靠于模型。
  
  (17)盡可能地按照現實世界建模(我們經常為了遵守系統功能分布原則、避免全能類原則以及集中放置相關數據和行為的原則而違反這條原則) 。
  
  (18)從你的設計中去除不需要的類。
  
  一般來說,我們會把這個類降級成一個屬性。
  
  (19)去除系統外的類。
  
  系統外的類的特點是,抽象地看它們只往系統領域發送消息但并不接受系統領域內其他類發出的消息。
  
  (20)不要把操作變成類。質疑任何名字是動詞或者派生自動詞的類,非凡是只有一個有意義行為的類。考慮一下那個有意義的行為是否應當遷移到已經存在或者尚未發現的某個類中。
  
  (21)我們在創建應用程序的分析模型時經常引入代理類。在設計階段,我們常會發現很多代理沒有用的,應當去除。
  
  (22)盡量減少類的協作者的數量。
  
  一個類用到的其他類的數目應當盡量少。
  
  (23)盡量減少類和協作者之間傳遞的消息的數量。
  
  (24)盡量減少類和協作者之間的協作量,也即:減少類和協作者之間傳遞的不同消息的數量。
  
  (25)盡量減少類的扇出,也即:減少類定義的消息數和發送的消息數的乘積。
  
  (26)假如類包含另一個類的對象,那么包含類應當給被包含的對象發送消息。也即:包含關系總是意味著使用關系。
  
  (27)類中定義的大多數方法都應當在大多數時間里使用大多數數據成員。
  
  (28)類包含的對象數目不應當超過開發者短期記憶的容量。這個數目經常是6。
  
  當類包含多于6個數據成員時,可以把邏輯相關的數據成員劃分為一組,然后用一個新的包含類去包含這一組成員。
  
  (29)讓系統功能在窄而深的繼續體系中垂直分布。
  
  (30)在實現語義約束時,最好根據類定義來實現。這經常會導致類泛濫成災,在這種情況下,約束應當在類的行為中實現,通常是在構造函數中實現,但不是必須如此。
  
  (31)在類的構造函數中實現語義約束時,把約束測試放在構造函數領域所答應的盡量深的包含層次中。
  
  (32)約束所依靠的語義信息假如經常改變,那么最好放在一個集中式的第3方對象中。
  
  (33)約束所依靠的語義信息假如很少改變,那么最好分布在約束所涉及的各個類中。
  
  (34)類必須知道它包含什么,但是不能知道誰包含它。
  
  (35)共享字面范圍(也就是被同一個類所包含)的對象相互之間不應當有使用關系。
  
  (36)繼續只應被用來為特化層次結構建模。
  
  (37)派生類必須知道基類,基類不應該知道關于它們的派生類的任何信息。
  
  (38)基類中的所有數據都應當是私有的,不要使用保護數據。
  
  類的設計者永遠都不應該把類的使用者不需要的東西放在公有接口中。
  
  (39)在理論上,繼續層次體系應當深一點,越深越好。
  
  (40)在實踐中,繼續層次體系的深度不應當超出一個普通人的短期記憶能力。一個廣為接受的深度值是6。
  
  (41)所有的抽象類都應當是基類。
  
  (42)所有的基類都應當是抽象類。
  
  (43)把數據、行為和/或接口的共性盡可能地放到繼續層次體系的高端。
  
  (44)假如兩個或更多個類共享公共數據(但沒有公共行為),那么應當把公共數據放在一個類中,每個共享這個數據的類都包含這個類。
  
  (45)假如兩個或更多個類有共同的數據和行為(就是方法),那么這些類的每一個都應當從一個表示了這些數據和方法的公共基類繼續。
  
  (46)假如兩個或更多個類共享公共接口(指的是消息,而不是方法),那么只有他們需要被多態地使用時,他們才應當從一個公共基類繼續。
  
  (47)對對象類型的顯示的分情況分析一般是錯誤的。在大多數這樣的情況下,設計者應當使用多態。
  
  (48)對屬性值的顯示的分情況分析經常是錯誤的。類應當解耦合成一個繼續層次結構,每個屬性值都被變換成一個派生類。
  
  (49)不要通過繼續關系來為類的動態語義建模。試圖用靜態語義關系來為動態語義建模會導致在運行時切換類型。
  
  (50)不要把類的對象變成派生類。對任何只有一個實例的派生類都要多加小心。
  
  (51)假如你覺得需要在運行時刻創建新的類,那么退后一步以認清你要創建的是對象。現在,把這些對象概括成一個類。
  
  (52)在派生類中用空方法(也就是什么也不做的方法)來覆寫基類中的方法應當是非法的。
  
  (53)不要把可選包含同對繼續的需要相混淆。把可選包含建模成繼續會帶來泛濫成災的類。
  
  (54)在創建繼續層次時,試著創建可復用的框架,而不是可復用的組件。
  
  (55)假如你在設計中使用了多重繼續,先假設你犯了錯誤。假如沒犯錯誤,你需要設法證實。
  
  (56)只要在面向對象設計中用到了繼續,問自己兩個問題:(1)派生類是否是它繼續的那個東西的一個非凡類型?(2)基類是不是派生類的一部分?
  
  (57)假如你在一個面向對象設計中發現了多重繼續關系,確保沒有哪個基類實際上是另一個基類的派生類。
  
  (58)在面向對象設計中假如你需要在包含關系和關聯關系間作出選擇,請選擇包含關系。
  
  (59)不要把全局數據或全局函數用于類的對象的薄記工作。應當使用類變量或類方法。
  
  (60)面向對象設計者不應當讓物理設計準則來破壞他們的邏輯設計。但是,在對邏輯設計作出決策的過程中我們經常用到物理設計準則。
  
  (61)不要繞開公共接口去修改對象的狀態。



橘子 2011-05-12 16:50 發表評論
]]>
SVN完整安裝及簡略使用http://m.tkk7.com/forget/archive/2006/08/08/62304.html橘子橘子Tue, 08 Aug 2006 02:33:00 GMThttp://m.tkk7.com/forget/archive/2006/08/08/62304.htmlhttp://m.tkk7.com/forget/comments/62304.htmlhttp://m.tkk7.com/forget/archive/2006/08/08/62304.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/62304.htmlhttp://m.tkk7.com/forget/services/trackbacks/62304.html閱讀全文

橘子 2006-08-08 10:33 發表評論
]]>
Synchronization state同步狀態http://m.tkk7.com/forget/archive/2006/07/26/60221.html橘子橘子Wed, 26 Jul 2006 10:01:00 GMThttp://m.tkk7.com/forget/archive/2006/07/26/60221.htmlhttp://m.tkk7.com/forget/comments/60221.htmlhttp://m.tkk7.com/forget/archive/2006/07/26/60221.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/60221.htmlhttp://m.tkk7.com/forget/services/trackbacks/60221.html同步狀態 ?
同步視圖顯示你的本地工作平臺與服務器存儲庫中資源的同步狀態。狀態按圖標顯示,你也可以把狀態顯示配置為資源名稱之后的文字。下表列出圖標的描述。 ?
指向左邊的藍色箭頭包含加號,引入新增——表示一項資源已經被加入到服務器。點更新鍵會把資源傳遞到本地上。 ?
指向左邊的藍色箭頭 ?引入變化——表示服務器中的資源已經變化。點更新鍵會把新文件傳遞到本地。 ?
指向左邊的藍色箭頭包含減號 ?引入刪除——表示服務器的資源已被刪除。點更新鍵會刪除你本地的資源 ? ?
指向右邊的黑色箭頭包含加號 ?輸出增加——表示你本地有新增加的文件,而服務器中沒有。添加提交鍵會把新文件傳到服務器上。 ? ?
指向右邊的黑色箭頭 ?輸出變化——表示本地的文件已經改變。提交文件會把變化傳入服務器并創建文件的一個新版本。 ? ?
指向右邊的黑色箭頭包含減號 ?輸出刪除——表示本地文件已經刪除。提交這些資源會刪除遠程資源。注意:在CVS中目錄不會從服務器中真正的刪除。而只是把文件刪除,在你本地除去空文件夾。 ? ?
紅色雙向箭頭包含加號 ?沖突增加——表示本地和遠程都新增加了資源 ? ?
紅色雙向箭頭 ?沖突變化——表示本地和遠程都有文件變化。用戶需要手工合并或者自動合并。同時,包含有沖突文件的上級視圖也同時被顯示為沖突,這樣做是為了讓沖突更容易找到。 ? ? ?
紅色雙向箭頭包含減號 ?沖突刪除——表示本地和遠程的文件都被刪除。????

橘子 2006-07-26 18:01 發表評論
]]>
使用 Eclipse 平臺共享代碼http://m.tkk7.com/forget/archive/2006/07/26/60220.html橘子橘子Wed, 26 Jul 2006 10:00:00 GMThttp://m.tkk7.com/forget/archive/2006/07/26/60220.htmlhttp://m.tkk7.com/forget/comments/60220.htmlhttp://m.tkk7.com/forget/archive/2006/07/26/60220.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/60220.htmlhttp://m.tkk7.com/forget/services/trackbacks/60220.html 在團隊項目中共享源代碼
現今的大多數應用程序是由多人組成的團隊開發的。即使只涉及幾個開發人員的小項目,也需要對源代碼的更改進行嚴格控制。這就是源代碼管理軟件的任務。源代碼版本控制軟件必須支持兩個核心功能:

  • 提供一種方法,能夠協調對源代碼的更改,并能集成這些更改
  • 團隊所提交工作的歷史記錄

當團隊成員完成新的工作時,通過將這些更改提交到資源庫來共享他們的工作。類似地,當他們希望獲得最新可用的工作成果時,就可以根據資源庫中的更改,更新自己的本地工作空間。這意味著項目資源庫會因團隊成員提交新工作成果而經常發生更改。換句話說,資源庫應該表示項目的當前狀態。任何時候,團隊成員都要能夠根據資源庫更新自己的工作空間,并確信它們是最新的。

維護歷史記錄也很重要,那樣就可以將當前工作與先前版本進行比較,如有必要,還可以回復到先前版本。協調團隊的工作,以便只存在唯一的當前項目狀態定義,以及包含團隊已集成的工作,這些對于管理版本控制也是十分必要的。這種協調有可能是最難實現的目標。

最理想的模型是:團隊的任何成員都可以對自己有權訪問的任何資源進行更改。因為兩個團隊成員可以提交對同一資源的更改,所以有可能發生沖突,必須解決這種沖突。這種模型假定沖突具有唯一性。但遺憾的是,沒有任何源代碼是孤立地存在的;通常它包含與其它資源隱式或顯式的相關性。源代碼引用了在其它源代碼資源中描述的構件。但源代碼管理軟件的工作就到此為止了,因為它并不能取代項目管理。項目管理者必須履行其職責:協調其它成員的工作以及負責進度、項目階段和發布日期。此外,源代碼管理也不能替代開發人員之間的交流。

Eclipse 平臺如何支持代碼管理
Eclipse 平臺提供了作為團隊在軟件項目中共享代碼和工作的能力。Eclipse 廣泛地支持各種代碼管理解決方案,這要歸功于它的插件體系結構(不過,現已推出了對 CVS 的支持)。Eclipse 平臺體系結構的重點在于工作空間。工作空間維護構建和測試軟件項目所需的一切。它包含對象(源代碼和資源)。它還保存了用于項目、IDE 和插件的配置設置。工作空間是在開發人員的機器上本地進行維護的,而團隊通過外部資源庫進行協作,不同開發人員的代碼在資源庫進行匯集。可以經由因特網通過“客戶機-服務器”體系結構訪問資源庫。

Eclipse 平臺提供了對于直接從工作空間進行團隊開發操作的支持。這種支持允許開發人員并發地與幾個獨立的資源庫以及不同版本的代碼或項目進行交互。工作空間中的資源允許團隊支持組件處理版本和配置管理問題。當然,單個工作空間可以同時訪問不同類型的資源庫。Eclipse 平臺并沒有提供它自己的代碼管理解決方案;它總是依靠外部系統。Eclipse 平臺只對一個(但也是最流行的一個)源代碼管理系統提供內置支持:并發版本控制系統(Concurrent Versions System,CVS)。對第三方代碼管理應用程序的支持一節中描述了使用第三方插件支持其它資源庫。

CVS 是什么?
CVS 誕生于 1986 年,當時作為一組 shell 腳本而出現,但它現在已經發展成了最流行的針對軟件開發人員的源代碼版本管理解決方案。CVS 是用于代碼版本管理的開放源碼的客戶機/服務器解決方案,它可用于各種平臺,包括 Linux 和 Windows NT/2000/XP。請參閱本文末尾的參考資料,其中有 CVS 客戶機、服務器和源代碼的下載鏈接。

通常,CVS 的主要功能是記錄源文件的歷史。當一組開發人員從事同一個項目時,CVS 將他們彼此隔離開來。每個開發人員都在他/她自己的目錄中獨立工作,然后使用 CVS 資源庫(不時地)合并工作結果。

Eclipse 擁有與 Eclipse 平臺 IDE 緊密集成的內置 CVS 客戶機,它是作為一個單獨透視圖(CVS Repository Exploring 透視圖)而實現的,用于與 CVS 的交互。用于 CVS 的通用 Eclipse 設置(General Eclipse settings for CVS)位于 Window -> Preferences window -> Team 下。在切換到 CVS Repository Exploring 透視圖之后,就可以使用所有 CVS 操作了(轉至 Window -> Open Perspective -> Other -> CVS Repository Exploring 菜單 — 請參閱圖 1圖 2)。

圖 1. 切換到 CVS Repository Exploring 透視圖
CVS 資源庫

首先設置資源庫的位置,它將定義用于選定 CVS 服務器/資源庫的連接參數。請確保使用 SSH 隧道(extssh)。

圖 2. 瀏覽 CVS Repository Exploring 透視圖中的 CVS 資源庫
瀏覽 CVS 資源庫

Eclipse/CVS 的源代碼工作流
CVS 團隊協作模型中,團隊成員彼此獨立地在他們各自的工作臺上完成自己的所有工作。最后,他們希望共享其工作。他們通過 CVS 資源庫實現這一點。CVS 使用分支(branch)模型來支持彼此獨立而又高度相互依賴的多個工作流程(course of work)。這些分支是開發團隊用來共享和集成正在進行中的工作的地方。可以認為分支是一個共享的工作臺,當團隊成員對源代碼進行更改時就更新這個工作臺。這個模型允許從事 CVS 團隊項目的每個開發人員在進行更改時與其他成員共享其工作,以及在項目進展期間訪問其他成員的工作。

一個稱為 HEAD 的特殊分支用來表示資源庫中的主要工作流程(HEAD 通常被稱為主干)。當團隊成員將資源提交給該分支時,會影響這些相關性。確保相關性的完整性是很重要的,因為該分支表示了當前項目的狀態。當然,任何時候,團隊成員都可以使用該分支的內容作為新工作的基礎。

那些規則不僅適用于 CVS:無論使用哪種版本控制軟件,團隊項目中都有一些用于源代碼管理的常見步驟。下面是一個使用 Eclipse 內置的 CVS 支持的示例工作流:

1. 啟動新的團隊項目
每個新的空 Eclipse 項目都可以通過 CVS(或受支持的任何其它源代碼管理系統)進行共享。開發人員也可以通過將其現有的代碼遷移到資源庫來共享它。要進行共享,單擊項目主文件夾,在顯示的上下文菜單中使用 Team -> Share Project 選項,如圖 3 所示。

圖 3. 使用 CVS 資源庫共享本地項目
共享項目

另一個選項是通過從選定的 CVS 資源庫分支導入代碼來創建新的工作臺項目。只要選擇適當分支(或 HEAD),然后選擇從 CVS Repository Exploring 透視圖中的上下文菜單中選擇“Checkout As Project”選項,如圖 4 所示。

圖 4. 從現有的 CVS 資源庫創建新項目
新建項目

2. 使用代碼并進行更改
開發人員通過 Eclipse 工作臺在本地使用代碼,包括的工作有創建新資源、修改現有資源、編寫注釋,并在他們使用后在本地保存這些內容。

3. 使本地更改與 CVS 資源庫同步
如果一個項目開發人員準備提交他/她的工作,那么首先要執行更新操作。這會針對引入的更改核對資源庫,并將這些更改添加到該開發人員的本地工作臺。這樣確保了開發人員知道這些更改可能會影響他/她將要提交的工作的完整性。使用項目上下文菜單中的 Compare With... 選項將本地版本與資源庫中存儲的代碼進行比較(請參閱圖 5)。

圖 5. 比較本地版本與資源庫中的版本
本地版本

下一步是解決最后出現的任何沖突,并設法再次編譯代碼。如果一切正常,那么從項目上下文菜單使用 Team -> Commit... 選項執行提交操作,如圖 6 所示。這會使所有更改都集成到資源庫中。

圖 6. 將更改提交到遠程資源庫
提交更改

4. 管理資源庫
CVS 允許開發人員將更改隔離在開發的某些獨立路徑之內,這些路徑稱為分支。當一個開發人員更改某個分支上的文件時,這種更改不會出現在主干或其它分支上。那些分支被命名為子版本(subversion)代碼分叉(code fork)。稍后,由合并操作將更改從一個分支遷移到另一個分支(或主干)。然后提交這些修訂。這樣就有效地將更改復制到了另一個分支上。使用項目上下文菜單的 Team -> Branch... 選項,Eclipse 使開發分支之間的遷移變得容易。

當然,當開發團隊維護大型資源庫時,有必要控制項目內的提交和合并操作。Eclipse/CVS 集成提供了一種特殊的視圖:CVS Repository History(請參閱圖 7)。它給出了關于團隊成員在資源庫中所執行更改的快速預覽。

圖 7. 在 CVS Resource History 窗口中查看帶注釋的修訂歷史記錄
修訂歷史記錄

Eclipse 平臺提供了幾個支持代碼管理的實用程序。最有用的是補丁功能。它將出自兩個來源(譬如本地工作臺和資源庫)的代碼進行比較,然后創建一個包含代碼差異的類似 UNIX 的補丁文件(請參閱圖 8)。可以將該文件發送給開發人員以將源代碼升級到最新版本。

圖 8. 創建用于源代碼分發的補丁
源代碼分發

5. 斷開項目與 CVS 的連接
當項目開發已經結束,并且團隊希望凍結源代碼時,可以從 HEAD 資源庫刪除該項目的最終版本。斷開項目與 CVS 的連接將在該項目及其資源上禁用資源庫操作,并刪除與該項目相關聯的 CVS 信息(這一操作是可選的)。

可以通過項目上下文菜單中的 Team -> Disconnect 選項執行斷開連接操作。通過選擇這個選項,會打開 Confirm Disconnect from CVS 對話框。在將該項目與資源庫的連接斷開之后,該團隊必須確定如何處理 CVS 信息。第一個選項是“Delete the CVS meta information”;它將禁用 CVS 團隊菜單操作并從文件系統中刪除CVS 文件夾及其內容。第二個選項是“Do not delete the CVS meta information”;它將禁用 CVS 團隊菜單操作,但保留 CVS 元信息。

對第三方代碼管理應用程序的支持
CVS 有幾個重要的限制:它不能確定單個文件或整個文件集范圍內同時進行的更改,它也不能檢測文件之間的邏輯沖突。其沖突概念純粹是文本意義上的,當對于同一基本文件的兩個更改時間上非常非常接近,從而使合并命令受到干擾時,就會發生沖突。CVS 也不能提供任何類似于消息傳遞這樣的交互式協作工具。幸運的是,CVS 并不是 Eclipse 平臺所支持的唯一的源代碼管理軟件。開發人員可以通過插件擴展 Eclipse 平臺的功能,而且目前(到 2003 年 3 月 4 日為止)已有 16 個可用于團隊開發軟件的插件。所有插件都是由 Eclipse 社區或商業軟件供應商創建的。這些插件中的大多數添加了對第三方、商業源代碼管理系統的支持。最有價值的插件是那些支持流行的企業代碼管理系統(如 Merant PVCS 和 Rational ClearCase)的插件。例如,CVS-SSH2 插件允許通過 SSH2 會話訪問 CVS,而 Microsoft Visual SourceSafe(VSS)團隊提供程序插件添加了對 MS VSS 產品的支持(也可以在諸如 Linux 這樣的非 Windows 平臺上使用)。

但是,我本人所偏愛的插件是 Koi(請參閱參考資料以獲取鏈接)。盡管它并非嚴格用于源代碼控制,但這個創新的工具給協作開發注入了許多新的活力。其當前版本支持工作臺到工作臺的消息傳遞、共享標記、沖突更改通知、共享日歷和事件通知。Koi 將 XML-RPC 用作其客戶機-服務器體系結構中的通信模型。客戶機是與“協作服務器”通信的單個 Eclipse 平臺實例,而協作服務器也是一個 Eclipse 插件。Koi 使用以 JDBC 訪問的關系數據庫作為數據存儲。可在參考資料中找到指向完整的、經過分類的 Eclipse 插件注冊表的鏈接。

參考資料

 

關于作者
Pawel Leszek 是 Studio B 的一位作家,他是一位專長于 Linux/Win/Mac OS 系統體系結構和管理的獨立軟件顧問和作家。他具有許多操作系統、編程語言和網絡協議方面的經驗,尤其是 Lotus Domino 和 DB2 方面。Pawel 還在 LinuxWorld 上發表過一系列文章,他是 PC World 波蘭版的 Linux 專欄作家。Pawel 和他的妻子以及可愛的小女兒住在華沙。歡迎提問并提出意見;您可以通過 pawel.leszek@ipgate.pl 與 Pawel 聯系。


橘子 2006-07-26 18:00 發表評論
]]>
什么是持久化和對象關系映射ORM技術http://m.tkk7.com/forget/archive/2006/06/26/55068.html橘子橘子Mon, 26 Jun 2006 01:42:00 GMThttp://m.tkk7.com/forget/archive/2006/06/26/55068.htmlhttp://m.tkk7.com/forget/comments/55068.htmlhttp://m.tkk7.com/forget/archive/2006/06/26/55068.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/55068.htmlhttp://m.tkk7.com/forget/services/trackbacks/55068.htmlhttp://www.volitation.net/Article/print.asp?SelectID=7。
何謂“持久化”
持久(Persistence),即把數據(如內存中的對象)保存到可永久保存的存儲設備中(如磁盤)。持久化的主要應用是將內存中的數據存儲在關系型的數據庫中,當然也可以存儲在磁盤文件中、XML數據文件中等等。

何謂“持久層”
持久層(Persistence Layer),即專注于實現數據持久化應用領域的某個特定系統的一個邏輯層面,將數據使用者和數據實體相關聯。

何謂“對象數據映射(ORM)”
ORM-Object/Relational Mapper,即“對象-關系型數據映射組件”。對于O/R,即 Object(對象)和 Relational(關系型數據),表示必須同時使用面向對象和關系型數據進行開發。

備注:建模領域中的 ORM 為 Object/Role Modeling(對象角色建模)。另外這里是“O/R Mapper”而非“O/R Mapping”。相對來講,O/R Mapping 描述的是一種設計思想或者實現機制,而 O/R Mapper指以O/R原理設計的持久化框架(Framework),包括 O/R機制還有 SQL自生成,事務處理,Cache管理等。


除了 ORM 技術,還有以下幾種持久化技術

主動域對象模式
它是在實現中封裝了關系數據模型和數據訪問細節的一種形式。在 J2EE 架構中,EJB 組件分為會話 EJB 和實體 EJB。會話 EJB 通常實現業務邏輯,而實體 EJB 表示業務實體。實體 EJB 又分為兩種:由 EJB 本身管理持久化,即 BMP(Bean-Managed Persistence);有 EJB 容器管理持久化,即 CMP(Container-Managed Persistence)。BM P就是主動域對象模式的一個例子,BMP 表示由實體 EJB 自身管理數據訪問細節。
主動域對象本身位于業務邏輯層,因此采用主動域對象模式時,整個應用仍然是三層應用結構,并沒有從業務邏輯層分離出獨立的持久化層。

JDO 模式
Java Data Objects(JDO)是 SUN 公司制定的描述對象持久化語義的標準API。嚴格的說,JDO 并不是對象-關系映射接口,因為它支持把對象持久化到任意一種存儲系統中,包括 關系數據庫、面向對象的數據庫、基于 XML 的數據庫,以及其他專有存儲系統。由于關系數據庫是目前最流行的存儲系統,許多 JDO 的實現都包含了對象-關系映射服務。

CMP 模式
在 J2EE 架構中,CMP(Container-Managed Persistence)表示由 EJB 容器來管理實體 EJB 的持久化,EJB 容器封裝了對象-關系的映射及數據訪問細節。CMP 和 ORM 的相似之處在于,兩者都提供對象-關系映射服務,都把對象持久化的任務從業務邏輯中分離出來。區別在于 CMP 負責持久化實體 EJB 組件,而 ORM 負責持久化 POJO,它是普通的基于 Java Bean 形式的實體域對象。

一般把基于 Java Bean 形式的實體域對象稱為 POJO(Plain Old Java Object),意為又普通又古老的 Java 對象的意思。隨著各種 ORM 映射工具的日趨成熟和流行,POJO有重現光彩,它和基于 CMP 的實體 EJB 相比,即簡單又具有很高的可移植性,因此聯合使用 ORM 映射工具和 POJO,已經成為一種越來越受歡迎的且用來取代 CMP 的持久化方案。POJO 的缺點就是無法做遠程調用,不支持分布式計算。


為什么要做持久化和ORM設計

在目前的企業應用系統設計中,MVC,即 Model(模型)- View(視圖)- Control(控制)為主要的系統架構模式。MVC 中的 Model 包含了復雜的業務邏輯和數據邏輯,以及數據存取機制(如 JDBC的連接、SQL生成和Statement創建、還有ResultSet結果集的讀取等)等。將這些復雜的業務邏輯和數據邏輯分離,以將系統的緊耦合關系轉化為松耦合關系(即解耦合),是降低系統耦合度迫切要做的,也是持久化要做的工作。MVC 模式實現了架構上將表現層(即View)和數據處理層(即Model)分離的解耦合,而持久化的設計則實現了數據處理層內部的業務邏輯和數據邏輯分離的解耦合。而 ORM 作為持久化設計中的最重要也最復雜的技術,也是目前業界熱點技術。

簡單來說,按通常的系統設計,使用 JDBC 操作數據庫,業務處理邏輯和數據存取邏輯是混雜在一起的。
一般基本都是如下幾個步驟:
1、建立數據庫連接,獲得 Connection 對象。
2、根據用戶的輸入組裝查詢 SQL 語句。
3、根據 SQL 語句建立 Statement 對象 或者 PreparedStatement 對象。
4、用 Connection 對象執行 SQL語句,獲得結果集 ResultSet 對象。
5、然后一條一條讀取結果集 ResultSet 對象中的數據。
6、根據讀取到的數據,按特定的業務邏輯進行計算。
7、根據計算得到的結果再組裝更新 SQL 語句。
8、再使用 Connection 對象執行更新 SQL 語句,以更新數據庫中的數據。
7、最后依次關閉各個 Statement 對象和 Connection 對象。

由上可看出代碼邏輯非常復雜,這還不包括某條語句執行失敗的處理邏輯。其中的業務處理邏輯和數據存取邏輯完全混雜在一塊。而一個完整的系統要包含成千上萬個這樣重復的而又混雜的處理過程,假如要對其中某些業務邏輯或者一些相關聯的業務流程做修改,要改動的代碼量將不可想象。另一方面,假如要換數據庫產品或者運行環境也可能是個不可能完成的任務。而用戶的運行環境和要求卻千差萬別,我們不可能為每一個用戶每一種運行環境設計一套一樣的系統。
所以就要將一樣的處理代碼即業務邏輯和可能不一樣的處理即數據存取邏輯分離開來,另一方面,關系型數據庫中的數據基本都是以一行行的數據進行存取的,而程序運行卻是一個個對象進行處理,而目前大部分數據庫驅動技術(如ADO.NET、JDBC、ODBC等等)均是以行集的結果集一條條進行處理的。所以為解決這一困難,就出現 ORM 這一個對象和數據之間映射技術。

舉例來說,比如要完成一個購物打折促銷的程序,用 ORM 思想將如下實現(引自《深入淺出Hibernate》):
業務邏輯如下:
public Double calcAmount(String customerid, double amount)
{
??? // 根據客戶ID獲得客戶記錄
??? Customer customer = CustomerManager.getCustomer(custmerid);
??? // 根據客戶等級獲得打折規則
??? Promotion promotion = PromotionManager.getPromotion(customer.getLevel());
??? // 累積客戶總消費額,并保存累計結果
??? customer.setSumAmount(customer.getSumAmount().add(amount);
??? CustomerManager.save(customer);
??? // 返回打折后的金額
??? return amount.multiply(protomtion.getRatio());
}
這樣代碼就非常清晰了,而且與數據存取邏輯完全分離。設計業務邏輯代碼的時候完全不需要考慮數據庫JDBC的那些千篇一律的操作,而將它交給 CustomerManager 和 PromotionManager 兩個類去完成。這就是一個簡單的 ORM 設計,實際的 ORM 實現框架比這個要復雜的多。


目前有哪些流行的 ORM 產品
目前眾多廠商和開源社區都提供了持久層框架的實現,常見的有
Apache OJB (http://db.apache.org/ojb/
Cayenne (http://objectstyle.org/cayenne/
Jaxor (http://jaxor.sourceforge.net
Hibernate (http://www.hibernate.org
iBatis (http://www.ibatis.com
jRelationalFramework (http://ijf.sourceforge.net
mirage (http://itor.cq2.org/en/oss/mirage/toon
SMYLE (http://www.drjava.de/smyle
TopLink (http://otn.oracle.com/products/ias/toplink/index.html
其中 TopLink 是 Oracle 的商業產品,其他均為開源項目。

其中 Hibernate 的輕量級 ORM 模型逐步確立了在 Java ORM 架構中領導地位,甚至取代復雜而又繁瑣的 EJB 模型而成為事實上的 Java ORM 工業標準。而且其中的許多設計均被 J2EE 標準組織吸納而成為最新 EJB 3.0 規范的標準,這也是開源項目影響工業領域標準的有力見證。


參考文獻:1、《深入淺出Hibernate》
???????? 2、《精通Hibernate:Java對象持久化技術詳解》



橘子 2006-06-26 09:42 發表評論
]]>
CVS命令篇(二)http://m.tkk7.com/forget/archive/2006/06/22/54416.html橘子橘子Thu, 22 Jun 2006 01:29:00 GMThttp://m.tkk7.com/forget/archive/2006/06/22/54416.htmlhttp://m.tkk7.com/forget/comments/54416.htmlhttp://m.tkk7.com/forget/archive/2006/06/22/54416.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/54416.htmlhttp://m.tkk7.com/forget/services/trackbacks/54416.html關鍵詞:CVS CVSWeb CVSTrac WinCVS CVSROOT

內容摘要:

CVS是一個C/S系統,多個開發人員通過一個中心版本控制系統來記錄文件版本,從而達到保證
文件同步的目的。工作模式如下:

       CVS服務器(文件版本庫)

/ | \

(版 本 同 步)

/ | \

開發者1 開發者2 開發者3




作為一般開發人員挑選2,6看就可以了,CVS的管理員則更需要懂的更多一些,最后還簡單介紹了
一些Windows下的cvs客戶端使用,CVS遠程用戶認證的選擇及與BUG跟蹤系統等開發環境的集成
問題。

  1. CVS環境初始化 :CVS環境的搭建 管理員
  2. CVS的日常使用 :日常開發中最常用的CVS命令, 開發人員 管理員
  3. CVS的分支開發 :項目按照不同進度和目標并發進行 管理員
  4. CVS的用戶認證 :通過SSH的遠程用戶認證,安全,簡單 管理員
  5. CVSWEB :CVS的WEB訪問界面大大提高代碼版本比較的效率 管理員
  6. CVS TAG :將$Id$ 加入代碼注釋中,方便開發過程的跟蹤開發人員
  7. CVS vs VSS : CVS和Virsual SourceSafe的比較 開發人員 管理員
  8. WinCVS: 通過SSH認證的WinCVS認證設置
  9. 基于CVSTrac的小組開發環境搭建 :通過CVSTrac實現web界面的CVS
    用戶管理,集成的BUG跟蹤和WIKI交流
  10. CVS中的用戶權限管理 :基于系統用戶的CVS權限管理和基于CVSROOT/passwd
    的虛擬用戶管理

一個系統20%的功能往往能夠滿足80%的需求,CVS也不例外,以下是CVS最常用的功能,可能還不
到它全部命令選項的20%,作為一般開發人員平時會用cvs update和cvs commit就夠了,更多的需求在
實際應用過程中自然會出現,不時回頭看看相關文檔經常有意外的收獲。


CVS環境初始化

環境設置:指定CVS庫的路徑CVSROOT

tcsh
setenv CVSROOT /path/to/cvsroot
bash
CVSROOT=/path/to/cvsroot ; export CVSROOT

后面還提到遠程CVS服務器的設置:
CVSROOT=:ext:$USER@test.server.address#port:/path/to/cvsroot CVS_RSH=ssh;
export CVSROOT CVS_RSH

初始化:CVS版本庫的初始化。
cvs init

一個項目的首次導入
cvs import -m "write some comments here" project_name vendor_tag release_tag
執行后:會將所有源文件及目錄導入到/path/to/cvsroot/project_name目錄下
vender_tag: 開發商標記
release_tag: 版本發布標記

項目導出:將代碼從CVS庫里導出
cvs checkout project_name
cvs 將創建project_name目錄,并將最新版本的源代碼導出到相應目錄中。這個checkout和Virvual SourceSafe中的check out不是一個概念,相對于Virvual SourceSafe的check out是cvs update,
check in是cvs commit。


CVS的日常使用

注意:第一次導出以后,就不是通過cvs checkout來同步文件了,而是要進入剛才cvs checkout
project_name導出的project_name目錄下進行具體文件的版本同步(添加,修改,刪除)操作。

將文件同步到最新的版本
cvs update
不制定文件名,cvs將同步所有子目錄下的文件,也可以制定某個文件名/目錄進行同步
cvs update file_name
最好每天開始工作前或將自己的工作導入到CVS庫里前都要做一次,并養成“先同步 后修改”的習
慣,和Virvual SourceSafe不同,CVS里沒有文件鎖定的概念,所有的沖突是在commit之前解決,如果
你修改過程中,有其他人修改并commit到了CVS 庫中,CVS會通知你文件沖突,并自動將沖突部分用
>>>>>>
content on cvs server
<<<<<<
content in your file
>>>>>>
標記出來,由你確認沖突內容的取舍。
版本沖突一般是在多個人修改一個文件造成的,但這種項目管理上的問題不應該指望由CVS來解決。

確認修改寫入到CVS庫里
cvs commit -m "write some comments here" file_name

注意:CVS的很多動作都是通過cvs commit進行最后確認并修改的,最好每次只修改一個文件。在確認
的前,還需要用戶填寫修改注釋,以幫助其他開發人員了解修改的原因。如果不用寫-m "comments"而
直接確認`cvs commit file_name` 的話,cvs會自動調用系統缺省的文字編輯器(一般是vi)要求你寫入注釋。
注釋的質量很重要:所以不僅必須要寫,而且必須寫一些比較有意義的內容:以方便其他開發人員能
夠很好的理解不好的注釋,很難讓其他的開發人員快速的理解:比如: -m "bug fixed" 甚至 -m ""
好的注釋,甚至可以用中文: -m "在用戶注冊過程中加入了Email地址校驗"


修改某個版本注釋:每次只確認一個文件到CVS庫里是一個很好的習慣,但難免有時候忘了指定文件
名,把多個文件以同樣注釋commit到CVS庫里了,以下命令可以允許你修改某個文件某個版本的注釋:
cvs admin -m 1.3:"write some comments here" file_name

添加文件
創建好新文件后,比如:touch new_file
cvs add new_file
注意:對于圖片,Word文檔等非純文本的項目,需要使用cvs add -kb選項按2進制文件方式導入(k表示
擴展選項,b表示binary),否則有可能出現文件被破壞的情況
比如:
cvs add -kb new_file.gif
cvs add -kb readme.doc

如果關鍵詞替換屬性在首次導入時設置錯了怎么辦?
cvs admin -kkv new_file.css

然后確認修改并注釋
cvs ci -m "write some comments here"

刪除文件
將某個源文件物理刪除后,比如:rm file_name
cvs rm file_name
然后確認修改并注釋
cvs ci -m "write some comments here"
以上面前2步合并的方法為:
cvs rm -f file_name
cvs ci -m "why delete file"
注意:很多cvs命令都有縮寫形式:commit=>ci; update=>up; checkout=>co/get; remove=>rm;

添加目錄
cvs add dir_name

查看修改歷史
cvs log file_name
cvs history file_name

查看當前文件不同版本的區別
cvs diff -r1.3 -r1.5 file_name
查看當前文件(可能已經修改了)和庫中相應文件的區別
cvs diff file_name
cvs的web界面提供了更方便的定位文件修改和比較版本區別的方法,具體安裝設置請看后面的cvsweb
使用

正確的通過CVS恢復舊版本的方法
如果用cvs update -r1.2 file.name
這個命令是給file.name加一個STICK TAG: "1.2" ,雖然你的本意只是想將它恢復到1.2版本
正確的恢復版本的方法是:cvs update -p -r1.2 file_name >file_name
如果不小心已經加成STICK TAG的話:用cvs update -A 解決

移動文件/文件重命名
cvs里沒有cvs move或cvs rename,因為這兩個操作是可以由先cvs remove old_file_name,然后cvs add new_file_name實現的。

刪除/移動目錄
最方便的方法是讓管理員直接移動,刪除CVSROOT里相應目錄(因為CVS一個項目下的子目錄都是
獨立的,移動到$CVSROOT目錄下都可以作為新的獨立項目:好比一顆樹,其實砍下任意一枝都能獨
立存活),對目錄進行了修改后,要求其開發人員重新導出項目cvs checkout project_name 或者用
cvs update -dP同步。

項目發布導出不帶CVS目錄的源文件
做開發的時候你可能注意到了,每個開發目錄下,CVS都創建了一個CVS/目錄。里面有文件用于記錄
當前目錄和CVS庫之間的對應信息。但項目發布的時候你一般不希望把文件目錄還帶著含有CVS信息
的CVS目錄吧,這個一次性的導出過程使用cvs export命令,不過export只能針對一個TAG或者日期導出,比如:
cvs export -r release1 project_name
cvs export -D 20021023 project_name
cvs export -D now project_name

CVS Branch:項目多分支同步開發

確認版本里程碑:多個文件各自版本號不一樣,項目到一定階段,可以給所有文件統一指定一個階段
里程碑版本號,方便以后按照這個階段里程碑版本號導出項目,同時也是項目的多個分支開發的基礎。

cvs tag release_1_0

開始一個新的里程碑
cvs commit -r 2 標記所有文件開始進入2.x的開發

注意:CVS里的revsion和軟件包的發布版本可以沒有直接的關系。但所有文件使用和發布版本一致的
版本號比較有助于維護。

版本分支的建立
在開發項目的2.x版本的時候發現1.x有問題,但2.x又不敢用,則從先前標記的里程碑:release_1_0導出
一個分支 release_1_0_patch
cvs rtag -b -r release_1_0 release_1_0_patch proj_dir

一些人先在另外一個目錄下導出release_1_0_patch這個分支:解決1.0中的緊急問題,
cvs checkout -r release_1_0_patch
而其他人員仍舊在項目的主干分支2.x上開發

在release_1_0_patch上修正錯誤后,標記一個1.0的錯誤修正版本號
cvs tag release_1_0_patch_1

如果2.0認為這些錯誤修改在2.0里也需要,也可以在2.0的開發目錄下合并release_1_0_patch_1中的修改到
當前代碼中:
cvs update -j release_1_0_patch_1

CVS的遠程認證通過SSH遠程訪問CVS

使用cvs本身基于pserver的遠程認證很麻煩,需要定義服務器和用戶組,用戶名,設置密碼等,

常見的登陸格式如下:
cvs -d :pserver:cvs_user_name@cvs.server.address:/path/to/cvsroot login
例子:
cvs -d :pserver:cvs@samba.org:/cvsroot login

不是很安全,因此一般是作為匿名只讀CVS訪問的方式。從安全考慮,通過系統本地帳號認證并通過
SSH傳輸是比較好的辦法,通過在客戶機的 /etc/profile里設置一下內容:
CVSROOT=:ext:$USER@cvs.server.address#port:/path/to/cvsroot CVS_RSH=ssh; export CVSROOT CVS_RSH
所有客戶機所有本地用戶都可以映射到CVS服務器相應同名帳號了。

比如:

CVS服務器是192.168.0.3,上面CVSROOT路徑是/home/cvsroot,另外一臺開發客戶機是192.168.0.4,
如果 tom在2臺機器上都有同名的帳號,那么從192.168.0.4上設置了:
export CVSROOT=:ext:tom@192.168.0.3:/home/cvsroot
export CVS_RSH=ssh
tom就可以直接在192.168.0.4上對192.168.0.3的cvsroot進行訪問了(如果有權限的話)
cvs checkout project_name
cd project_name
cvs update
...
cvs commit

如果CVS所在服務器的SSH端口不在缺省的22,或者和客戶端與CVS服務器端SSH缺省端口不一致,
有時候設置了:
:ext:$USER@test.server.address#port:/path/to/cvsroot

仍然不行,比如有以下錯誤信息:
ssh: test.server.address#port: Name or service not known
cvs [checkout aborted]: end of file from server (consult above messages if any)

解決的方法是做一個腳本指定端口轉向(不能使用alias,會出找不到文件錯誤):
創建一個/usr/bin/ssh_cvs文件,假設遠程服務器的SSH端口是非缺省端口:34567
#!/bin/sh
/usr/bin/ssh -p 34567 "$@"
然后:chmod +x /usr/bin/ssh_cvs
并CVS_RSH=ssh_cvs; export CVS_RSH

注意:port是指相應服務器SSH的端口,不是指cvs專用的pserver的端口

CVSWEB:提高文件瀏覽效率

CVSWEB就是CVS的WEB界面,可以大大提高程序員定位修改的效率:

使用的樣例可以看:http://www.freebsd.org/cgi/cvsweb.cgi

CVSWEB的下載:CVSWEB從最初的版本已經演化出很多功能界面更豐富的版本,這個是我個人感
覺安裝設置比較方便的:
原先在:http://www.spaghetti-code.de/software/linux/cvsweb/,但目前已經刪除,目前仍可以在本站下載CVSWEB,其實最近2年FreeBSD的CVSWeb項目已經有了更好的發展吧,而當初沒有用FreeBSD那個
版本主要就是因為沒有彩色的文件Diff功能。
下載解包:
tar zxf cvsweb.tgz
把配置文件cvsweb.conf放到安全的地方(比如和apache的配置放在同一個目錄下),
修改:cvsweb.cgi讓CGI找到配置文件:
$config = $ENV{'CVSWEB_CONFIG'} || '/path/to/apache/conf/cvsweb.conf';

轉到/path/to/apache/conf下并修改cvsweb.conf:

  1. 修改CVSROOT路徑設置:
    %CVSROOT = (
    'Development' => '/path/to/cvsroot', #<==修改指向本地的CVSROOT
    );
  2. 缺省不顯示已經刪除的文檔:
    "hideattic" => "1",#<==缺省不顯示已經刪除的文檔
  3. 在配置文件cvsweb.conf中還可以定制頁頭的描述信息,你可以修改$long_intro成你需要的文字

CVSWEB可不能隨便開放給所有用戶,因此需要使用WEB用戶認證:
先生成 passwd:
/path/to/apache/bin/htpasswd -c cvsweb.passwd user

修改httpd.conf: 增加
<Directory "/path/to/apache/cgi-bin/cvsweb/">
AuthName "CVS Authorization"
AuthType Basic
AuthUserFile /path/to/cvsweb.passwd
require valid-user
</Directory>

CVS TAGS: $Id: cvs_card.html,v 1.5 2003/03/09 08:41:46

chedong Exp $

將$Id: cvs_card.html,v 1.9 2003/11/09 07:57:11 chedong Exp $ 加在程序文件開頭的注釋里是一個很好
的習慣,cvs能夠自動解釋更新其中的內容成:file_name version time user_name 的格式,比如:
cvs_card.txt,v 1.1 2002/04/05 04:24:12 chedong Exp,可以這些信息了解文件的最后修改人和修改時間


幾個常用的缺省文件:
default.php
<?php
/*
* Copyright (c) 2002 Company Name.
* $Header: /home/cvsroot/tech/cvs_card.html,v 1.9 2003/11/09 07:57:11
chedong Exp $

*/

?>
====================================
Default.java: 注意文件頭一般注釋用 /* 開始 JAVADOC注釋用 /** 開始的區別
/*
* Copyright (c) 2002 MyCompany Name.
* $Header: /home/cvsroot/tech/cvs_card.html,v 1.9 2003/11/09 07:57:11
chedong Exp $

*/

package com.mycompany;

import java.;

/**
* comments here
*/
public class Default {
/**
* Comments here
* @param
* @return
*/
public toString() {

}
}
====================================
default.pl:
#!/usr/bin/perl -w
# Copyright (c) 2002 Company Name.
# $Header: /home/cvsroot/tech/cvs_card.html,v 1.9 2003/11/09 07:57:11
chedong Exp $


# file comments here

use strict;

CVS vs VSS

CVS沒有文件鎖定模式,VSS在check out同時,同時記錄了文件被導出者鎖定。

CVS的update和commit, VSS是get_lastest_version和check in

對應VSS的check out/undo check out的CVS里是edit和unedit

在CVS中,標記自動更新功能缺省是打開的,這樣也帶來一個潛在的問題,就是不用-kb方式添加
binary文件的話在cvs自動更新時可能會導致文件失效。

$Header: /home/cvsroot/tech/cvs_card.html,v 1.5 2003/03/09 08:41:46 chedong Exp $ $Date: 2003/11/09
07:57:11 $這樣的標記在Virsual SourceSafe中稱之為Keyword Explaination,缺省是關閉
的,需要通過OPITION打開,并指定需要進行源文件關鍵詞掃描的文件類型:*.txt,*.java, *.html...

對于Virsual SourceSafe和CVS都通用的TAG有:
$Header: /home/cvsroot/tech/cvs_card.html,v 1.5 2003/03/09 08:41:46 chedong Exp $
$Author: chedong $
$Date: 2003/11/09 07:57:11 $
$Revision: 1.9 $

我建議盡量使用通用的關鍵詞保證代碼在CVS和VSS都能方便的跟蹤。

WinCVS

下載:

cvs Windows客戶端:目前穩定版本為1.2
http://cvsgui.sourceforge.net
ssh Windows客戶端
http://www.networksimplicity.com/openssh/

安裝好以上2個軟件以后:
WinCVS客戶端的admin==>preference設置
1 在general選單里
設置CVSROOT: username@192.168.0.123:/home/cvsroot
設置Authorization: 選擇SSH server

2 Port選單里
鉤上:check for alternate rsh name
并設置ssh.exe的路徑,缺省是裝在 C:\Program Files\NetworkSimplicity\ssh\ssh.exe

然后就可以使用WinCVS進行cvs操作了,所有操作都會跳出命令行窗口要求你輸入服務器端的認
證密碼。

當然,如果你覺得這樣很煩的話,還有一個辦法就是生成一個沒有密碼的公鑰/私鑰對,并設置
CVS使用基于公鑰/私鑰的SSH認證(在general 選單里)。

可以選擇的diff工具:examdiff
下載:
http://www.prestosoft.com/examdiff/examdiff.htm
還是在WinCVS菜單admin==>preference的WinCVS選單里
選上:Externel diff program
并設置diff工具的路徑,比如:C:\Program Files\ed16i\ExamDiff.exe
在對文件進行版本diff時,第一次需要將窗口右下角的use externel diff選上。

基于CVSTrac的小組開發環境搭建

作為一個小組級的開發環境,版本控制系統和BUG跟蹤系統等都涉及到用戶認證部分。如何方便的
將這些系統集成起來是一個非常困難的事情,畢竟我們不能指望 Linux下有像Source Offsite那樣集成
度很高的版本控制/BUG跟蹤集成系統。

我個人是很反對使用pserver模式的遠程用戶認證的,但如果大部分組員使用WINDOWS客戶端進行
開發的話,總體來說使用 CVSROOT/passwd認證還是很難避免的,但CVS本身用戶的管理比較麻煩
本來我打算自己用perl寫一個管理界面的,直到我發現了 CVSTrac:一個基于WEB界面的BUG跟蹤
系統,它外掛在CVS系統上的BUG跟蹤系統,其中就包括了WEB界面的CVSROOT/passwd文件的管
理,甚至還集成了WIKI討論組功能。

這里首先說一下CVS的pserver模式下的用戶認證,CVS的用戶認證服務是基于inetd中的:
cvspserver stream tcp nowait apache /usr/bin/cvs cvs --allow-root=/home/cvsroot pserver
一般在2401端口(這個端口號很好記:49的平方)

CVS用戶數據庫是基于CVSROOT/passwd文件,文件格式:
[username]:[crypt_password]:[mapping_system_user]
由于密碼都用的是UNIX標準的CRYPT加密,這個passwd文件的格式基本上是apache的htpasswd格式
的擴展(比APACHE的 PASSWD文件多一個系統用戶映射字段),所以這個文件最簡單的方法可
以用
apache/bin/htpasswd -b myname mypassword
創建。注意:通過htpasswd創建出來的文件會沒有映射系統用戶的字段
例如:
new:geBvosup/zKl2
setup:aISQuNAAoY3qw
test:hwEpz/BX.rEDU

映射系統用戶的目的在于:你可以創建一個專門的CVS服務帳號,比如用apache的運行用戶apache,
并將/home/cvsroot目錄下的所有權限賦予這個用戶,然后在passwd文件里創建不同的開發用戶帳號,
但開發用戶帳號最后的文件讀寫權限都映射為apache用戶,在SSH模式下多個系統開發用戶需要在
同一個組中才可以相互讀寫CVS庫中的文件。

進一步的,你可以將用戶分別映射到apache這個系統用戶上。
new:geBvosup/zKl2:apache
setup:aISQuNAAoY3qw:apache
test:hwEpz/BX.rEDU:apache

CVSTrac很好的解決了CVSROOT/passwd的管理問題,而且包含了BUG跟蹤報告系統和集成WIKI交

功能等,使用的 CGI方式的安裝,并且基于GNU Public License

在inetd里加入cvspserver服務:
cvspserver stream tcp nowait apache /usr/bin/cvs cvs --allow-root=/home/cvsroot pserver

xietd的配置文件:%cat cvspserver
service cvspserver
{
disable = no
socket_type = stream
wait = no
user = apache
server = /usr/bin/cvs
server_args = -f --allow-root=/home/cvsroot pserver
log_on_failure += USERID
}

注意:這里的用戶設置成apache目的是和/home/cvsroot的所有用戶一致,并且必須讓這個這個用戶對/home/cvsroot/下的 CVSROOT/passwd和cvstrac初始化生成的myproj.db有讀取權限。

安裝過程

  1. 下載:可以從http://www.cvstrac.org 下載
    我用的是已經在Linux上編譯好的應用程序包:cvstrac-1.1.2.bin.gz,
    %gzip -d cvstrac-1.1.2.bin.gz
    %chmod +x cvstrac-1.1.2.bin
    #mv cvstarc-1.1.1.bin /usr/bin/cvstrac
    如果是從源代碼編譯:
    從 http://www.sqlite.org/download.html 下載SQLITE的rpm包:
    rpm -i sqlite-devel-2.8.6-1.i386.rpm
    從 ftp://ftp.cvstrac.org/cvstrac/ 下載軟件包
    解包,假設解包到/home/chedong/cvstrac-1.1.2下,并規劃將cvstrac安裝到/usr/local/bin目錄下, cd /home/chedong/cvstrac-1.1.2 編輯linux-gcc.mk:
    修改:
    SRCDIR = /home/chedong/cvstrac-1.1.2
    INSTALLDIR = /usr/local/bin
    然后
    mv linux-gcc.mk Makefile
    make
    #make install

  2. 初始化cvstrac數據庫:假設數據庫名是 myproj
    在已經裝好的CVS服務器上(CVS庫這時候應該已經是初始化好了,比如:cvs init初始化在/home/cvsroot里),運行一下
    %cvstrac init /home/cvsroot myproj
    運行后,/home/cvsroot里會有一個的myproj.db庫,使用CVSTRAC服務,/home/cvsroot/myproj.db /home/cvsroot/CVSROOT/readers
    /home/cvsroot/CVSROOT/writers /home/cvsroot/CVSROOT/passwd這幾個文件對于web服務的運行
    用戶應該是可寫的,在RedHat8上,缺省就有一個叫 apache用戶和一個apache組,所以在
    httpd.conf文件中設置了用apache用戶運行web服務:
    User apache
    Group apache,
    然后設置屬于apache用戶和apache組
    #chown -R apache:apache /home/cvsroot
    -rw-r--r-- 1 apache apache 55296 Jan 5 19:40 myproj.db
    drwxrwxr-x 3 apache apache 4096 Oct 24 13:04 CVSROOT/
    drwxrwxr-x 2 apache apache 4096 Aug 30 19:47 some_proj/
    此外還在/home/cvsroot/CVSROOT中設置了:
    chmod 664 readers writers passwd
  3. 在apche/cgi-bin目錄中創建腳本cvstrac:
    #!/bin/sh
    /usr/bin/cvstrac cgi /home/cvsroot
    設置腳本可執行:
    chmod +x /home/apache/cgi-bin/cvstrac
  4. 從 http://cvs.server.address/cgi-bin/cvstrac/myproj 進入管理界面
    缺省登錄名:setup 密碼 setup
    對于一般用戶可以從:
    http://cvs.server.address/cgi-bin/cvstrac/myproj
  5. 在setup中重新設置了CVSROOT的路徑后,/home/cvsroot
    如果是初次使用需要在/home/cvsroot/CVSROOT下創建passwd, readers, writers文件
    touch passwd readers writers
    然后設置屬于apache用戶,
    chown apache.apache passwd readers writers
    這樣使用setup用戶創建新用戶后會同步更新CVSROOT/passwd下的帳號

修改登錄密碼,進行BUG報告等,
更多使用細節可以在使用中慢慢了解。

對于前面提到的WinCVS在perference里設置:
CVSROOT欄輸入:username@ip.address.of.cvs:/home/cvsroot
Authenitication選擇:use passwd file on server side
就可以了從服務器上進行CVS操作了。

CVS的用戶權限管理

CVS的權限管理分2種策略:

  • 基于系統文件權限的系統用戶管理:適合多個在Linux上使用系統帳號的開發人員進行開發。
  • 基于CVSROOT/passwd的虛擬用戶管理:適合多個在Windows平臺上的開發人員將帳號映射
    成系統帳號使用。
為什么使用apache/apache用戶?首先RedHat8中缺省就有了,而且使用這個用戶可以方便通過cvstrac
進行WEB管理。
chown -R apache.apache /home/cvsroot
chmod 775 /home/cvsroot

Linux上通過ssh連接CVS服務器的多個開發人員:通過都屬于apache組實現文件的共享讀寫開發人員
有開發服務器上的系統帳號:sysuser1 sysuser2,設置讓他們都屬于apache組,因為通過cvs新導入的
項目都是對組開放的:664權限的,這樣無論那個系統用戶導入的項目文件,只要文件的組宿主是apache,所有其他同組系統開發用戶就都可以讀寫;基于ssh遠程認證的也是一樣。

? ?apache(system group)
/ ? ? ? ? ? ?| ? ? ? ? ? \
sysuser1 ? sysuser2 ? ? sysuser3

Windows上通過cvspserver連接CVS服務器的多個開發人員:通過在passwd文件種映射成 apache用戶
實現文件的共享讀寫
他們的帳號通過CVSROOT/passwd和readers writers這幾個文件管理;通過cvstrac設置所有
虛擬用戶都映射到apache用戶上即可。

? ?apache(system user)
/ ? ? ? ? ? ?| ? ? ? ? ? ?\
windev1 ? ? windev2 ? ? ?windev3? ? ? ? ? ? ?

利用CVS WinCVS/CVSWeb/CVSTrac 構成了一個相對完善的跨平臺工作組開發版本控制環境。

相關資源:

CVS HOME:
http://www.cvshome.org

CVS FAQ:
http://www.loria.fr/~molli/cvs-index.html

相關網站:
http://directory.google.com/Top/Computers/Software/Configuration_Management/Tools/Concurrent_
Versions_System/

CVS--并行版本系統
http://www.soforge.com/cvsdoc/zh_CN/book1.html

CVS 免費書:
http://cvsbook.red-bean.com/

CVS命令的速查卡片 refcards.com/refcards/cvs/

WinCVS:
http://cvsgui.sourceforge.net/

CVSTrac: A Web-Based Bug And Patch-Set Tracking System For CVS
http://www.cvstrac.org

StatCVS:基于CVS的代碼統計工具:按代碼量,按開發者的統計表等
http://sourceforge.net/projects/statcvs

如何在WEB開發中規劃CVS上:在Google上查 "cvs web development"
http://ccm.redhat.com/bboard-archive/cvs_for_web_development/index.html
轉載:作者: 車東 Email: chedongATbigfoot.com/chedongATchedong.com
http://flysun163.spaces.msn.com/blog/

橘子 2006-06-22 09:29 發表評論
]]>
CVSNT用戶管理方案篇http://m.tkk7.com/forget/archive/2006/06/22/54393.html橘子橘子Wed, 21 Jun 2006 17:28:00 GMThttp://m.tkk7.com/forget/archive/2006/06/22/54393.htmlhttp://m.tkk7.com/forget/comments/54393.htmlhttp://m.tkk7.com/forget/archive/2006/06/22/54393.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/54393.htmlhttp://m.tkk7.com/forget/services/trackbacks/54393.html1、 CVSNT的用戶驗證方式
我們這里所討論的是工作在pserver方式下。
在CVSNT的文檔中給出了兩種驗證方式,我總結了一下,可以這樣稱呼:Window和CVSNT混合驗證方式,CVSNT獨立驗證方式。在前面的文章中,我們沒有詳細的給出這兩種方式的內容,所講述的啟示就是混合驗證方式。
決定CVSNT工作于何種驗證方式是由CVS的管理文件來決定的,這些管理文件處在庫的目錄下的CVSROOT目錄中,這里可以得出結論,對于不同的庫,可以給不同的驗證方式。所以,在每個庫建立的時候要首先設定好這些前提。
下面的操作如果沒有特殊指出則都是在客戶端來進行管理的,下面首先是對一些控制原理和相關的文件做一些說明,如果你正在進行相關的模擬操作,請停下來暫時停止你的操作,因為這些操作的步驟是有先后的,如果你順序不對,那么你可能就權限失效,進行不了下面的操作了。
1.1 config文件
在庫建立好了以后,你還沒有對控制文件進行修改之前,CVSNT是工作在混合驗證方式之下的,這個時候,CVS服務器的管理員就是CVSNT的管理員,你以一個管理員身份登陸,檢出你要操作的庫的CVSROOT模塊,看一下文件列表,控制CVSNT的驗證工作方式的是config文件,你可以在文件列表中找到它,雙擊看看其中的內容,這里對我們最重要的就是第一個設置內容,你會看到下面的內容:
# Set this to `no' if pserver shouldn't check system users/passwords
#SystemAuth=yes
第二行就是我們要修改的內容,默認狀態是被注釋掉的,SystemAuth有兩個值yes和no
yes:pserver將使用系統用戶數據庫和passwd文件(這個文件后面會詳細講述)來共同驗證(若passwd文件不存在或者文件中沒有相應的資料,則用系統用戶來進行驗證)默認為yes
no:所有的用戶必須在passwd中存在,根據passwd的內容來進行用戶的驗證。
我這里所闡述的方案就是工作在no的下面的,修改完之后提交到服務器,提交完畢服務器就處在CVSNT的獨立驗證模式下了。在這個工作方式下,NT本地的用戶和CVSNT用戶沒有任何本質的聯系和影響(僅僅是要建立一個別名)。
1.2 passwd文件
在講述上面的時候提到了這個文件,在服務器工作在CVSNT驗證模式下的時候,這個文件就可以稱之為CVSNT的用戶數據庫,這個里面存儲著用戶列表,用戶的密碼,以及別名的一些信息。默認狀態下這個文件是不存在的,所以,如果我們要在CVSNT驗證模式下工作,必須建立這個文件。注意:這個文件是不能夠在客戶端進行修改的。這個文件的內容是相當簡單的,就像下面:
bach:ULtgRLXo7NRxs
spwang:1sOp854gDF3DY
melissa:tGX1fS8sun6rY:pubcvs
qproj:XR4EZcEs0szik:pubcvs
這里分別拿第一個用戶bach和第三個用戶melissa來進行說明,每一行代表一個用戶,總共有三部分信息,用戶名、密碼、本地用戶三部分之間使用冒號“:”來進行分割。
用戶名:就是登陸CVS的用戶名
密 碼:用戶的密碼,這里是經過加密的,如果為空,那么就是空密碼
本地用戶:CVS用戶這個別名對應的本地用戶,(跟本地用戶沒有任何其他關系,僅僅是別名的關系)
如果在本地系統中存在一個用戶名bash,那么要在CVS建立一個bach這樣的用戶就不需要在后面指出對應的系統用戶,melissa后面的pubcvs就是系統用戶,在本地系統上面存在的用戶。對于要用命令增加這兩種用戶的格式如下:
cvspasswd –a bach
cvspasswd –r pubcvs –a melissa
在庫建立的時候可以在服務器上建立一個簡單的passwd初始化文件,加一行
cvsadmin:
這樣,就給出了一個cvsadmin這個空密碼用戶(本地系統中有這樣的用戶,就可以不加到后面去),然后在客戶端來進行修改和以后的用戶增加工作。注意:在客戶端進行其他之前請先首先修改這個密碼,以防止別人進行破壞。
在服務器端建立了這個文件以后,就不用再手動進行修改了,當你在客戶端進行密碼或者用戶的增加刪除的時候,系統會自動進行這個文件的更新。這個文件是管理著CVSNT系統中的所有的用戶,所以,要特別重視,不了解這個文件格式的,不要去隨便修改,更加不要嘗試在客戶端進行修改!
1.3 admin文件
這個文件是指定CVSNT的管理員列表的文件,CVSNT會根據這個文件中的內容來判斷一個用戶是否是管理員。這個文件的內容很簡單,是一個用戶列表。類似下面
user1
user2
user3
這些代表user1,user2,user3都是管理員,當然,這些用戶必須要存在才能夠正確登陸系統來執行管理。
這個文件默認狀態下是沒有的,但是,可以在客戶端進行添加,在你的客戶端進行新建這個文件然后add上去再commit一下,這個文件就可以上傳到服務器,但是這個時候還沒有生效,請修改checkoutlist這個文件,加入admin這一行,checkoutlist也可以在客戶端進行修改再提交,這個時候admin就可以被系統自動的build了。
Checkoutlist是維護的一個文件列表,可以放入系統自動build的用戶自定義的系統文件列表,注意:對passwd沒有用!!
1.4 group文件
這個文件是定義系統的組,我們可以將同樣性質的用戶歸入一個組,然后用給用戶賦權限的方式給組賦權限,這樣,一個組的用戶就會具有同樣的權限。Group的內容如下:
group1:user1 user2 user3
group2:me you he
group3:tom honey
有上面可以看出來,這個文件的內容也是相當的簡單,首先是組的名稱然后是冒號,接著是用戶名,多個用戶名之間用空格來進行分割。
Group文件可以在客戶端進行新建和修改,不用修改checkoutlist這個文件,系統會自動build這個文件并且使之生效。
作為組里面的特定成員還可以賦給特定的權限,權限分為兩類c,w,r和n,否定權限是有高的優先級的。
好,上面已經介紹了本方案所涉及到的幾個重要的文件以及修改方式。這里再強調一下,passwd只能夠再服務器端進行建立和修改,不能夠在客戶端進行操作!
現在根據上面介紹的內容,可以開始你的操作了,下面給出修改順序,庫剛剛建立起來的時候,使用一個服務器上的本地管理員用戶進行登陸檢出CVSROOT模塊。
1、 現在服務器端加上passwd文件,給一個初始的用戶,比如cvsadmin:
2、 在客戶端增加admin,將cvsadmin加入admin文件,作為出是管理員,并提交加入到庫中。
3、 在修改checkoutlist文件,加入admin,使其能夠自動build。
4、 最后修改config文件的SystemAuth=no,在提交之前要確認一下你上面的修改是否正確,如果提交了這個文件,CVSNT驗證模式就開始生效了!
5、 好,現在請修改你的參數再重新進行的登陸吧。因為你的系統已經切換了工作模式,你當前的用戶已經失效了。
完成了上面的步驟,整個服務器就會有效的工作在CVSNT驗證模式下了。而group文件在你需要的任何時候可以加入。
在上面的文章關于CVSNT的用戶的管理方案的,在這里做一點補充,在后面的操作中全部是針對在客戶端使用WinCVS來進行的(出了增加passwd)文件,其實,在我的實踐當中config,passwd,admin,checkoutlist,這些文件的起始修改(初始化)都可以在新建了庫以后一起完成,然后再讓相應的庫的管理員來進行相關的操作。
轉載至:http://www.51cmm.com/casepanel/CM/No051.htm

橘子 2006-06-22 01:28 發表評論
]]>
CVSNT命令篇http://m.tkk7.com/forget/archive/2006/06/22/54392.html橘子橘子Wed, 21 Jun 2006 17:26:00 GMThttp://m.tkk7.com/forget/archive/2006/06/22/54392.htmlhttp://m.tkk7.com/forget/comments/54392.htmlhttp://m.tkk7.com/forget/archive/2006/06/22/54392.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/54392.htmlhttp://m.tkk7.com/forget/services/trackbacks/54392.html在得到CVSROOT和你的口令之后,你就可以試著登陸了。

首先,由于其他所有的GUI工具都是基于CVS基本協議的,而且他們可能會提供CVS的命令行或者等價形
式作為顯示的一部分,所以你應該對命令行操作有所了解。如果你還沒有一個cvs。exe的命令行程序,從
www.cvsnt.org你可以得到一個cvsnt的下載連接,其中就包含了一個命令行的cvs.exe程序。我們先從它開始
(為了作為一個client使用,你不需要安裝cvsnt的server組件)。CVSNT的cvs.exe是專門為windows編寫的,你
需要把cvs.exe放在你的path里面。

1.進入命令行方式。

和VSS一樣,你也需要在本地有一個工作目錄對應于一個repository。假設這個目錄是'd:\works\sandbox'。
請切換到這個目錄。

輸入"cvs"。你會看到:


這些提示信息告訴您關于cvs的基本語法。cvs后面跟著的是全局參數,然后是命令,最后是命令的參數。

2.login


正確的login不會有任何輸出,否則會告訴你錯誤原因。


如果login失敗,則可以先嘗試命令:set cvsroot=:pserver:cao@IP或者計算機名字/CVSRoot

3.下面我們看看這個CVS server中有哪些module。


4.假設現在我們工作的項目是projectX,下面我們需要得到它下面的全部文件。


現在讓我們看一下我們得到了什么。


在d:/works/sandbox目錄下,你可以看到有一個projectX目錄。這就是你得到的所有文件。

這個目錄下你會發現一個叫做 CVS的目錄。危險!請不要刪除這個目錄,或者改名,或者改動其中的
任何文件,除非你知道你在做什么。這個目錄是CVS的控制目錄。如果你用過source safe,你一定很熟悉。scc這個文件,CVS目錄的作用就和這個控制文件一樣,都是用來記錄你訪問服務器的參數。

這里我們需要解釋一下cvs和VSS的名詞差別。在VSS中,checkout意味著你將獲得一個文件的修改權,而
cvs中checkout的這個含義取消了,僅僅指取得文件的新版本。很多cvs server會有一個anonymous用戶,他
只有checkout權限,也就意味著它只讀。???

				

5.讓我們試著加入一個文件:
在d:/works/sandbox/projectX下,新建一個文件newfile.txt,



然后,在這個目錄下執行:





你需要commit它才能被sever接受。




一個notepad窗口彈出請您輸入注釋。



這是commit完成的結果。現在的版本號是1.1。

6.好了,現在假設您需要改一下這個文件的內容。


CVS可以幫助您比較現在您的版本和repository中的版本有什么不同。

好了,現在您可以提交您的新文件。

CVS會幫您保留您的各個版本。在commit之后,現在我們來看一看各個版本的history。

7.最后,為了完成這個試驗,請把這個newfile文件刪去。

我們現在認識了一些最基本的CVS入門級指令。
其實CVS是非常強大的,我們并沒有用到一些更復雜的功能,請參閱cvs的手冊來得到更為詳盡的幫助。
轉載至:http://www.redsaga.com/CVS_newbie_win32/



橘子 2006-06-22 01:26 發表評論
]]>
CVS相關配置使用http://m.tkk7.com/forget/archive/2006/06/21/54112.html橘子橘子Wed, 21 Jun 2006 01:15:00 GMThttp://m.tkk7.com/forget/archive/2006/06/21/54112.htmlhttp://m.tkk7.com/forget/comments/54112.htmlhttp://m.tkk7.com/forget/archive/2006/06/21/54112.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/54112.htmlhttp://m.tkk7.com/forget/services/trackbacks/54112.html1、下載CVSNT一路默認安裝,在選擇安裝類型時,應該選擇完全安裝。一路裝好ok,重啟動系統,在控制面板多了個東東。并且可以在服務控制器中發現多了2個服務:cvsnt與cvslocking,雙擊Service Control Panel快捷方式,在Service Status頁面,會看見cvs server 和 cvs lock server2個服務正常和穩定運行

2、切換到Advanced,先在Use local users for pserver authentication instead of domain users和Pretend to be a Unix CVS version鉤上,這是讓CVSNT使用本地賬戶作為pserver認證方式以及讓CVSNT服務器模擬為Unix CVS服務器,如圖:

3、選擇Repository頁面,點按Add按鈕,選擇已經準備好的F:\Root這個目錄,確認,OK,Yes,這時會在F:\Root下面建立一個CVSRoot目錄,這是CVS默認的管理目錄(默認模塊)。如果報錯,那是系統Path路徑未設置正確。
?
4、CVSNT的用戶驗證方式:我會專門找一篇寫得全的另外寫。

5、打開一個cmd窗口,輸入命令set cvsroot=:pserver:sunxdd@server/Root(sunxdd是剛才建立的用戶名,server是安裝的計算機名稱或者IP,/Root是剛才建立的文件夾別名,每次登陸之前都要這樣告訴系統建立這樣一個環境變量)
cvs login
密碼為空
這時會登錄成功
改密碼
cvs passwd

到這里CVSNT服務器基本上搞定了。


有用的資源:
http://edu.tmn.cn/html/5/47/185/2005210/104247.htm
http://www.redsaga.com/CVS_newbie_win32/#tortoisecvs
http://sunxdd.blogchina.com/2338489.html



橘子 2006-06-21 09:15 發表評論
]]>
php開發wap常用技巧http://m.tkk7.com/forget/archive/2006/06/17/53462.html橘子橘子Sat, 17 Jun 2006 03:43:00 GMThttp://m.tkk7.com/forget/archive/2006/06/17/53462.htmlhttp://m.tkk7.com/forget/comments/53462.htmlhttp://m.tkk7.com/forget/archive/2006/06/17/53462.html#Feedback1http://m.tkk7.com/forget/comments/commentRss/53462.htmlhttp://m.tkk7.com/forget/services/trackbacks/53462.html在php中輸出返回上一級的代碼:
echo "<a href=".$_SERVER["HTTP_REFERER"].">點擊這里返回</a>";
在wap中的代碼是:
<?php
@header("Content-Type:text/vnd.wap.wml");
?>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.3//EN" "<wml>
<head>
<meta http-equiv="expires" content="0" />
</head>
<card title="輸入標題">
<do type="prev" label="返回上頁">
<prev/>
<!--provide a button you can clink to back a step-->
</do><br/>
<!--<anchor>
<prev/>后退
</anchor>-->?
</card>
</wml>
在wap中打電話的代碼:
<?php
?@header("Content-Type:text/vnd.wap.wml");
?>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.3//EN" "
<wml>
<head>
<meta http-equiv="expires" content="0" />
</head>
<card title="標題">
<p>
<input name="phone_no" format="*m" value="13"/>
<do type="option" >
<go href="wtai://wp/mc;$(phone_no)"/>
</do><br/>
或者
<a href="wtai://wp/mc;13333333333">撥打電話</a>
<br />
</p>
</card>
</wml>

加入WAP書簽

<?xml version="1.0"?>
<!DOCTYPE CHARACTERISTIC-LIST SYSTEM "/DTD/characteristic_list.xml">
<CHARACTERISTIC-LIST>
<CHARACTERISTIC TYPE="ADDRESS">
<PARM NAME="BEARER" VALUE="GPRS"/>
<PARM NAME="PROXY" VALUE="10.0.0.172"/>
<PARM NAME="PORT" VALUE="9201"/>
<PARM NAME="GPRS_ACCESSPOINTNAME" VALUE="wap.02826.com"/>
<PARM NAME="PPP_AUTHTYPE" VALUE="PAP"/>
</CHARACTERISTIC>
<CHARACTERISTIC TYPE="NAME">
<PARM NAME="NAME" VALUE="wmzsoft GPRS"/>
</CHARACTERISTIC>
<CHARACTERISTIC TYPE="BOOKMARK"/>
<PARM NAME="NAME" VALUE="02826"/>
<PARM NAME="URL" VALUE="
http://wap.02826.com "/>
</CHARACTERISTIC>
</CHARACTERISTIC-LIST>


橘子 2006-06-17 11:43 發表評論
]]>
點中復選框使得復選框后的文本框內容顯示出指定的內容http://m.tkk7.com/forget/archive/2006/06/09/51764.html橘子橘子Fri, 09 Jun 2006 15:08:00 GMThttp://m.tkk7.com/forget/archive/2006/06/09/51764.htmlhttp://m.tkk7.com/forget/comments/51764.htmlhttp://m.tkk7.com/forget/archive/2006/06/09/51764.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/51764.htmlhttp://m.tkk7.com/forget/services/trackbacks/51764.html<!--
function test(obj) {
??? if (obj.checked) {document.all(obj.name+'_t').value=obj.value}
??? else {document.all(obj.name+'_t').value=''}
}
//-->
</script>
<input type="checkbox" name="cb1" value="aaaa" onClick="test(this)">aaaa
<input type="text" name="cb1_t">
<br>
<input type="checkbox" name="cb2" value="bbbb" onClick="test(this)">bbbb
<input type="text" name="cb2_t">
<br>
<input type="checkbox" name="cb3" value="cccc" onClick="test(this)">cccc
<input type="text" name="cb3_t">
<br>
<input type="checkbox" name="cb4" value="dddd" onClick="test(this)">dddd
<input type="text" name="cb4_t">

這樣一來 如果想輸入某個確定的值時就不用那么辛辛苦苦的復制了,點擊就自動選擇!

橘子 2006-06-09 23:08 發表評論
]]>
php上傳多個文件http://m.tkk7.com/forget/archive/2006/06/08/51520.html橘子橘子Thu, 08 Jun 2006 14:31:00 GMThttp://m.tkk7.com/forget/archive/2006/06/08/51520.htmlhttp://m.tkk7.com/forget/comments/51520.htmlhttp://m.tkk7.com/forget/archive/2006/06/08/51520.html#Feedback1http://m.tkk7.com/forget/comments/commentRss/51520.htmlhttp://m.tkk7.com/forget/services/trackbacks/51520.html前面提到了上傳單個文件的方法,上傳多個文件的思想類似
1、在表單頁面動態生成多個文件提交框,這里注意一下,多個文件提交框的名字要設置為數組,否則只有一個文件會上傳。
此時在$_FILES數組構造方式是這樣:$_FILES["files"][xxxxfileProperty][xxxcount]; 比如說我要知道第一個文件的error值:$_FILES["userfiles"]["error"][0] ,第一個文件客戶端名字:$_FILES["userfiles"]["name"][0]等等。
2、接收端接收,操作和單個的是一樣,只是需要做個循環,有多少個文件做多少次循環,以便所有的文件都能正確發送。
示例代碼:
表單頁面
<form enctype="multipart/form-data" action="post.php" method="post">
&nbsp;&nbsp;文章標題:&nbsp;&nbsp;<input name="title" type="text"/>&nbsp;標題不能為空!
<br />&nbsp;&nbsp;淘吧名字:&nbsp;&nbsp;<input name="bar_name" type="text"/>
<?php
echo "請選擇一個!\t(";
for ($i=0; $i<count($name); $i++ ){
?echo mb_convert_encoding($name[$i]["name"],"UTF-8","GB2312");
?echo "? ";
}
echo ")";
?>
<br />
<textarea name="text" cols="90" rows="20"></textarea>
<?php
for ($i=0;$i<3;$i++){
?echo "<input name=\"userfile[]\" type=\"file\"/>";
}
echo "<input name=\"i\" type=\"hidden\" value=\"$i\" />";
?>
</td></tr>
</table>
<table align="center" cellpadding="0" cellspacing="0"><tr><td>
<input name="submit" type="submit" value="確定提交"/>&nbsp;&nbsp;
<input name="reset" type="reset" value="重新來過"/>
</form>
處理頁面
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "<html xmlns="<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>提交</title>
</head>

<body>
<?php
$title=$_POST["title"];
$text=$_POST["text"];
$name=$_POST["name"];
$count=$_POST["i"];
include_once("數據庫連接文件");
if (empty($title)||empty($text)||empty($bar_name)){
?echo "標題或內容不能空
?die("<br /><a href=\"index.php\">重新來過</a>");
}

/*這里是數據查詢語言取出要用的數據*/

if(in_array("0", $_FILES['userfile']['error'])){//上傳文件開始
?$uploaddir= 'attfile/';//設置上傳的文件夾地址
?$FILES_EXT=array('.gif','.jpg','.mp3','.3gp');//設置允許上傳文件的類型
?$MAX_SIZE = 20000000;//設置文件上傳限制20000000byte=2M
?for ($i=0;$i<$count;$i++){
??$FILES_NAME=$_FILES['userfile']['name'][$i];//客戶端文件名
??//取出文件后綴名,strrpos()從標記開始前字節個數(不算標記),substr()顯示從第strrpos()之后的字符
??$file_ext=substr($FILES_NAME,strrpos($FILES_NAME,"."));
??//檢查文件大小
??if($_FILES['userfile']['size'][$i]>$MAX_SIZE){
???echo "文件大小超程序允許范圍!";
???exit;
??}
??//檢查文件類型
??if(in_array($file_ext, $FILES_EXT)){
???$_FILES['userfile']['name'][$i]=date("YmdHis").rand(10000,1000000).$file_ext;
???//echo $_FILES['userfile']['name'][$i];
???$uploadfile = $uploaddir.$_FILES['userfile']['name'][$i];//上傳后文件的路徑及文件名
???//echo $uploadfile;
???//用move函數生成臨時文件名,并按照 $_FILES['userfile']['name']上傳到$uploaddir下
???if (move_uploaded_file($_FILES['userfile']['tmp_name'][$i], $uploadfile)) {
????//將上傳后的路徑寫入到數據庫中
????$post_id=(int)$post_id;
????$uploadfile="attfile/".$_FILES['userfile']['name'][$i];
????$sql=插入語句
????$stmt=$db->prepare($sql);
????$stmt->execute();
????print "<br />文件\n{$FILES_NAME}\n上傳成功!";
???} else {
????print "上傳錯誤!? 以下是上傳的信息:\n";
????print_r($_FILES);
???}
??}
??else{
???echo "{$FILES_NAME}\n不是允許上傳的文件類型!";
???exit;
??}
?}
}

?>
</body>
</html>



橘子 2006-06-08 22:31 發表評論
]]>
php上傳單個文件http://m.tkk7.com/forget/archive/2006/06/08/51506.html橘子橘子Thu, 08 Jun 2006 14:09:00 GMThttp://m.tkk7.com/forget/archive/2006/06/08/51506.htmlhttp://m.tkk7.com/forget/comments/51506.htmlhttp://m.tkk7.com/forget/archive/2006/06/08/51506.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/51506.htmlhttp://m.tkk7.com/forget/services/trackbacks/51506.html ??? PHP上傳文件的問題:
一:1、上傳單個文件的時候。在表單頁面設置文件輸入域,<input name="userfile" type="file" />然后表單要加入<form enctype="multipart/form-data" action="post.php" method="post">這個屬性,這是告訴瀏覽器我要上傳文件的屬性,一定要加上。
??? 2、設置好了表單,接下來的事就是讀取表單的變量,如果你還定義了其他的變量,那么php使用$_POST來讀出,如:$uservar=$_POST["uservar"],然而文件是存在$_FILES中,具體見下面:
?
? * $_FILES['userfile']['name'] 客戶端機器文件的原名稱。
? ?* $_FILES['userfile']['type'] 文件的 MIME 類型,需要瀏覽器提供該信息的支持,例如“image/gif”。
? ?* $_FILES['userfile']['size'] 已上傳文件的大小,單位為字節。
? ?* $_FILES['userfile']['tmp_name'] 文件被上傳后在服務端儲存的臨時文件名。
? ?* $_FILES['userfile']['error'] 和該文件上傳相關的錯誤代碼

? 1. 值:0; 沒有錯誤發生,文件上傳成功。
? 2. 值:1; 上傳的文件超過了 php.ini 中 upload_max_filesize 選項限制的值。
? 3. 值:2; 上傳文件的大小超過了 HTML 表單中 MAX_FILE_SIZE 選項指定的值。
? 4. 值:3; 文件只有部分被上傳。
? 5. 值:4; 沒有文件被上傳。
3、完成上傳過程。示例代碼:
(1)
<?php
$upload_file=$_FILES['userfile']['tmp_name'];
$upload_file_name=$_FILES['userfile']['name'];
if($upload_file){
?$file_size_max = 20000000;// 1M限制文件上傳最大容量(bytes)
?$store_dir = "attfile/";// 上傳文件的儲存位置
?$accept_overwrite = 1;//是否允許覆蓋相同文件
?// 檢查文件大小
?if ($upload_file_size > $file_size_max) {
??echo "對不起,你的文件容量大于規定";
??exit;
?}
?// 檢查讀寫文件
?if (file_exists($store_dir . $upload_file_name) && !$accept_overwrite) {
??echo?? "存在相同文件名的文件";
??exit;
?}
?//復制文件到指定目錄
?if (!move_uploaded_file($upload_file,$store_dir.$upload_file_name)) {
??echo "復制文件失敗";
??exit;
?}
}
echo?? "<p>你上傳了文件:";
echo $_FILES['userfile']['name'];
echo "<br>";
//客戶端機器文件的原名稱。
Echo?? "文件的 MIME 類型為:";
echo $_FILES['userfile']['type'];
//文件的 MIME 類型,需要瀏覽器提供該信息的支持,例如“image/gif”。
echo "<br>";

Echo?? "上傳文件大小:";
echo $_FILES['userfile']['size'];
//已上傳文件的大小,單位為字節。
echo "<br>";

Echo?? "文件上傳后被臨時儲存為:";
echo $_FILES['userfile']['tmp_name'];
//文件被上傳后在服務端儲存的臨時文件名。
echo "<br>";

$Erroe=$_FILES['userfile']['error'];
switch($Erroe){
?case 0:
?Echo?? "上傳成功"; break;
?case 1:
?Echo?? "上傳的文件超過了 php.ini 中 upload_max_filesize 選項限制的值."; break;
?case 2:
?Echo?? "上傳文件的大小超過了 HTML 表單中 MAX_FILE_SIZE 選項指定的值。";?? break;
?case 3:
?Echo?? "文件只有部分被上傳";break;
?case 4:
?Echo?? "沒有文件被上傳";break;
}
?>
(2)<?php
$uploaddir= '../attfile/';//設置上傳的文件夾地址
$FILES_EXT=array('.gif','.jpg','.bmp');//設置允許上傳文件的類型
$MAX_SIZE = 20000000;//設置文件上傳限制20000000byte=2M
for ($i=0;$i<count($userfile);$i++){
?$FILES_NAME=$_FILES['userfile']['name'][$i];//客戶端文件名
}
//echo $FILES_NAME;
//取出文件后綴名,strrpos()從標記開始前字節個數(不算標記),substr()顯示從第strrpos()之后的字符
$file_ext=substr($FILES_NAME,strrpos($FILES_NAME,"."));
//echo $file_ext;
//檢查文件大小
if($_FILES['userfile']['size']>$MAX_SIZE){
?echo "文件大小超程序允許范圍!";
?exit;
}
//檢查文件類型
if(in_array($file_ext, $FILES_EXT)){
?$_FILES['userfile']['name']=date("YmdHis").rand().$file_ext;
?$uploadfile = $uploaddir.$_FILES['userfile']['name'];//上傳后文件的路徑及文件名
?//將上傳后的路徑寫入到數據庫中

?//用move函數生成臨時文件名,并按照 $_FILES['userfile']['name']上傳到$uploaddir下
?if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
??print "\n上傳成功!";
?} else {
??print "上傳錯誤!? 以下是上傳的信息:\n";
??print_r($_FILES);
?}
}
else{
?echo "{$file_ext}不是允許上傳的文件類型!";
?exit;
}
?>



小技巧>>1、當在提交時,希望確認是否要提交可以在<form>里如這樣加入:<form onsubmit="return confirm('你真的要提交嗎?')">
2、在php里希望返回時所有在文本框里的東西都保留可以這樣:<a href=javascript:history.back(1)>重新來過</a>。



橘子 2006-06-08 22:09 發表評論
]]>
JAVA相關基礎知識http://m.tkk7.com/forget/archive/2006/05/19/47089.html橘子橘子Fri, 19 May 2006 09:38:00 GMThttp://m.tkk7.com/forget/archive/2006/05/19/47089.htmlhttp://m.tkk7.com/forget/comments/47089.htmlhttp://m.tkk7.com/forget/archive/2006/05/19/47089.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/47089.htmlhttp://m.tkk7.com/forget/services/trackbacks/47089.html
JAVA相關基礎知識
1、面向對象的特征有哪些方面??
1.抽象:
抽象就是忽略一個主題中與當前目標無關的那些方面,以便更充分地注意與當前目標有關的方面。抽象并不打算了解全部問題,而只是選擇其中的一部分,暫時不用部分細節。抽象包括兩個方面,一是過程抽象,二是數據抽象。
2.繼承:
繼 承是一種聯結類的層次模型,并且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。對象的一個新類可以從現有的類中派生,這個過程稱為類繼承。新類繼 承了原始類的特性,新類稱為原始類的派生類(子類),而原始類稱為新類的基類(父類)。派生類可以從它的基類那里繼承方法和實例變量,并且類可以修改或增 加新的方法使之更適合特殊的需要。
3.封裝:
封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的界面。面向對象計算始于這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的對象,這些對象通過一個受保護的接口訪問其他對象。
4. 多態性:
多態性是指允許不同類的對象對同一消息作出響應。多態性包括參數化多態性和包含多態性。多態性語言具有靈活、抽象、行為共享、代碼共享的優勢,很好的解決了應用程序函數同名問題。
2、String是最基本的數據類型嗎?
基本數據類型包括byte、int、char、long、float、double、boolean和short。
java.lang.String類是final類型的,因此不可以繼承這個類、不能修改這個類。為了提高效率節省空間,我們應該用StringBuffer類
3、int 和 Integer 有什么區別
Java 提供兩種不同的類型:引用類型和原始類型(或內置類型)。Int是java的原始數據類型,Integer是java為int提供的封裝類。Java為每個原始類型提供了封裝類。
原始類型封裝類
booleanBoolean
charCharacter
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
引 用類型和原始類型的行為完全不同,并且它們具有不同的語義。引用類型和原始類型具有不同的特征和用法,它們包括:大小和速度問題,這種類型以哪種類型的數 據結構存儲,當引用類型和原始類型用作某個類的實例數據時所指定的缺省值。對象引用實例變量的缺省值為 null,而原始類型實例變量的缺省值與它們的類型有關。
4、String 和StringBuffer的區別
JAVA平臺提供了兩個 類:String和StringBuffer,它們可以儲存和操作字符串,即包含多個字符的字符數據。這個String類提供了數值不可改變的字符串。而 這個StringBuffer類提供的字符串進行修改。當你知道字符數據要改變的時候你就可以使用StringBuffer。典型地,你可以使用 StringBuffers來動態構造字符數據。
5、運行時異常與一般異常有何異同?
異常表示程序運行過程中可能出現的非正常狀態,運行時異常表示虛擬機的通常操作中可能遇到的異常,是一種常見運行錯誤。java編譯器要求方法必須聲明拋出可能發生的非運行時異常,但是并不要求必須聲明拋出未被捕獲的運行時異常。
6、說出Servlet的生命周期,并說出Servlet和CGI的區別。
Servlet被服務器實例化后,容器運行其init方法,請求到達時運行其service方法,service方法自動派遣運行與請求對應的doXXX方法(doGet,doPost)等,當服務器決定將實例銷毀的時候調用其destroy方法。
與cgi的區別在于servlet處于服務器進程中,它通過多線程方式運行其service方法,一個實例可以服務于多個請求,并且其實例一般不會銷毀,而CGI對每個請求都產生新的進程,服務完成后就銷毀,所以效率上低于servlet。
7、說出ArrayList,Vector, LinkedList的存儲性能和特性
ArrayList 和Vector都是使用數組方式存儲數據,此數組元素數大于實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元 素移動等內存操作,所以索引數據快而插入數據慢,Vector由于使用了synchronized方法(線程安全),通常性能上較ArrayList差, 而LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行前向或后向遍歷,但是插入數據時只需要記錄本項的前后項即可,所以插入速度較快。
8、EJB是基于哪些技術實現的?并說出SessionBean和EntityBean的區別,StatefulBean和StatelessBean的區別。
??? EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技術實現。
SessionBean在J2EE應用程序中被用來完成一些服務器端的業務操作,例如訪問數據庫、調用其他EJB組件。EntityBean被用來代表應用系統中用到的數據。
對于客戶機,SessionBean是一種非持久性對象,它實現某些在服務器上運行的業務邏輯。
對于客戶機,EntityBean是一種持久性對象,它代表一個存儲在持久性存儲器中的實體的對象視圖,或是一個由現有企業應用程序實現的實體。
Session Bean 還可以再細分為 Stateful Session Bean 與 Stateless Session Bean ,這兩種的 Session Bean都可以將系統邏輯放在 method之中執行,不同的是 Stateful Session Bean 可以記錄呼叫者的狀態,因此通常來說,一個使用者會有一個相對應的 Stateful Session Bean 的實體。Stateless Session Bean 雖然也是邏輯組件,但是他卻不負責記錄使用者狀態,也就是說當使用者呼叫 Stateless Session Bean 的時候,EJB Container 并不會找尋特定的 Stateless Session Bean 的實體來執行這個 method。換言之,很可能數個使用者在執行某個 Stateless Session Bean 的 methods 時,會是同一個 Bean 的 Instance 在執行。從內存方面來看, Stateful Session Bean 與 Stateless Session Bean 比較, Stateful Session Bean 會消耗 J2EE Server 較多的內存,然而 Stateful Session Bean 的優勢卻在于他可以維持使用者的狀態。
9、Collection 和 Collections的區別。
  Collection是集合類的上級接口,繼承與他的接口主要有Set 和List.
Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作。
10、&和&&的區別。
??? &是位運算符,表示按位與運算,&&是邏輯運算符,表示邏輯與(and)。
11、HashMap和Hashtable的區別。
??? HashMap是Hashtable的輕量級實現(非線程安全的實現),他們都完成了Map接口,主要區別在于HashMap允許空(null)鍵值(key),由于非線程安全,效率上可能高于Hashtable。
HashMap允許將null作為一個entry的key或者value,而Hashtable不允許。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因為contains方法容易讓人引起誤解。
Hashtable繼承自Dictionary類,而HashMap是Java1.2引進的Map interface的一個實現。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個線程訪問Hashtable時,不需要自己為它的方法實現同步,而HashMap 就必須為之提供外同步。
Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會有很大的差異。
12、final, finally, finalize的區別。
  final 用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。
finally是異常處理語句結構的一部分,表示總是執行。
finalize是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉文件等。
13、sleep() 和 wait() 有什么區別?
??? sleep是線程類(Thread)的方法,導致此線程暫停執行指定時間,給執行機會給其他線程,但是監控狀態依然保持,到時后會自動恢復。調用sleep不會釋放對象鎖。
wait是Object類的方法,對此對象調用wait方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或notifyAll)后本線程才進入對象鎖定池準備獲得對象鎖進入運行狀態。
14、Overload和Override的區別。Overloaded的方法是否可以改變返回值的類型?
方 法的重寫Overriding和重載Overloading是Java多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重 載Overloading是一個類中多態性的一種表現。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被"屏蔽"了。如果在一個類中定義了多個同名的方 法,它們或有不同的參數個數或有不同的參數類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型。
15、error和exception有什么區別?
error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。
??? exception 表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。
16、同步和異步有何異同,在什么情況下分別使用他們?舉例說明。
如果數據將在線程間共享。例如正在寫的數據以后可能被另一個線程讀到,或者正在讀的數據可能已經被另一個線程寫過了,那么這些數據就是共享數據,必須進行同步存取。
當應用程序在對象上調用了一個需要花費很長時間來執行的方法,并且不希望讓程序等待方法的返回時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率。
17、abstract class和interface有什么區別?
聲 明方法的存在而不去實現它的類被叫做抽象類(abstract class),它用于要創建一個體現某些基本行為的類,并為該類聲明方法,但不能在該類中實現該類的情況。不能創建abstract 類的實例。然而可以創建一個變量,其類型是一個抽象類,并讓它指向具體子類的一個實例。不能有抽象構造函數或抽象靜態方法。Abstract 類的子類為它們父類中的所有抽象方法提供實現,否則它們也是抽象類為。取而代之,在子類中實現該方法。知道其行為的其它類可以在類中實現這些方法。
接 口(interface)是抽象類的變體。在接口中,所有方法都是抽象的。多繼承性可通過實現這樣的接口而獲得。接口中的所有方法都是抽象的,沒有一個有 程序體。接口只可以定義static final成員變量。接口的實現與子類相似,除了該實現類不能從接口定義中繼承行為。當類實現特殊接口時,它定義(即將程序體給予)所有這種接口的方法。 然后,它可以在實現了該接口的類的任何對象上調用接口的方法。由于有抽象類,它允許使用接口名作為引用變量的類型。通常的動態聯編將生效。引用可以轉換到 接口類型或從接口類型轉換,instanceof 運算符可以用來決定某對象的類是否實現了接口。
18、heap和stack有什么區別。
棧是一種線形集合,其添加和刪除元素的操作應在同一段完成。棧按照后進先出的方式進行處理。
堆是棧的一個組成元素
19、forward 和redirect的區別
forward是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,然后把這些內容再發給瀏覽器,瀏覽器根本不知道服務器發送的內容是從哪兒來的,所以它的地址欄中還是原來的地址。
??? redirect就是服務端根據邏輯,發送一個狀態碼,告訴瀏覽器重新去請求那個地址,一般來說瀏覽器會用剛才請求的所有參數重新請求,所以session,request參數都可以獲取。
20、EJB與JAVA BEAN的區別?
Java Bean 是可復用的組件,對Java Bean并沒有嚴格的規范,理論上講,任何一個Java類都可以是一個Bean。但通常情況下,由于Java Bean是被容器所創建(如Tomcat)的,所以Java Bean應具有一個無參的構造器,另外,通常Java Bean還要實現Serializable接口用于實現Bean的持久性。Java Bean實際上相當于微軟COM模型中的本地進程內COM組件,它是不能被跨進程訪問的。Enterprise Java Bean 相當于DCOM,即分布式組件。它是基于Java的遠程方法調用(RMI)技術的,所以EJB可以被遠程訪問(跨進程、跨計算機)。但EJB必須被布署在 諸如Webspere、WebLogic這樣的容器中,EJB客戶從不直接訪問真正的EJB組件,而是通過其容器訪問。EJB容器是EJB組件的代理, EJB組件由容器所創建和管理。客戶通過容器來訪問真正的EJB組件。
21、Static Nested Class 和 Inner Class的不同。
??? Static Nested Class是被聲明為靜態(static)的內部類,它可以不依賴于外部類實例被實例化。而通常的內部類需要在外部類實例化后才能實例化。
22、JSP中動態INCLUDE與靜態INCLUDE的區別?
動態INCLUDE用jsp:include動作實現 <jsp:include page="included.jsp" flush="true" />它總是會檢查所含文件中的變化,適合用于包含動態頁面,并且可以帶參數。
靜態INCLUDE用include偽碼實現,定不會檢查所含文件的變化,適用于包含靜態頁面<%@ include file="included.htm" %>
23、什么時候用assert。
??? assertion(斷言)在軟件開發中是一種常用的調試方式,很多開發語言中都支持這種機制。在實現中,assertion就是在程序中的一條語句,它 對一個boolean表達式進行檢查,一個正確程序必須保證這個boolean表達式的值為true;如果該值為false,說明程序已經處于不正確的狀 態下,系統將給出警告或退出。一般來說,assertion用于保證程序最基本、關鍵的正確性。assertion檢查通常在開發和測試時開啟。為了提高 性能,在軟件發布后,assertion檢查通常是關閉的。
24、GC是什么? 為什么要有GC?
  GC是垃圾收集的意思 (Gabage Collection),內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰,Java提供的GC功能可以 自動監測對象是否超過作用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操作方法。
25、short s1 = 1; s1 = s1 + 1;有什么錯? short s1 = 1; s1 += 1;有什么錯?
??? short s1 = 1; s1 = s1 + 1; (s1+1運算結果是int型,需要強制轉換類型)
short s1 = 1; s1 += 1;(可以正確編譯)
26、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
??? Math.round(11.5)==12
Math.round(-11.5)==-11
round方法返回與參數最接近的長整數,參數加1/2后求其floor.
27、String s = new String("xyz");創建了幾個String Object?
??? 兩個
28、設計4個線程,其中兩個線程每次對j增加1,另外兩個線程對j每次減少1。寫出程序。
以下程序使用內部類實現線程,對j增減的時候沒有考慮順序問題。
public class ThreadTest1{
? private int j;
? public static void main(String args[]){
ThreadTest1 tt=new ThreadTest1();
Inc inc=tt.new Inc();
Dec dec=tt.new Dec();
for(int i=0;i<2;i++){
Thread t=new Thread(inc);
t.start();
t=new Thread(dec);
t.start();
}
}
? private synchronized void inc(){
j++;
System.out.println(Thread.currentThread().getName()+"-inc:"+j);
? }
? private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+"-dec:"+j);
? }
? class Inc implements Runnable{
public void run(){
for(int i=0;i<100;i++){
inc();
}
}
? }
? class Dec implements Runnable{
public void run(){
for(int i=0;i<100;i++){
dec();
}
?}
? }
}
29、Java有沒有goto?
java中的保留字,現在沒有在java中使用。
30、啟動一個線程是用run()還是start()?
啟動一個線程是調用start()方法,使線程所代表的虛擬處理機處于可運行狀態,這意味著它可以由JVM調度并執行。這并不意味著線程就會立即運行。run()方法可以產生必須退出的標志來停止一個線程。
?

31、EJB包括(SessionBean,EntityBean)說出他們的生命周期,及如何管理事務的?
SessionBean: Stateless Session Bean 的生命周期是由容器決定的,當客戶機發出請求要建立一個Bean的實例時,EJB容器不一定要創建一個新的Bean的實例供客戶機調用,而是隨便找一個現 有的實例提供給客戶機。當客戶機第一次調用一個Stateful Session Bean 時,容器必須立即在服務器中創建一個新的Bean實例,并關聯到客戶機上,以后此客戶機調用Stateful Session Bean 的方法時容器會把調用分派到與此客戶機相關聯的Bean實例。
EntityBean:Entity Beans能存活相對較長的時間,并且狀態是持續的。只要數據庫中的數據存在,Entity beans就一直存活。而不是按照應用程序或者服務進程來說的。即使EJB容器崩潰了,Entity beans也是存活的。Entity Beans生命周期能夠被容器或者 Beans自己管理。
EJB通過以下技術管理實務:對象管理組織(OMG)的對象實務服務(OTS),Sun Microsystems的Transaction Service(JTS)、Java Transaction API(JTA),開發組(X/Open)的XA接口。
32、應用服務器有那些?
BEA WebLogic Server,IBM WebSphere Application Server,Oracle9i Application Server,jBoss,Tomcat
33、給我一個你最常見到的runtime exception。
ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException
34、接口是否可繼承接口? 抽象類是否可實現(implements)接口? 抽象類是否可繼承實體類(concrete class)?
接口可以繼承接口。抽象類可以實現(implements)接口,抽象類是否可繼承實體類,但前提是實體類必須有明確的構造函數。
35、List, Set, Map是否繼承自Collection接口?
??? List,Set是,Map不是
36、說出數據連接池的工作機制是什么?
J2EE 服務器啟動時會建立一定數量的池連接,并一直維持不少于此數目的池連接。客戶端程序需要連接時,池驅動程序會返回一個未使用的池連接并將其表記為忙。如果 當前沒有空閑連接,池驅動程序就新建一定數量的連接,新建連接的數量有配置參數決定。當使用的池連接調用完成后,池驅動程序將此連接表記為空閑,其他調用 就可以使用這個連接。
37、abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?
??? 都不能
38、數組有沒有length()這個方法? String有沒有length()這個方法?
數組沒有length()這個方法,有length的屬性。String有有length()這個方法。
39、Set里的元素是不能重復的,那么用什么方法來區分重復與否呢? 是用==還是equals()? 它們有何區別?
Set里的元素是不能重復的,那么用iterator()方法來區分重復與否。equals()是判讀兩個Set是否相等。
??? equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,為的是當兩個分離的對象的內容和類型相配的話,返回真值。
40、構造器Constructor是否可被override?
構造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading。
41、是否可以繼承String類?
String類是final類故不可以繼承。
42、swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
switch(expr1)中,expr1是一個整數表達式。因此傳遞給 switch 和 case 語句的參數應該是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。
43、try {}里有一個return語句,那么緊跟在這個try后的finally {}里的code會不會被執行,什么時候被執行,在return前還是后?
會執行,在return前執行。
44、編程題: 用最有效率的方法算出2乘以8等於幾?
2 << 3
45、兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?
不對,有相同的hash code。
46、當一個對象被當作參數傳遞到一個方法后,此方法可改變這個對象的屬性,并可返回變化后的結果,那么這里到底是值傳遞還是引用傳遞?
是值傳遞。Java 編程語言只有值傳遞參數。當一個對象實例作為一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的內容可以在被調用的方法中改變,但對象的引用是永遠不會改變的。
47、當一個線程進入一個對象的一個synchronized方法后,其它線程是否可進入此對象的其它方法?
不能,一個對象的一個synchronized方法只能由一個線程訪問。
48、編程題: 寫一個Singleton出來。
Singleton模式主要作用是保證在Java應用程序中,一個類Class只有一個實例存在。
一般Singleton模式通常有幾種種形式:
第一種形式: 定義一個類,它的構造函數為private的,它有一個static的private的該類變量,在類初始化時實例話,通過一個public的getInstance方法獲取對它的引用,繼而調用其中的方法。
public class Singleton {
private Singleton(){}
  ??? //在自己內部定義自己一個實例,是不是很奇怪?
  ??? //注意這是private 只供內部調用
  ??? private static Singleton instance = new Singleton();
  ??? //這里提供了一個供外部訪問本class的靜態方法,可以直接訪問  
  ??? public static Singleton getInstance() {
    ??? return instance;   
  ??? }
??? }
??? 第二種形式:
public class Singleton {
  private static Singleton instance = null;
  public static synchronized Singleton getInstance() {
  //這個方法比上面有所改進,不用每次都進行生成對象,只是第一次     
  //使用時生成實例,提高了效率!
  if (instance==null)
    instance=new Singleton();
return instance;   }
}
其他形式:
定義一個類,它的構造函數為private的,所有方法為static的。
一般認為第一種形式要更加安全些
49、Java的接口和C++的虛類的相同和不同處。
由 于Java不支持多繼承,而有可能某個類或對象要使用分別在幾個類或對象里面的方法或屬性,現有的單繼承機制就不能滿足要求。與繼承相比,接口有更高的靈 活性,因為接口中沒有任何實現代碼。當一個類實現了接口以后,該類要實現接口里面所有的方法和屬性,并且接口里面的屬性在默認狀態下面都是public static,所有方法默認情況下是public.一個類可以實現多個接口。
50、Java中的異常處理機制的簡單原理和應用。
當JAVA 程序違反了JAVA的語義規則時,JAVA虛擬機就會將發生的錯誤表示為一個異常。違反語義規則包括2種情況。一種是JAVA類庫內置的語義檢查。例如數 組下標越界,會引發IndexOutOfBoundsException;訪問null的對象時會引發NullPointerException。另一種 情況就是JAVA允許程序員擴展這種語義檢查,程序員可以創建自己的異常,并自由選擇在何時用throw關鍵字引發異常。所有的異常都是 java.lang.Thowable的子類。
51、垃圾回收的優點和原理。并考慮2種回收機制。
Java語言中一個顯著的特點就是引入 了垃圾回收機制,使c++程序員最頭疼的內存管理的問題迎刃而解,它使得Java程序員在編寫程序的時候不再需要考慮內存管理。由于有個垃圾回收機制, Java中的對象不再有"作用域"的概念,只有對象的引用才有"作用域"。垃圾回收可以有效的防止內存泄露,有效的使用可以使用的內存。垃圾回收器通常是 作為一個單獨的低級別的線程運行,不可預知的情況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清楚和回收,程序員不能實時的調用垃圾回收器對某個 對象或所有對象進行垃圾回收。回收機制有分代復制垃圾回收和標記垃圾回收,增量垃圾回收。
52、請說出你所知道的線程同步的方法。
wait():使一個線程處于等待狀態,并且釋放所持有的對象的lock。
sleep():使一個正在運行的線程處于睡眠狀態,是一個靜態方法,調用此方法要捕捉InterruptedException異常。
notify():喚醒一個處于等待狀態的線程,注意的是在調用此方法的時候,并不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且不是按優先級。
Allnotity():喚醒所有處入等待狀態的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。
53、你所知道的集合類都有哪些?主要方法?
最常用的集合類是 List 和 Map。 List 的具體實現包括 ArrayList 和 Vector,它們是可變大小的列表,比較適合構建、存儲和操作任何類型對象的元素列表。 List 適用于按數值索引訪問元素的情形。
Map 提供了一個更通用的元素存儲方法。 Map 集合類用于存儲元素對(稱作"鍵"和"值"),其中每個鍵映射到一個值。
54、描述一下JVM加載class文件的原理機制?
JVM中類的裝載是由ClassLoader和它的子類來實現的,Java ClassLoader 是一個重要的Java運行時系統組件。它負責在運行時查找和裝入類文件的類。
55、char型變量中能不能存貯一個中文漢字?為什么?
能夠定義成為一個中文的,因為java中以unicode編碼,一個char占16個字節,所以放一個中文是沒問題的
56、多線程有幾種實現方法,都是什么?同步有幾種實現方法,都是什么?
多線程有兩種實現方法,分別是繼承Thread類與實現Runnable接口
同步的實現方面有兩種,分別是synchronized,wait與notify
57、JSP的內置對象及方法。
request表示HttpServletRequest對象。它包含了有關瀏覽器請求的信息,并且提供了幾個用于獲取cookie, header, 和session數據的有用的方法。
??? response表示HttpServletResponse對象,并提供了幾個用于設置送回 瀏覽器的響應的方法(如cookies,頭信息等)
??? out對象是javax.jsp.JspWriter的一個實例,并提供了幾個方法使你能用于向瀏覽器回送輸出結果。
??? pageContext表示一個javax.servlet.jsp.PageContext對象。它是用于方便存取各種范圍的名字空間、servlet相關的對象的API,并且包裝了通用的servlet相關功能的方法。
??? session表示一個請求的javax.servlet.http.HttpSession對象。Session可以存貯用戶的狀態信息
??? applicaton 表示一個javax.servle.ServletContext對象。這有助于查找有關servlet引擎和servlet環境的信息
??? config表示一個javax.servlet.ServletConfig對象。該對象用于存取servlet實例的初始化參數。
??? page表示從該頁面產生的一個servlet實例
58、線程的基本概念、線程的基本狀態以及狀態之間的關系
線程指在程序執行過程中,能夠執行程序代碼的一個執行單位,每個程序至少都有一個線程,也就是程序本身。
Java中的線程有四種狀態分別是:運行、就緒、掛起、結束。
59、JSP的常用指令
<%@page language="java" contenType="text/html;charset=gb2312" session="true" buffer="64kb" autoFlush="true" isThreadSafe="true" info="text" errorPage="error.jsp" isErrorPage="true" isELIgnored="true" pageEncoding="gb2312" import="java.sql.*"%>
isErrorPage(是否能使用Exception對象),isELIgnored(是否忽略表達式)
<%@include file="filename"%>
<%@taglib prefix="c"uri="http://......"%>
60、什么情況下調用doGet()和doPost()?
Jsp頁面中的form標簽里的method屬性為get時調用doGet(),為post時調用doPost()。
61、servlet的生命周期
web容器加載servlet,生命周期開始。通過調用servlet的init()方法進行servlet的初始化。通過調用service()方法實現,根據請求的不同調用不同的do***()方法。結束服務,web容器調用servlet的destroy()方法。
62、如何現實servlet的單線程模式
<%@ page isThreadSafe="false"%>
63、頁面間對象傳遞的方法
request,session,application,cookie等
64、JSP和Servlet有哪些相同點和不同點,他們之間的聯系是什么?
JSP 是Servlet技術的擴展,本質上是Servlet的簡易方式,更強調應用的外表表達。JSP編譯后是"類servlet"。Servlet和JSP最 主要的不同點在于,Servlet的應用邏輯是在Java文件中,并且完全從表示層中的HTML里分離開來。而JSP的情況是Java和HTML可以組合 成一個擴展名為.jsp的文件。JSP側重于視圖,Servlet主要用于控制邏輯。
65、四種會話跟蹤技術
會話作用域ServletsJSP 頁面描述
page否是代表與一個頁面相關的對象和屬性。一個頁面由一個編譯好的 Java servlet 類(可以帶有任何的 include 指令,但是沒有 include 動作)表示。這既包括 servlet 又包括被編譯成 servlet 的 JSP 頁面
request是是代表與 Web 客戶機發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個 Web 組件(由于 forward 指令和 include 動作的關系)
session是是代表與用于某個 Web 客戶機的一個用戶體驗相關的對象和屬性。一個 Web 會話可以也經常會跨越多個客戶機請求
application是是代表與整個 Web 應用程序相關的對象和屬性。這實質上是跨越整個 Web 應用程序,包括多個頁面、請求和會話的一個全局作用域
66、Request對象的主要方法:
setAttribute(String name,Object):設置名字為name的request的參數值
getAttribute(String name):返回由name指定的屬性值
getAttributeNames():返回request對象所有屬性的名字集合,結果是一個枚舉的實例
getCookies():返回客戶端的所有Cookie對象,結果是一個Cookie數組
getCharacterEncoding():返回請求中的字符編碼方式
getContentLength():返回請求的Body的長度
getHeader(String name):獲得HTTP協議定義的文件頭信息
getHeaders(String name):返回指定名字的request Header的所有值,結果是一個枚舉的實例
getHeaderNames():返回所以request Header的名字,結果是一個枚舉的實例
getInputStream():返回請求的輸入流,用于獲得請求中的數據
getMethod():獲得客戶端向服務器端傳送數據的方法
getParameter(String name):獲得客戶端傳送給服務器端的有name指定的參數值
getParameterNames():獲得客戶端傳送給服務器端的所有參數的名字,結果是一個枚舉的實例
getParameterValues(String name):獲得有name指定的參數的所有值
getProtocol():獲取客戶端向服務器端傳送數據所依據的協議名稱
getQueryString():獲得查詢字符串
getRequestURI():獲取發出請求字符串的客戶端地址
getRemoteAddr():獲取客戶端的IP地址
getRemoteHost():獲取客戶端的名字
getSession([Boolean create]):返回和請求相關Session
getServerName():獲取服務器的名字
getServletPath():獲取客戶端所請求的腳本文件的路徑
getServerPort():獲取服務器的端口號
removeAttribute(String name):刪除請求中的一個屬性
67、J2EE是技術還是平臺還是框架?
??? J2EE本身是一個標準,一個為企業分布式應用的開發提供的標準平臺。
??? J2EE也是一個框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技術。
68、我們在web應用開發過程中經常遇到輸出某種編碼的字符,如iso8859-1等,如何輸出一個某種編碼的字符串?
? Public String translate (String str) {
??? String tempStr = "";
??? try {
????? tempStr = new String(str.getBytes("ISO-8859-1"), "GBK");
????? tempStr = tempStr.trim();
??? }
??? catch (Exception e) {
????? System.err.println(e.getMessage());
??? }
??? return tempStr;
? }
69、簡述邏輯操作(&,|,^)與條件操作(&&,||)的區別。
區別主要答兩點:a.條件操作只能操作布爾型的,而邏輯操作不僅可以操作布爾型,而且可以操作數值型
b.邏輯操作不會產生短路
70、XML文檔定義有幾種形式?它們之間有何本質區別?解析XML文檔有哪幾種方式?
a: 兩種形式 dtd? schema,b: 本質區別:schema本身是xml的,可以被XML解析器解析(這也是從DTD上發展schema的根本目的),c:有DOM,SAX,STAX等
??? DOM:處理大型文件時其性能下降的非常厲害。這個問題是由DOM的樹結構所造成的,這種結構占用的內存較多,而且DOM必須在解析文件之前把整個文檔裝入內存,適合對XML的隨機訪問
SAX:不現于DOM,SAX是事件驅動型的XML解析方式。它順序讀取XML文件,不需要一次全部裝載整個文件。當遇到像文件開頭,文檔結束,或者標簽開頭與標簽結束時,它會觸發一個事件,用戶通過在其回調事件中寫入處理代碼來處理XML文件,適合對XML的順序訪問
??? STAX:Streaming API for XML (StAX)
71、簡述synchronized和java.util.concurrent.locks.Lock的異同 ?
主要相同點:Lock能完成synchronized所實現的所有功能
主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。
72、EJB的角色和三個對象
一 個完整的基于EJB的分布式計算結構由六個角色組成,這六個角色可以由不同的開發商提供,每個角色所作的工作必須遵循Sun公司提供的EJB規范,以保證 彼此之間的兼容性。這六個角色分別是EJB組件開發者(Enterprise Bean Provider) 、應用組合者(Application Assembler)、部署者(Deployer)、EJB 服務器提供者(EJB Server Provider)、EJB 容器提供者(EJB Container Provider)、系統管理員(System Administrator)
三個對象是Remote(Local)接口、Home(LocalHome)接口,Bean類
73、EJB容器提供的服務
主要提供聲明周期管理、代碼產生、持續性管理、安全、事務管理、鎖和并發行管理等服務。
74、EJB規范規定EJB中禁止的操作有哪些?
??? 1.不能操作線程和線程API(線程API指非線程對象的方法如notify,wait等),2.不能操作awt,3.不能實現服務器功能,4.不能對靜 態屬生存取,5.不能使用IO操作直接存取文件系統,6.不能加載本地庫.,7.不能將this作為變量和返回,8.不能循環調用。
75、remote接口和home接口主要作用
remote接口定義了業務方法,用于EJB客戶端調用業務方法。
home接口是EJB工廠用于創建和移除查找EJB實例
76、bean 實例的生命周期
對 于Stateless Session Bean、Entity Bean、Message Driven Bean一般存在緩沖池管理,而對于Entity Bean和Statefull Session Bean存在Cache管理,通常包含創建實例,設置上下文、創建EJB Object(create)、業務方法調用、remove等過程,對于存在緩沖池管理的Bean,在create之后實例并不從內存清除,而是采用緩沖 池調度機制不斷重用實例,而對于存在Cache管理的Bean則通過激活和去激活機制保持Bean的狀態并限制內存中實例數量。
77、EJB的激活機制
以Stateful Session Bean 為例:其Cache大小決定了內存中可以同時存在的Bean實例的數量,根據MRU或NRU算法,實例在激活和去激活狀態之間遷移,激活機制是當客戶端調 用某個EJB實例業務方法時,如果對應EJB Object發現自己沒有綁定對應的Bean實例則從其去激活Bean存儲中(通過序列化機制存儲實例)回復(激活)此實例。狀態變遷前會調用對應的 ejbActive和ejbPassivate方法。
78、EJB的幾種類型
會話(Session)Bean ,實體(Entity)Bean 消息驅動的(Message Driven)Bean
會話Bean又可分為有狀態(Stateful)和無狀態(Stateless)兩種
實體Bean可分為Bean管理的持續性(BMP)和容器管理的持續性(CMP)兩種
79、客服端調用EJB對象的幾個基本步驟
設置JNDI服務工廠以及JNDI服務地址系統屬性,查找Home接口,從Home接口調用Create方法創建Remote接口,通過Remote接口調用其業務方法。
80、如何給weblogic指定大小的內存?
在啟動Weblogic的腳本中(位于所在Domian對應服務器目錄下的startServerName),增加set MEM_ARGS=-Xms32m -Xmx200m,可以調整最小內存為32M,最大200M
81、如何設定的weblogic的熱啟動模式(開發模式)與產品發布模式?
可以在管理控制臺中修改對應服務器的啟動模式為開發或產品模式之一。或者修改服務的啟動文件或者commenv文件,增加set PRODUCTION_MODE=true。
82、如何啟動時不需輸入用戶名與密碼?
修改服務啟動文件,增加 WLS_USER和WLS_PW項。也可以在boot.properties文件中增加加密過的用戶名和密碼.
83、在weblogic管理制臺中對一個應用域(或者說是一個網站,Domain)進行jms及ejb或連接池等相關信息進行配置后,實際保存在什么文件中?
保存在此Domain的config.xml文件中,它是服務器的核心配置文件。
84、 說說weblogic中一個Domain的缺省目錄結構?比如要將一個簡單的helloWorld.jsp放入何目錄下,然的在瀏覽器上就可打入 http://主機:端口號//helloword.jsp就可以看到運行結果了? 又比如這其中用到了一個自己寫的javaBean該如何辦?
Domain 目錄服務器目錄applications,將應用目錄放在此目錄下將可以作為應用訪問,如果是Web應用,應用目錄需要滿足Web應用目錄要求,jsp文 件可以直接放在應用目錄中,Javabean需要放在應用目錄的WEB-INF目錄的classes目錄中,設置服務器的缺省應用將可以實現在瀏覽器上無 需輸入應用名。
85、在weblogic中發布ejb需涉及到哪些配置文件
不同類型的EJB涉及的配置文件不同,都涉及到的配置文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP實體Bean一般還需要weblogic-cmp-rdbms-jar.xml
86、如何在weblogic中進行ssl配置與客戶端的認證配置或說說j2ee(標準)進行ssl的配置
缺 省安裝中使用DemoIdentity.jks和DemoTrust.jks? KeyStore實現SSL,需要配置服務器使用Enable SSL,配置其端口,在產品模式下需要從CA獲取私有密鑰和數字證書,創建identity和trust keystore,裝載獲得的密鑰和數字證書。可以配置此SSL連接是單向還是雙向的。
87、如何查看在weblogic中已經發布的EJB?
可以使用管理控制臺,在它的Deployment中可以查看所有已發布的EJB
88、CORBA是什么?用途是什么?
CORBA 標準是公共對象請求代理結構(Common Object Request Broker Architecture),由對象管理組織 (Object Management Group,縮寫為 OMG)標準化。它的組成是接口定義語言(IDL), 語言綁定(binding:也譯為聯編)和允許應用程序間互操作的協議。其目的為:用不同的程序設計語言書寫在不同的進程中運行,為不同的操作系統開發。
89、說說你所熟悉或聽說過的j2ee中的幾種常用模式?及對設計模式的一些看法
? Session Facade Pattern:使用SessionBean訪問EntityBean
Message Facade Pattern:實現異步調用
EJB Command Pattern:使用Command JavaBeans取代SessionBean,實現輕量級訪問
Data Transfer Object Factory:通過DTO Factory簡化EntityBean數據提供特性
Generic Attribute Access:通過AttibuteAccess接口簡化EntityBean數據提供特性
Business Interface:通過遠程(本地)接口和Bean類實現相同接口規范業務邏輯一致性
EJB架構的設計好壞將直接影響系統的性能、可擴展性、可維護性、組件可重用性及開發效率。項目越復雜,項目隊伍越龐大則越能體現良好設計的重要性。
90、說說在weblogic中開發消息Bean時的persistent與non-persisten的差別
persistent方式的MDB可以保證消息傳遞的可靠性,也就是如果EJB容器出現問題而JMS服務器依然會將消息在此MDB可用的時候發送過來,而non-persistent方式的消息將被丟棄。
91、Servlet執行時一般實現哪幾個方法?
public void init(ServletConfig config)
public ServletConfig getServletConfig()
public String getServletInfo()
public void service(ServletRequest request,ServletResponse response)
public void destroy()
92、j2ee常用的設計模式?說明工廠模式。
??? Java中的23種設計模式:
Factory(工廠模式),????? Builder(建造模式),?????? Factory Method(工廠方法模式),
Prototype(原始模型模式),Singleton(單例模式),??? Facade(門面模式),
Adapter(適配器模式),??? Bridge(橋梁模式),??????? Composite(合成模式),
Decorator(裝飾模式),??? Flyweight(享元模式),???? Proxy(代理模式),
Command(命令模式),????? Interpreter(解釋器模式), Visitor(訪問者模式),
Iterator(迭代子模式),?? Mediator(調停者模式),??? Memento(備忘錄模式),
Observer(觀察者模式),?? State(狀態模式),???????? Strategy(策略模式),
Template Method(模板方法模式), Chain Of Responsibleity(責任鏈模式)
工 廠模式:工廠模式是一種經常被使用到的模式,根據工廠模式實現的類可以根據提供的數據生成一組類中某一個類的實例,通常這一組類有一個公共的抽象父類并且 實現了相同的方法,但是這些方法針對不同的數據進行了不同的操作。首先需要定義一個基類,該類的子類通過不同的方法實現了基類中的方法。然后需要定義一個 工廠類,工廠類可以根據條件生成不同的子類實例。當得到子類的實例后,開發人員可以調用基類中的方法而不必考慮到底返回的是哪一個子類的實例。
93、EJB需直接實現它的業務接口或Home接口嗎,請簡述理由。
遠程接口和Home接口不需要直接實現,他們的實現代碼是由服務器產生的,程序運行中對應實現類會作為對應接口類型的實例被使用。
94、排序都有哪幾種方法?請列舉。用JAVA實現一個快速排序。
??? 排序的方法有:插入排序(直接插入排序、希爾排序),交換排序(冒泡排序、快速排序),選擇排序(直接選擇排序、堆排序),歸并排序,分配排序(箱排序、基數排序)
快速排序的偽代碼。
/ /使用快速排序方法對a[ 0 :n- 1 ]排序
從a[ 0 :n- 1 ]中選擇一個元素作為m i d d l e,該元素為支點
把余下的元素分割為兩段left 和r i g h t,使得l e f t中的元素都小于等于支點,而right 中的元素都大于等于支點
遞歸地使用快速排序方法對left 進行排序
遞歸地使用快速排序方法對right 進行排序
所得結果為l e f t + m i d d l e + r i g h t
95、請對以下在J2EE中常用的名詞進行解釋(或簡單描述)
web 容器:給處于其中的應用程序組件(JSP,SERVLET)提供一個環境,使JSP,SERVLET直接更容器中的環境變量接口交互,不必關注其它系統問 題。主要有WEB服務器來實現。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。該容器提供的接口嚴格遵守J2EE規范中的WEB APPLICATION 標準。我們把遵守以上標準的WEB服務器就叫做J2EE中的WEB容器。
EJB容器:Enterprise java bean 容器。更具有行業領域特色。他提供給運行在其中的組件EJB各種管理功能。只要滿足J2EE規范的EJB放入該容器,馬上就會被容器進行高效率的管理。并 且可以通過現成的接口來獲得系統級別的服務。例如郵件服務、事務管理。
JNDI:(Java Naming & Directory Interface)JAVA命名目錄服務。主要提供的功能是:提供一個目錄系統,讓其它各地的應用程序在其上面留下自己的索引,從而滿足快速查找和定位分布式應用程序的功能。
JMS:(Java Message Service)JAVA消息服務。主要實現各個應用程序之間的通訊。包括點對點和廣播。
JTA:(Java Transaction API)JAVA事務服務。提供各種分布式事務服務。應用程序只需調用其提供的接口即可。
JAF:(Java Action FrameWork)JAVA安全認證框架。提供一些安全控制方面的框架。讓開發者通過各種部署和自定義實現自己的個性安全控制策略。
RMI/IIOP: (Remote Method Invocation /internet對象請求中介協議)他們主要用于通過遠程調用服務。例如,遠程有一臺計算機上運行一個程序,它提供股票分析服務,我們可以在本地計算機 上實現對其直接調用。當然這是要通過一定的規范才能在異構的系統之間進行通信。RMI是JAVA特有的。
96、JAVA語言如何進行異常處理,關鍵字:throws,throw,try,catch,finally分別代表什么意義?在try塊中可以拋出異常嗎?
Java 通過面向對象的方法進行異常處理,把各種不同的異常進行分類,并提供了良好的接口。在Java中,每個異常都是一個對象,它是Throwable類或其它 子類的實例。當一個方法出現異常后便拋出一個異常對象,該對象中包含有異常信息,調用這個對象的方法可以捕獲到這個異常并進行處理。Java的異常處理是 通過5個關鍵詞來實現的:try、catch、throw、throws和finally。一般情況下是用try來執行一段程序,如果出現異常,系統會拋 出(throws)一個異常,這時候你可以通過它的類型來捕捉(catch)它,或最后(finally)由缺省處理器來處理。
用try來指定一塊預防所有"異常"的程序。緊跟在try程序后面,應包含一個catch子句來指定你想要捕捉的"異常"的類型。
throw語句用來明確地拋出一個"異常"。
throws用來標明一個成員函數可能拋出的各種"異常"。
Finally為確保一段代碼不管發生什么"異常"都被執行一段代碼。
可 以在一個成員函數調用的外面寫一個try語句,在這個成員函數內部寫另一個try語句保護其他代碼。每當遇到一個try語句,"異常"的框架就放到堆棧上 面,直到所有的try語句都完成。如果下一級的try語句沒有對某種"異常"進行處理,堆棧就會展開,直到遇到有處理這種"異常"的try語句。
97、一個".java"源文件中是否可以包括多個類(不是內部類)?有什么限制?
可以。必須只有一個類名與文件名相同。
98、MVC的各個部分都有那些技術來實現?如何實現?
MVC 是Model-View-Controller的簡寫。"Model" 代表的是應用的業務邏輯(通過JavaBean,EJB組件實現), "View" 是應用的表示面(由JSP頁面產生),"Controller" 是提供應用的處理過程控制(一般是一個Servlet),通過這種設計模型把應用邏輯,處理過程和顯示邏輯分成不同的組件實現。這些組件可以進行交互和重 用。
99、java中有幾種方法可以實現一個線程?用什么關鍵字修飾同步方法? stop()和suspend()方法為何不推薦使用?
有兩種實現方法,分別是繼承Thread類與實現Runnable接口
用synchronized關鍵字修飾同步方法
反 對使用stop(),是因為它不安全。它會解除由線程獲取的所有鎖定,而且如果對象處于一種不連貫狀態,那么其他線程能在那種狀態下檢查和修改它們。結果 很難檢查出真正的問題所在。suspend()方法容易發生死鎖。調用suspend()的時候,目標線程會停下來,但卻仍然持有在這之前獲得的鎖定。此 時,其他任何線程都不能訪問鎖定的資源,除非被"掛起"的線程恢復運行。對任何線程來說,如果它們想恢復目標線程,同時又試圖使用任何一個鎖定的資源,就 會造成死鎖。所以不應該使用suspend(),而應在自己的Thread類中置入一個標志,指出線程應該活動還是掛起。若標志指出線程應該掛起,便用 wait()命其進入等待狀態。若標志指出線程應當恢復,則用一個notify()重新啟動線程。
100、java中有幾種類型的流?JDK為每種類型的流提供了一些抽象類以供繼承,請說出他們分別是哪些類?
字節流,字符流。字節流繼承于InputStream OutputStream,字符流繼承于InputStreamReader OutputStreamWriter。在java.io包中還有許多其他的流,主要是為了提高性能和使用方便。
101、java中會存在內存泄漏嗎,請簡單描述。
會。如:int i,i2;? return (i-i2);?? //when i為足夠大的正數,i2為足夠大的負數。結果會造成溢位,導致錯誤。
102、java中實現多態的機制是什么?
方法的重寫Overriding和重載Overloading是Java多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。
103、垃圾回收器的基本原理是什么?垃圾回收器可以馬上回收內存嗎?有什么辦法主動通知虛擬機進行垃圾回收?
對 于GC來說,當程序員創建對象時,GC就開始監控這個對象的地址、大小以及使用情況。通常,GC采用有向圖的方式記錄和管理堆(heap)中的所有對象。 通過這種方式確定哪些對象是"可達的",哪些對象是"不可達的"。當GC確定一些對象為"不可達"時,GC就有責任回收這些內存空間。可以。程序員可以手 動執行System.gc(),通知GC運行,但是Java語言規范并不保證GC一定會執行。
104、靜態變量和實例變量的區別?
static i = 10; //常量
?? class A a;? a.i =10;//可變
105、什么是java序列化,如何實現java序列化?
序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。可以對流化后的對象進行讀寫操作,也可將流化后的對象傳輸于網絡之間。序列化是為了解決在對對象流進行讀寫操作時所引發的問題。
序 列化的實現:將需要被序列化的類實現Serializable接口,該接口沒有需要實現的方法,implements Serializable只是為了標注該對象是可被序列化的,然后使用一個輸出流(如:FileOutputStream)來構造一個 ObjectOutputStream(對象流)對象,接著,使用ObjectOutputStream對象的writeObject(Object obj)方法就可以將參數為obj的對象寫出(即保存其狀態),要恢復的話則用輸入流。
106、是否可以從一個static方法內部發出對非static方法的調用?
不可以,如果其中包含對象的method();不能保證對象初始化.
107、寫clone()方法時,通常都有一行代碼,是什么?
Clone 有缺省行為,super.clone();他負責產生正確大小的空間,并逐位復制。
108、在JAVA中,如何跳出當前的多重嵌套循環?
用break; return 方法。
109、List、Map、Set三個接口,存取元素時,各有什么特點?
List 以特定次序來持有元素,可有重復元素。Set 無法擁有重復元素,內部排序。Map 保存key-value值,value可多值。
110、J2EE是什么?
J2EE 是Sun公司提出的多層(multi-diered),分布式(distributed),基于組件(component-base)的企業級應用模型 (enterpriese application model).在這樣的一個應用系統中,可按照功能劃分為不同的組件,這些組件又可在不同計算機上,并且處于相應的層次(tier)中。所屬層次包括客戶 層(clietn tier)組件,web層和組件,Business層和組件,企業信息系統(EIS)層。
111、UML方面
標準建模語言UML。用例圖,靜態圖(包括類圖、對象圖和包圖),行為圖,交互圖(順序圖,合作圖),實現圖。
112、說出一些常用的類,包,接口,請各舉5個
常用的類:BufferedReader? BufferedWriter? FileReader? FileWirter? String? Integer
常用的包:java.lang? java.awt? java.io? java.util? java.sql
常用的接口:Remote? List? Map? Document? NodeList
113、開發中都用到了那些設計模式?用在什么場合?
每個模式都描述了一個在我們的環境中不斷出現的問題,然后描述了該問題的解決方案的核心。通過這種方式,你可以無數次地使用那些已有的解決方案,無需在重復相同的工作。主要用到了MVC的設計模式。用來開發JSP/Servlet或者J2EE的相關應用。簡單工廠模式等。
114、jsp有哪些動作?作用分別是什么?
JSP 共有以下6種基本動作 jsp:include:在頁面被請求的時候引入一個文件。 jsp:useBean:尋找或者實例化一個JavaBean。 jsp:setProperty:設置JavaBean的屬性。 jsp:getProperty:輸出某個JavaBean的屬性。 jsp:forward:把請求轉到一個新的頁面。 jsp:plugin:根據瀏覽器類型為Java插件生成OBJECT或EMBED標記。
115、Anonymous Inner Class (匿名內部類) 是否可以extends(繼承)其它類,是否可以implements(實現)interface(接口)?
可以繼承其他類或完成其他接口,在swing編程中常用此方式。
116、應用服務器與WEB SERVER的區別?
應用服務器:Weblogic、Tomcat、Jboss
WEB SERVER:IIS、 Apache
117、BS與CS的聯系與區別。
C/S是Client/Server的縮寫。服務器通常采用高性能的PC、工作站或小型機,并采用大型數據庫系統,如Oracle、Sybase、Informix或 SQL Server。客戶端需要安裝專用的客戶端軟件。
B/S 是Brower/Server的縮寫,客戶機上只要安裝一個瀏覽器(Browser),如Netscape Navigator或Internet Explorer,服務器安裝Oracle、Sybase、Informix或 SQL Server等數據庫。在這種結構下,用戶界面完全通過WWW瀏覽器實現,一部分事務邏輯在前端實現,但是主要事務邏輯在服務器端實現。瀏覽器通過Web Server 同數據庫進行數據交互。
C/S 與 B/S 區別:
1.硬件環境不同:
  C/S 一般建立在專用的網絡上, 小范圍里的網絡環境, 局域網之間再通過專門服務器提供連接和數據交換服務.
  B/S 建立在廣域網之上的, 不必是專門的網絡硬件環境,例與電話上網, 租用設備. 信息自己管理. 有比C/S更強的適應范圍, 一般只要有操作系統和瀏覽器就行
2.對安全要求不同
  C/S 一般面向相對固定的用戶群, 對信息安全的控制能力很強. 一般高度機密的信息系統采用C/S 結構適宜. 可以通過B/S發布部分可公開信息.
  B/S 建立在廣域網之上, 對安全的控制能力相對弱, 可能面向不可知的用戶。
3.對程序架構不同
  C/S 程序可以更加注重流程, 可以對權限多層次校驗, 對系統運行速度可以較少考慮.
   B/S 對安全以及訪問速度的多重的考慮, 建立在需要更加優化的基礎之上. 比C/S有更高的要求 B/S結構的程序架構是發展的趨勢, 從MS的.Net系列的BizTalk 2000 Exchange 2000等, 全面支持網絡的構件搭建的系統. SUN 和IBM推的JavaBean 構件技術等,使 B/S更加成熟.
4.軟件重用不同
  C/S 程序可以不可避免的整體性考慮, 構件的重用性不如在B/S要求下的構件的重用性好.
  B/S 對的多重結構,要求構件相對獨立的功能. 能夠相對較好的重用.就入買來的餐桌可以再利用,而不是做在墻上的石頭桌子
5.系統維護不同?
  C/S 程序由于整體性, 必須整體考察, 處理出現的問題以及系統升級. 升級難. 可能是再做一個全新的系統
  B/S 構件組成,方面構件個別的更換,實現系統的無縫升級. 系統維護開銷減到最小.用戶從網上自己下載安裝就可以實現升級.
6.處理問題不同
  C/S 程序可以處理用戶面固定, 并且在相同區域, 安全要求高需求, 與操作系統相關. 應該都是相同的系統
  B/S 建立在廣域網上, 面向不同的用戶群, 分散地域, 這是C/S無法作到的. 與操作系統平臺關系最小.
7.用戶接口不同
  C/S 多是建立的Window平臺上,表現方法有限,對程序員普遍要求較高
  B/S 建立在瀏覽器上, 有更加豐富和生動的表現方式與用戶交流. 并且大部分難度減低,減低開發成本.
8.信息流不同
  C/S 程序一般是典型的中央集權的機械式處理, 交互性相對低
  B/S 信息流向可變化, B-B B-C B-G等信息、流向的變化, 更像交易中心。
118、LINUX下線程,GDI類的解釋。
LINUX實現的就是基于核心輕量級進程的"一對一"線程模型,一個線程實體對應一個核心輕量級進程,而線程之間的管理在核外函數庫中實現。
GDI類為圖像設備編程接口類庫。
119、STRUTS的應用(如STRUTS架構)
Struts 是采用Java Servlet/JavaServer Pages技術,開發Web應用程序的開放源碼的framework。采用Struts能開發出基于MVC(Model-View- Controller)設計模式的應用構架。 Struts有如下的主要功能:一.包含一個controller servlet,能將用戶的請求發送到相應的Action對象。二.JSP自由tag庫,并且在controller servlet中提供關聯支持,幫助開發員創建交互式表單應用。三.提供了一系列實用對象:XML處理、通過Java reflection APIs自動處理JavaBeans屬性、國際化的提示和消息。
120、Jdo是什么?
JDO 是Java對象持久化的新的規范,為java data object的簡稱,也是一個用于存取某種數據倉庫中的對象的標準化API。JDO提供了透明的對象存儲,因此對開發人員來說,存儲數據對象完全不需要額 外的代碼(如JDBC API的使用)。這些繁瑣的例行工作已經轉移到JDO產品提供商身上,使開發人員解脫出來,從而集中時間和精力在業務邏輯上。另外,JDO很靈活,因為它 可以在任何數據底層上運行。JDBC只是面向關系數據庫(RDBMS)JDO更通用,提供到任何數據底層的存儲功能,比如關系數據庫、文件、XML以及對 象數據庫(ODBMS)等等,使得應用可移植性更強。
121、內部類可以引用他包含類的成員嗎?有沒有什么限制?
一個內部類對象可以訪問創建它的外部類對象的內容
122、WEB SERVICE名詞解釋。JSWDL開發包的介紹。JAXP、JAXM的解釋。SOAP、UDDI,WSDL解釋。
Web ServiceWeb Service是基于網絡的、分布式的模塊化組件,它執行特定的任務,遵守具體的技術規范,這些規范使得Web Service能與其他兼容的組件進行互操作。
JAXP(Java API for XML Parsing) 定義了在Java中使用DOM, SAX, XSLT的通用的接口。這樣在你的程序中你只要使用這些通用的接口,當你需要改變具體的實現時候也不需要修改代碼。
JAXM(Java API for XML Messaging) 是為SOAP通信提供訪問方法和傳輸機制的API。
WSDL是一種 XML 格式,用于將網絡服務描述為一組端點,這些端點對包含面向文檔信息或面向過程信息的消息進行操作。這種格式首先對操作和消息進行抽象描述,然后將其綁定到具體的網絡協議和消息格式上以定義端點。相關的具體端點即組合成為抽象端點(服務)。
SOAP即簡單對象訪問協議(Simple Object Access Protocol),它是用于交換XML編碼信息的輕量級協議。
UDDI 的目的是為電子商務建立標準;UDDI是一套基于Web的、分布式的、為Web Service提供的、信息注冊中心的實現標準規范,同時也包含一組使企業能將自身提供的Web Service注冊,以使別的企業能夠發現的訪問協議的實現標準。

JAVA代碼查錯
1.
abstract class Name {
?? private String name;
?? public abstract boolean isStupidName(String name) {}
}
大俠們,這有何錯誤?
答案: 錯。abstract method必須以分號結尾,且不帶花括號。
2.
public class Something {
?? void doSomething () {
?????? private String s = "";
?????? int l = s.length();
?? }
}
有錯嗎?
答案: 錯。局部變量前不能放置任何訪問修飾符 (private,public,和protected)。final可以用來修飾局部變量
(final如同abstract和strictfp,都是非訪問修飾符,strictfp只能修飾class和method而非variable)。
3.
abstract class Something {
?? private abstract String doSomething ();
}
這好像沒什么錯吧?
答案: 錯。abstract的methods不能以private修飾。abstract的methods就是讓子類implement(實現)具體細節的,怎么可以用private把abstract
method封鎖起來呢? (同理,abstract method前不能加final)。
4.
public class Something {
?? public int addOne(final int x) {
?????? return ++x;
?? }
}
這個比較明顯。
答案: 錯。int x被修飾成final,意味著x不能在addOne method中被修改。
5.
public class Something {
?? public static void main(String[] args) {
?????? Other o = new Other();
?????? new Something().addOne(o);
?? }
?? public void addOne(final Other o) {
?????? o.i++;
?? }
}
class Other {
?? public int i;
}
和上面的很相似,都是關于final的問題,這有錯嗎?
答案: 正確。在addOne method中,參數o被修飾成final。如果在addOne method里我們修改了o的reference
(比如: o = new Other();),那么如同上例這題也是錯的。但這里修改的是o的member vairable
(成員變量),而o的reference并沒有改變。
6.
class Something {
??? int i;
??? public void doSomething() {
??????? System.out.println("i = " + i);
??? }
}
有什么錯呢? 看不出來啊。
答案: 正確。輸出的是"i = 0"。int i屬於instant variable (實例變量,或叫成員變量)。instant variable有default value。int的default value是0。
7.
class Something {
??? final int i;
??? public void doSomething() {
??????? System.out.println("i = " + i);
??? }
}
和上面一題只有一個地方不同,就是多了一個final。這難道就錯了嗎?
答 案: 錯。final int i是個final的instant variable (實例變量,或叫成員變量)。final的instant variable沒有default value,必須在constructor (構造器)結束之前被賦予一個明確的值。可以修改為"final int i = 0;"。
8.
public class Something {
???? public static void main(String[] args) {
??????? Something s = new Something();
??????? System.out.println("s.doSomething() returns " + doSomething());
??? }
??? public String doSomething() {
??????? return "Do something ...";
??? }
}
?看上去很完美。
答 案: 錯。看上去在main里call doSomething沒有什么問題,畢竟兩個methods都在同一個class里。但仔細看,main是static的。static method不能直接call non-static methods。可改成"System.out.println("s.doSomething() returns " + s.doSomething());"。同理,static method不能訪問non-static instant variable。
9.
此處,Something類的文件名叫OtherThing.java
class Something {
??? private static void main(String[] something_to_do) {???????
??????? System.out.println("Do something ...");
??? }
}
?這個好像很明顯。
答案: 正確。從來沒有人說過Java的Class名字必須和其文件名相同。但public class的名字必須和文件名相同。
10.
interface? A{
?? int x = 0;
}
class B{
?? int x =1;
}
class C extends B implements A {
?? public void pX(){
????? System.out.println(x);
?? }
?? public static void main(String[] args) {
????? new C().pX();
?? }
}
答 案:錯誤。在編譯時會發生錯誤(錯誤描述不同的JVM有不同的信息,意思就是未明確的x調用,兩個x都匹配(就象在同時import java.util和java.sql兩個包時直接聲明Date一樣)。對于父類的變量,可以用super.x來明確,而接口的屬性默認隱含為 public static final.所以可以通過A.x來明確。
11.
interface Playable {
??? void play();
}
interface Bounceable {
??? void play();
}
interface Rollable extends Playable, Bounceable {
??? Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
??? private String name;
??? public String getName() {
??????? return name;
??? }
??? public Ball(String name) {
??????? this.name = name;???????
??? }
?? public void play() {
??????? ball = new Ball("Football");
??????? System.out.println(ball.getName());
??? }
}
這個錯誤不容易發現。
答 案: 錯。"interface Rollable extends Playable, Bounceable"沒有問題。interface可繼承多個interfaces,所以這里沒錯。問題出在interface Rollable里的"Ball ball = new Ball("PingPang");"。任何在interface里聲明的interface variable (接口變量,也可稱成員變量),默認為public static final。也就是說"Ball ball = new Ball("PingPang");"實際上是"public static final Ball ball = new Ball("PingPang");"。在Ball類的Play()方法中,"ball = new Ball("Football");"改變了ball的reference,而這里的ball來自Rollable interface,Rollable interface里的ball是public static final的,final的object是不能被改變reference的。因此編譯器將在"ball = new Ball("Football");"這里顯示有錯。


橘子 2006-05-19 17:38 發表評論
]]>
關于JAVA的中文問題http://m.tkk7.com/forget/archive/2006/04/09/40064.html橘子橘子Sun, 09 Apr 2006 03:13:00 GMThttp://m.tkk7.com/forget/archive/2006/04/09/40064.htmlhttp://m.tkk7.com/forget/comments/40064.htmlhttp://m.tkk7.com/forget/archive/2006/04/09/40064.html#Feedback0http://m.tkk7.com/forget/comments/commentRss/40064.htmlhttp://m.tkk7.com/forget/services/trackbacks/40064.htmlJAVA的中文問題比較突出,主要表現在控制面板輸出,JSP頁面輸出和數據庫訪問上。本文盡量避開字體問題,而只談編碼。通過本文,你可以了解JAVA中文問題的由來,問題的解決方法,其中提了一下用JDBC訪問數據庫的方法。

二、問題描述:
1)在中文W2000中文窗口編譯和運行,用的是國際版的JDK,連接的是中文W2000下的Cp936編碼的SQL SERVER數據庫:

J:\exercise\demo\encode\HelloWorld>make
Created by XCompiler. PhiloSoft All Rights Reserved.
Wed May 30 02:54:45 CST 2001

J:\exercise\demo\encode\HelloWorld>run
Created by XRunner. PhiloSoft All Rights Reserved.
Wed May 30 02:51:33 CST 2001
中文
[B@7bc8b569
[B@7b08b569
[B@7860b569
中文
中文
????
中文
中文
????
??
??
??

2)如果在中文W2000的西文窗口(編碼為437)下編譯,用JAVA運行則由于無字體而無法正常顯示,如果象上面一樣在中文W2000的中文窗口運行,輸出為:

J:\exercise\demo\encode\HelloWorld>run
Created by XRunner. PhiloSoft All Rights Reserved.
Wed May 30 02:51:33 CST 2001
????
[B@7bc0b66a
[B@7b04b66a
[B@7818b66a
????
????
????
????
????
????
中文
中文
????

三)分析

1)出現有亂碼(也就是?)。由于只出現?而沒出現小方框,說明只是編碼有問題,而不是字體問題。 在編碼中,如果從一種字符集轉換到別一種字符集,比較典型的是從GB2312轉換到ISO8859_1(即ASCII),那么很多漢字(半個漢字)是無法映射到西文字符中去的,在這種情形下,系統就把這些字符用?代替。同樣,也存在小字符集無法到大字符集的情況,具體原因這里就不詳談了。

2)出現了中文環境編譯,中文環境運行時漢字顯示有正確也有不正確的地方,同樣,在西文環境下編譯,在中文環境下運行時也出現類似情況。這是由于自動(默認)或手工(也就new String(bytes[,encode])和bytes getBytes([encode]))轉碼的結果。

2.1)在JAVA源文件-->JAVAC-->Class-->Java-->getBytes()-->new String()-->顯示的過程中,每一步都有編碼的轉換過程,這個過程總是存在的,只是有的時候用默認的參數進行。下面我們一步一步分析為什么出現上面的情形。

2.2)這里是源代碼:

HelloWorld.java:
------------------------
public class HelloWorld
{
public static void main(String[] argv){
try{
System.out.println("中文");//1
System.out.println("中文".getBytes());//2
System.out.println("中文".getBytes("GB2312"));//3
System.out.println("中文".getBytes("ISO8859_1"));//4

System.out.println(new String("中文".getBytes()));//5
System.out.println(new String("中文".getBytes(),"GB2312"));//6
System.out.println(new String("中文".getBytes(),"ISO8859_1"));//7

System.out.println(new String("中文".getBytes("GB2312")));//8
System.out.println(new String("中文".getBytes("GB2312"),"GB2312"));//9
System.out.println(new

String("中文".getBytes("GB2312"),"ISO8859_1"));//10

System.out.println(new String("中文".getBytes("ISO8859_1")));//11
System.out.println(new

String("中文".getBytes("ISO8859_1"),"GB2312"));//12
System.out.println(new

String("中文".getBytes("ISO8859_1"),"ISO8859_1"));//13
}
catch(Exception e){
e.printStackTrace();
}
}
}

為了方便起見,在每個轉換的后面加了操作序號,分別為1,2,...,13。

2.3)需要說明的是,JAVAC是以系統默認編碼讀入源文件,然后按UNICODE進行編碼的。在JAVA運行的時候,JAVA也是采用UNICODE編碼的,并且默認輸入和輸出的都是操作系統的默認編碼,也就是說在new String(bytes[,encode])中,系統認為輸入的是編碼為encode的字節流,換句話說,如果按encode來翻譯bytes才能得到正確的結果,這個結果最后要在JAVA中保存,它還是要從這個encode轉換成Unicode,也就是說有bytes-->encode字符-->Unicode字符的轉換;而在String.getBytes([encode])中,系統要做一個Unicode字符-->encode字符-->bytes的轉換。

在這個例子中,除那個英文窗口編碼的時候除外,其實情形下默認編碼都是GBK(在本例中,我們暫且把GBK和GB2312等同看待)。

2.4)由于在未指明在上面的兩個用代碼實現的轉換中,如果未指定encode,系統將采用默認的編碼(這里為GBK),我們認為上面的5,6,7和8,9,10是一樣的,8和9、11和12也是一樣的,所以我們在討論中將只討論1,9,10,12,13。其中的2,3,4只是用于測試,不在我們的討論范圍之內。

2.5)下面我們來跟蹤程序中的“中”字的轉換歷程,我們先說在中文窗口下作的編譯和運行過程,注意在下面的字母下標中,我有意識地使用了一些數字,以表示相同,相異還是相關2.5.1)我們先以上面的13個代碼段中的的代碼9為例:

步驟 內容 地點 說明
01: C1 HelloWorld.java C1泛指一個GBK字符
02: U1 JAVAC讀取 U1泛指一個Unicode字符
03: C1 getBytes()第一步 JAVA先和操作系統交流
04: B1,B2 getBytes()第二步 然后返回字節數組
05: C1 new String()第一步 JAVA先和操作系統交流
06: U1 new String()第二步 然后返回字符
07: C1 println(String) 能顯示“中”字,內容和原來的相同

2.5.2)然后再以代碼段10為例,我們注意到只是:

步驟 內容 地點 說明
01: C1 HelloWorld.java C1泛指一個GBK字符
02: U1 JAVAC讀取 U1泛指一個Unicode字符
03: C1 getBytes()第一步 JAVA先和操作系統交流
04: B1,B2 getBytes()第二步 然后返回字節數組
05: C3,C4 new String()第一步 JAVA先和操作系統交流,這時解析錯誤
06: U5,U6 new String()第二步 然后返回字符
07: C3,C4 println(String) 由于中字給分成了兩半,在ISO8859_1中剛好也沒有字符

能映射上,所以顯示為“??”。在上面的示例中,
“中文”兩個字就顯示為“????”
2.5.3)在完全中文模式下的其它情形類似,我就不多說了

2.6)我們接著看為什么在西文DOS窗口下編譯出來的類在中文窗口下也出現類似情形,特別是為什么居然有的情形下還能正確顯示漢字。

2.6.1)我們還是先以代碼段9為例:

步驟 內容 地點 說明
01: C1C2 HelloWorld.java C1C2分別泛指一個ISO8859_1字符,“中”字被拆開
02: U3U4 JAVAC讀取 U1U2泛指一個Unicode字符
03: C5C6 getBytes()第一步 JAVA先和操作系統交流,這時解析錯誤
04: B5B6B7B8 getBytes()第二步 然后返回字節數組
05: C5C6 new String()第一步 JAVA先和操作系統交流
06: U3U4 new String()第二步 然后返回字符
07: C5C6 println(String) 雖然同是兩個字符,但已不是最初的“兩個ISO8859_1字

符”,而是“兩個BGK字符”,“中”顯示成了“??”
而“中文”就顯示成了“????”

2.6.2)下面我們以代碼段12為例,因為它能正確顯示漢字

步驟 內容 地點 說明

01: C1C2 HelloWorld.java C1C2分別泛指一個ISO8859_1字符,“中”字被拆開
02: U3U4 JAVAC讀取 U1U2泛指一個Unicode字符
03: C1C2 getBytes()第一步 JAVA先和操作系統交流(注意還是正確的哦!)
04: B5B6 getBytes()第二步 然后返回字節數組(這是很關鍵的一步!)
05: C12 new String()第一步 JAVA先和操作系統交流(這是更關鍵的一步,JAVA已經知道B5B6要解析成一個漢字!)
06: U7 new String()第二步 然后返回字符(真是一個項兩!U7包含了U3U4的信息)
07: C12 println(String) 這就原來的“中”字,很委屈被JAVAC冤枉了一回,不過被程序員撥亂反正了一下!當然,“中文”兩個字都能正確顯示了!

3)那為什么有的時候用JDBC的
new String(Recordset.getBytes(int)[,encode])
Recordset.getSting(int)
Recordset.setBytes(String.getBytes([encode]))

Recordset.setString(String)
的時候會出現亂碼了呢?

其實問題就出現在編寫JDBC的的也考慮了編碼問題,它從數據庫讀取數據后,可能自作主張做了一個從GB2312(默認編碼)到Unicode的轉換,我的這個WebLogic For SQL Server的JDBC Driver就是這樣的,當我讀字串的時候,發出讀到的不是正確的漢字,可恨的是我卻可以直接寫漢字字串,這讓人多少有點難以接受!
也就是說,我們不得不在讀或寫的時候進行轉碼,盡管這個轉碼有的時候不是那么明顯,這是因為我們使用了默認的編碼進行轉碼。JDBC Driver所做的操作,我們只有進入到源代碼內部才能清楚,不是嗎?

橘子 2006-04-09 11:13 發表評論
]]>
主站蜘蛛池模板: 男女作爱免费网站| 亚洲第一网站免费视频| 亚洲youwu永久无码精品| 黄页网站在线看免费| 亚洲最大黄色网站| 亚洲免费视频观看| 亚洲剧情在线观看| 好大好硬好爽免费视频| 亚洲经典千人经典日产| 亚洲AV无码乱码在线观看牲色| 精品久久久久久亚洲中文字幕| 亚洲国产精品13p| 精品久久久久久无码免费| 国产亚洲av片在线观看播放| 一级做a爰全过程免费视频| 亚洲毛片在线免费观看| 国产va免费精品观看精品| 亚洲AV无码专区在线观看成人| 日韩免费无码一区二区视频| 男女猛烈无遮掩视频免费软件| 精品久久香蕉国产线看观看亚洲| 日韩在线永久免费播放| 亚洲人配人种jizz| 免费在线精品视频| 国产成人精品无码免费看| 亚洲伦理一二三四| 亚洲国产成人久久综合区| 免费无码中文字幕A级毛片| 亚洲看片无码在线视频| 国产成人精品久久亚洲| 1a级毛片免费观看| 免费亚洲视频在线观看| 国产AV无码专区亚洲A∨毛片| 青青久在线视频免费观看| a一级毛片免费高清在线| 中文字幕在线观看亚洲| 暖暖日本免费在线视频| 成全视频在线观看免费| 亚洲国产成人久久综合| 久久久亚洲精品国产| 成熟女人牲交片免费观看视频|