michaelwang1978

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            10 Posts :: 0 Stories :: 0 Comments :: 0 Trackbacks

          2005年10月21日 #

          其實(shí),這個(gè)應(yīng)用是個(gè)簡單得不能再簡單的JavaScript應(yīng)用,只不過被冠以了AJAX這個(gè)今年2月份才誕生的名詞以后忽然熱了起來。AJAX這一個(gè)單詞,居然可以把一堆98年就開始用的技術(shù)推到前臺(tái)來,成為當(dāng)今在特定的圈子里最熱的詞匯,倒是一個(gè)典型的tipping point(臨界點(diǎn))的案例。就像99年Netcenter用的RSS終于在2002年開始被從blogger撿起來,并在2005年煥發(fā)了青春。

          這些用Javascript+XMLHTTPRequest的做法給我們提供了一個(gè)很廣闊的空間,可以有很多的想象。比如,在任何靜態(tài)的頁面里面,只要加入這段代碼也就可以擁有這個(gè)功能了。

          <script language=Javascript src="http://home.wangjianshuo.com/scripts/php/markit.php">
          </script>

          把鼠標(biāo)放在上面還可以知道是從哪個(gè)IP在什么時(shí)間批注的。值得注意的是,這只是一個(gè)最簡單的SAJAX應(yīng)用,如果把它應(yīng)用于地圖,以及應(yīng)用于多個(gè)網(wǎng)站之間的聯(lián)合,會(huì)有更讓人驚訝的結(jié)果出來。估計(jì),以后客齊集的后臺(tái)的管理系統(tǒng)將會(huì)是最早使用這些簡單但是有效的思想的地方。

          注:那些紅線,只是在Word里面隨手畫的。
          注二:沒有經(jīng)過測試,F(xiàn)ireFox下面什么樣子不曉得,放在其他頁面怎么樣也不曉得。。

          posted @ 2005-10-21 23:05 Michael 閱讀(182) | 評論 (0)編輯 收藏

          2005年10月11日 #

          我們期待自己成為一個(gè)優(yōu)秀的軟件模型設(shè)計(jì)者,但是,要怎樣做,又從哪里開始呢? 

            將下列原則應(yīng)用到你的軟件工程中,你會(huì)獲得立桿見影的成果。 

            1. 人遠(yuǎn)比技術(shù)重要 

            你開發(fā)軟件是為了供別人使用,沒有人使用的軟件只是沒有意義的數(shù)據(jù)的集合而已。許多在軟件方面很有成就的行家在他們事業(yè)的初期卻表現(xiàn)平平,因?yàn)樗麄兡菚r(shí)侯將主要精力都集中在技術(shù)上。顯然,構(gòu)件(components),EJB(Enterprise Java Beans)和代理(agent)是很有趣的東西。但是對于用戶來說,如果你設(shè)計(jì)的軟件很難使用或者不能滿足他們的需求,后臺(tái)用再好的技術(shù)也于事無補(bǔ)。多花點(diǎn)時(shí)間到軟件需求和設(shè)計(jì)一個(gè)使用戶能很容易理解的界面上。 
           
            2. 理解你要實(shí)現(xiàn)的東西 

            好的軟件設(shè)計(jì)人員把大多數(shù)時(shí)間花費(fèi)在建立系統(tǒng)模型上,偶爾寫一些源代碼,但那只不過是為了驗(yàn)證設(shè)計(jì)過程中所遇到的問題。這將使他們的設(shè)計(jì)方案更加可行。 

            3. 謙虛是必須的品格 

            你不可能知道一切,你甚至要很努力才能獲得足夠用的知識(shí)。軟件開發(fā)是一項(xiàng)復(fù)雜而艱巨的工作,因?yàn)檐浖_發(fā)所用到的工具和技術(shù)是在不斷更新的。而且,一個(gè)人也不可能了解軟件開發(fā)的所有過程。在日常生活中你每天接觸到的新鮮事物可能不會(huì)太多。但是對于從事軟件開發(fā)的人來說,每天可以學(xué)習(xí)很多新東西(如果愿意的話)。 

            4. 需求就是需求 

            如果你沒有任何需求,你就不要?jiǎng)邮珠_發(fā)任何軟件。成功的軟件取決于時(shí)間(在用戶要求的時(shí)間內(nèi)完成)、預(yù)算和是否滿足用戶的需求。如果你不能確切知道用戶需要的是什么,或者軟件的需求定義,那么你的工程注定會(huì)失敗。 

            5. 需求其實(shí)很少改變,改變的是你對需求的理解 

            Object ToolSmiths公司(www.objecttoolsmiths.com)的Doug Smith常喜歡說:“分析是一門科學(xué),設(shè)計(jì)是一門藝術(shù)”。他的意思是說在眾多的“正確”分析模型中只存在一個(gè)最“正確”分析模型可以完全滿足解決某個(gè)具體問題的需要(我理解的意思是需求分析需要一絲不茍、精確的完成,而設(shè)計(jì)的時(shí)候反而可以發(fā)揮創(chuàng)造力和想象力 - 譯者注)。 

            如果需求經(jīng)常改動(dòng),很可能是你沒有作好需求分析,并不是需求真的改變了。 

            你可以抱怨用戶不能告訴你他們想得到什么,但是不要忘記,收集需求信息是你工作。 

            你可以說是新來的開發(fā)人員把事情搞得一團(tuán)糟,但是,你應(yīng)該確定在工程的第一天就告訴他們應(yīng)該做什么和怎樣去做。 

            如果你覺得公司不讓你與用戶充分接觸,那只能說明公司的管理層并不是真正支持你的項(xiàng)目。 

            你可以抱怨公司有關(guān)軟件工程的管理制度不合理,但你必須了解大多同行公司是怎么做的。 

            你可以借口說你們的競爭對手的成功是因?yàn)樗麄冇辛艘粋€(gè)新的理念,但是為什么你沒先想到呢? 

            需求真正改變的情況很少,但是沒有做好需求分析工作的理由卻很多。 

            6. 經(jīng)常閱讀 

            在這個(gè)每日都在發(fā)生變化的產(chǎn)業(yè)中,你不可能在已取得的成就上陶醉太久。 

            每個(gè)月至少讀2、3本專業(yè)雜志或者1本專業(yè)書籍。保持不落伍需要付出很多的時(shí)間和金錢,但會(huì)使你成為一個(gè)很有實(shí)力的競爭者。 

            7. 降低軟件模塊間的耦合度 

            高耦合度的系統(tǒng)是很難維護(hù)的。一處的修改引起另一處甚至更多處的變動(dòng)。 

            你可以通過以下方法降低程序的耦合度:隱藏實(shí)現(xiàn)細(xì)節(jié),強(qiáng)制構(gòu)件接口定義,不使用公用數(shù)據(jù)結(jié)構(gòu),不讓應(yīng)用程序直接操作數(shù)據(jù)庫(我的經(jīng)驗(yàn)法則是:當(dāng)應(yīng)用程序員在寫SQL代碼的時(shí)候,你的程序的耦合度就已經(jīng)很高了)。 

            耦合度低的軟件可以很容易被重用、維護(hù)和擴(kuò)充。 

            8. 提高軟件的內(nèi)聚性 

            如果一個(gè)軟件的模塊只實(shí)現(xiàn)一個(gè)功能,那么該模塊具有高內(nèi)聚性。高內(nèi)聚性的軟件更容易維護(hù)和改進(jìn)。 

            判斷一個(gè)模塊是否有高的內(nèi)聚性,看一看你是否能夠用一個(gè)簡單的句子描述它的功能就行了。如果你用了一段話或者你需要使用類似“和”、“或”等連詞,則說明你需要將該模塊細(xì)化。 

            只有高內(nèi)聚性的模塊才可能被重用。 

            9. 考慮軟件的移植性 

            移植是軟件開發(fā)中一項(xiàng)具體而又實(shí)際的工作,不要相信某些軟件工具的廣告宣傳(比如java 的宣傳口號(hào)write once run many ? 譯者注)。 

            即使僅僅對軟件進(jìn)行常規(guī)升級,也要把這看得和向另一個(gè)操作系統(tǒng)或數(shù)據(jù)庫移植一樣重要。 

            記得從16位Windows移植到32位windows的“樂趣”嗎 ?當(dāng)你使用了某個(gè)操作系統(tǒng)的特性,如它的進(jìn)程間通信(IPC)策略,或用某數(shù)據(jù)庫專有語言寫了存儲(chǔ)過程。你的軟件和那個(gè)特定的產(chǎn)品結(jié)合度就已經(jīng)很高了。 

            好的軟件設(shè)計(jì)者把那些特有的實(shí)現(xiàn)細(xì)節(jié)打包隱藏起來,所以,當(dāng)那些特性該變的時(shí)候,你的僅僅需要更新那個(gè)包就可以了。 

            10. 接受變化 

            這是一句老話了:唯一不變的只有變化。 

            你應(yīng)該將所有系統(tǒng)將可能發(fā)生的變化以及潛在需求記錄下來,以便將來能夠?qū)崿F(xiàn)(參見“Architecting for Change”,Thinking Objectively, May 1999) 

            通過在建模期間考慮這些假設(shè)的情況,你就有可能開發(fā)出足夠強(qiáng)壯且容易維護(hù)的軟件。設(shè)計(jì)強(qiáng)壯的軟件是你最基本的目標(biāo)。 

            11. 不要低估對軟件規(guī)模的需求 

            Internet 帶給我們的最大的教訓(xùn)是你必須在軟件開發(fā)的最初階段就考慮軟件規(guī)模的可擴(kuò)充性。 

            今天只有100人的部門使用的應(yīng)用程序,明天可能會(huì)被有好幾萬人的組織使用,下月,通過因特網(wǎng)可能會(huì)有幾百萬人使用它。 

            在軟件設(shè)計(jì)的初期,根據(jù)在用例模型中定義的必須支持的基本事務(wù)處理,確定軟件的基本功能。然后,在建造系統(tǒng)的時(shí)候再逐步加入比較常用的功能。 

            在設(shè)計(jì)的開始考慮軟件的規(guī)模需求,避免在用戶群突然增大的情況下,重寫軟件。 

            12. 性能僅僅是很多設(shè)計(jì)因素之一 

            關(guān)注軟件設(shè)計(jì)中的一個(gè)重要因素--性能,這好象也是用戶最關(guān)心的事情。一個(gè)性能不佳的軟件將不可避免被重寫。 

            但是你的設(shè)計(jì)還必須具有可靠性,可用性,便攜性和可擴(kuò)展性。你應(yīng)該在工程開始就應(yīng)該定義并區(qū)分好這些因素,以便在工作中恰當(dāng)使用。性能可以是,也可以不是優(yōu)先級最高的因素,我的觀點(diǎn)是,給每個(gè)設(shè)計(jì)因素應(yīng)有的考慮。 

            13. 管理接口 

            “UML User Guide”(Grady Booch,Ivar Jacobson和Jim Rumbaugh ,Addison Wesley, 1999)中指出,你應(yīng)該在開發(fā)階段的早期就定義軟件模塊之間的接口。 

            這有助于你的開發(fā)人員全面理解軟件的設(shè)計(jì)結(jié)構(gòu)并取得一致意見,讓各模塊開發(fā)小組相對獨(dú)立的工作。一旦模塊的接口確定之后,模塊怎樣實(shí)現(xiàn)就不是很重要了。 

            從根本上說,如果你不能夠定義你的模塊“從外部看上去會(huì)是什么樣子”,你肯定也不清楚模塊內(nèi)要實(shí)現(xiàn)什么。 

            14. 走近路需要更長的時(shí)間 

            在軟件開發(fā)中沒有捷徑可以走。 

            縮短你的在需求分析上花的時(shí)間,結(jié)果只能是開發(fā)出來的軟件不能滿足用戶的需求,必須被重寫。 

            在軟件建模上每節(jié)省一周,在將來的編碼階段可能會(huì)多花幾周時(shí)間,因?yàn)槟阍谌嫠伎贾熬蛣?dòng)手寫程序。 

            你為了節(jié)省一天的測試時(shí)間而漏掉了一個(gè)bug,在將來的維護(hù)階段,可能需要花幾周甚至幾個(gè)月的時(shí)間去修復(fù)。與其如此,還不如重新安排一下項(xiàng)目計(jì)劃。 

            避免走捷徑,只做一次但要做對(do it once by doing it right)。 

            15. 別信賴任何人 

            產(chǎn)品和服務(wù)銷售公司不是你的朋友,你的大部分員工和高層管理人員也不是。 

            大部分產(chǎn)品供應(yīng)商希望把你牢牢綁在他們的產(chǎn)品上,可能是操作系統(tǒng),數(shù)據(jù)庫或者某個(gè)開發(fā)工具。 

            大部分的顧問和承包商只關(guān)心你的錢并不是你的工程(停止向他們付款,看一看他們會(huì)在周圍呆多長時(shí)間)。 

            大部分程序員認(rèn)為他們自己比其他人更優(yōu)秀,他們可能拋棄你設(shè)計(jì)的模型而用自己認(rèn)為更好的。 

            只有良好的溝通才能解決這些問題。 

            要明確的是,不要只依靠一家產(chǎn)品或服務(wù)提供商,即使你的公司(或組織)已經(jīng)在建模、文檔和過程等方面向那個(gè)公司投入了很多錢。 

            16. 證明你的設(shè)計(jì)在實(shí)踐中可行 

            在設(shè)計(jì)的時(shí)候應(yīng)當(dāng)先建立一個(gè)技術(shù)原型, 或者稱為“端到端”原型。以證明你的設(shè)計(jì)是能夠工作的。 

            你應(yīng)該在開發(fā)工作的早期做這些事情,因?yàn)?,如果軟件的設(shè)計(jì)方案是不可行的,在編碼實(shí)現(xiàn)階段無論采取什么措施都于事無補(bǔ)。技術(shù)原型將證明你的設(shè)計(jì)的可行性,從而,你的設(shè)計(jì)將更容易獲得支持。 

            17. 應(yīng)用已知的模式 

            目前,我們有大量現(xiàn)成的分析和設(shè)計(jì)模式以及問題的解決方案可以使用。 

            一般來說,好的模型設(shè)計(jì)和開發(fā)人員,都會(huì)避免重新設(shè)計(jì)已經(jīng)成熟的并被廣泛應(yīng)用的東西。 
          http://www.ambysoft.com/processPatternsPage.html 收藏了許多開發(fā)模式的信息。 

            18. 研究每個(gè)模型的長處和弱點(diǎn) 

            目前有很多種類的模型可以使用,如下圖所示。用例捕獲的是系統(tǒng)行為需求,數(shù)據(jù)模型則描述支持一個(gè)系統(tǒng)運(yùn)行所需要的數(shù)據(jù)構(gòu)成。你可能會(huì)試圖在用例中加入實(shí)際數(shù)據(jù)描述,但是,這對開發(fā)者不是非常有用。同樣,數(shù)據(jù)模型對描述軟件需求來說是無用的。每個(gè)模型在你建模過程中有其相應(yīng)的位置,但是,你需要明白在什么地方,什么時(shí)候使用它們。 

            19. 在現(xiàn)有任務(wù)中應(yīng)用多個(gè)模型 

            當(dāng)你收集需求的時(shí)候,考慮使用用例模型,用戶界面模型和領(lǐng)域級的類模型。 

            當(dāng)你設(shè)計(jì)軟件的時(shí)候,應(yīng)該考慮制作類模型,順序圖、狀態(tài)圖、協(xié)作圖和最終的軟件實(shí)際物理模型。 

            程序設(shè)計(jì)人員應(yīng)該慢慢意識(shí)到,僅僅使用一個(gè)模型而實(shí)現(xiàn)的軟件要么不能夠很好地滿足用戶的需求,要么很難擴(kuò)展。 

            20. 教育你的聽眾 

            你花了很大力氣建立一個(gè)很成熟的系統(tǒng)模型,而你的聽眾卻不能理解它們,甚至更糟-連為什么要先建立模型都不知道。那么你的工作是毫無意義的。 

            教給你開發(fā)人員基本的建模知識(shí);否則,他們會(huì)只看看你畫的漂亮圖表,然后繼續(xù)編寫不規(guī)范的程序。 

            另外, 你還需要告訴你的用戶一些需求建模的基礎(chǔ)知識(shí)。給他們解釋你的用例(uses case)和用戶界面模型,以使他們能夠明白你要表達(dá)地東西。當(dāng)每個(gè)人都能使用一個(gè)通用的設(shè)計(jì)語言的時(shí)候(比如UML-譯者注),你的團(tuán)隊(duì)才能實(shí)現(xiàn)真正的合作。 

            21. 帶工具的傻瓜還是傻瓜 

            你給我CAD/CAM工具,請我設(shè)計(jì)一座橋。但是,如果那座橋建成的話,我肯定不想當(dāng)?shù)谝粋€(gè)從橋上過的人,因?yàn)槲覍ㄖ桓[不通。 

            使用一個(gè)很優(yōu)秀的CASE工具并不能使你成為一個(gè)建模專家,只能使你成為一個(gè)優(yōu)秀CASE工具的使用者。成為一個(gè)優(yōu)秀的建模專家需要多年的積累,不會(huì)是一周針對某個(gè)價(jià)值幾千美元工具的培訓(xùn)。一個(gè)優(yōu)秀的CASE工具是很重要,但你必須學(xué)習(xí)使用它,并能夠使用它設(shè)計(jì)它支持的模型。 

            22. 理解完整的過程 

            好的設(shè)計(jì)人員應(yīng)該理解整個(gè)軟件過程,盡管他們可能不是精通全部實(shí)現(xiàn)細(xì)節(jié)。 

            軟件開發(fā)是一個(gè)很復(fù)雜的過程,還記得《object-oriented software process》第36頁的內(nèi)容嗎?除了編程、建模、測試等你擅長工作外,還有很多工作要做。 

            好的設(shè)計(jì)者需要考慮全局。必須從長遠(yuǎn)考慮如何使軟件滿足用戶需要,如何提供維護(hù)和技術(shù)支持等。 

            23. 常做測試,早做測試 

            如果測試對你的軟件來說是無所謂的,那么你的軟件多半也沒什么必要被開發(fā)出來。 

            建立一個(gè)技術(shù)原型供技術(shù)評審使用,以檢驗(yàn)?zāi)愕能浖P汀?nbsp;

            在軟件生命周期中,越晚發(fā)現(xiàn)的錯(cuò)誤越難修改,修改成本越昂貴。盡可能早的做測試是很值得的。 

            24. 把你的工作歸檔 

            不值得歸檔的工作往往也不值得做。歸檔你的設(shè)想,以及根據(jù)設(shè)想做出的決定;歸檔軟件模型中很重要但不很明顯的部分。 給每個(gè)模型一些概要描述以使別人很快明白模型所表達(dá)的內(nèi)容。 

            25. 技術(shù)會(huì)變,基本原理不會(huì) 

            如果有人說“使用某種開發(fā)語言、某個(gè)工具或某某技術(shù),我們就不需要再做需求分析,建模,編碼或測試”。不要相信,這只說明他還缺乏經(jīng)驗(yàn)。拋開技術(shù)和人的因素,實(shí)際上軟件開發(fā)的基本原理自20世紀(jì)70年代以來就沒有改變過。你必須還定義需求,建模,編碼,測試,配置,面對風(fēng)險(xiǎn),發(fā)布產(chǎn)品,管理工作人員等等。 

            軟件建模技術(shù)是需要多年的實(shí)際工作才能完全掌握的。好在你可以從我的建議開始,完善你們自己的軟件開發(fā)經(jīng)驗(yàn)。 

            以雞湯開始,加入自己的蔬菜。然后,開始享受你自己的豐盛晚餐吧
          posted @ 2005-10-11 09:26 Michael 閱讀(157) | 評論 (0)編輯 收藏

          現(xiàn)在到eclipse網(wǎng)站可以下到中文包了!
              有兩個(gè),分別是:NLpack1-eclipse-SDK-3.1.1a-win32.zip和NLpack1_FeatureOverlay-eclipse-SDK-3.1.1.zip。
              后者是前者的補(bǔ)充。
             
              在我的機(jī)子上,這兩個(gè)中文包只適合eclipse3.1.1版本,3.1版本都不適合,但網(wǎng)上有人說可以用,就不得而知了。eclipse3.1.1版本已經(jīng)出了一段時(shí)日了,但一直都沒有使用過,今天是試用了一下,Lomboz還可以用,但de.strutsbox_20050804就不能用了。
              不過,裝上lomboz,NLpack1_FeatureOverlay-eclipse-SDK-3.1.1.zip就不怎么起作用了。

              myeclipseME-4.0GA_E3.1ManualInstall版在這個(gè)版本下面也不能使用。

              eclipse3.1.1在功能上與3.1版沒什么區(qū)別,但對插件兼容就不敢恭維了。

              eclipse3.1.1.jpg
          posted @ 2005-10-11 09:15 Michael 閱讀(1277) | 評論 (0)編輯 收藏

          開放源代碼協(xié)會(huì)通過Linux軟件開發(fā)公司Ximian開始了一個(gè)旨在將微軟.Net平臺(tái)移植到Linux上來的項(xiàng)目。這個(gè)叫做Mono工程的項(xiàng)目包括創(chuàng)建一個(gè)開發(fā)平臺(tái)允許人們?yōu)榛贚inux和基于Windows系統(tǒng)的.Net開發(fā)應(yīng)用程序。據(jù)Ximian公司的首席技術(shù)官員Miguel de Icaza說Mono項(xiàng)目的起因是GNOME社團(tuán)特別是Ximain公司對于一個(gè)改進(jìn)的開發(fā)工具的需要。

          但是Mono項(xiàng)目的影響確是更加深遠(yuǎn)的,因?yàn)檫@些開發(fā)工具是基于CLI(通用語言架構(gòu))和微軟提交給歐洲計(jì)算機(jī)制造協(xié)會(huì)(ECMA)的C#實(shí)現(xiàn)標(biāo)準(zhǔn)的。如果Mono能夠完成基于這些標(biāo)準(zhǔn)創(chuàng)建一套Linux開發(fā)工具集的目標(biāo)的話,開發(fā)者將能夠編寫同時(shí)在Windows和Linux上運(yùn)行的.Net程序,這些程序甚至還可能在其它非Windows的操作系統(tǒng)上運(yùn)行,比方Unix。

          除了實(shí)際的開發(fā)過程,Mono項(xiàng)目的工具必須在開放源代碼社團(tuán)的內(nèi)部完成而不能違反微軟的知識(shí)產(chǎn)權(quán)專利--這實(shí)際上意味著開發(fā)者們必須基于標(biāo)準(zhǔn)重新構(gòu)造這些工具而不能查看微軟的任何源代碼。

          Mono項(xiàng)目包括三個(gè)核心的部分:一個(gè)C#語言的編譯器,一個(gè)CLI和一個(gè)類庫。 CLI是包含了類加載器的虛擬機(jī),實(shí)時(shí)的編譯器,和一個(gè)運(yùn)行時(shí)環(huán)境的垃圾收集器。CLI這個(gè)組件將允許用C#編寫的應(yīng)用程序能夠在象Linux這樣的非Windows操作系統(tǒng)上運(yùn)行。這與Java世界中Java虛擬機(jī)能夠讓一個(gè)應(yīng)用程序在不同的操作系統(tǒng)上運(yùn)行是類似的。

          Mono項(xiàng)目的類庫能夠讓應(yīng)用程序完成核心的諸如XML處理,文件輸入輸出,和連接網(wǎng)絡(luò)之類的任務(wù)。它將會(huì)和微軟的CLI兼容(與微軟在.Net framework中發(fā)布的東西緊密的配套),還有一點(diǎn)就是將由開放源代碼團(tuán)體編寫的額外的類庫也將和CLI兼容。

          Ximian公司的de Icaza希望在年底到達(dá)項(xiàng)目的一個(gè)里程碑,這時(shí)編譯器將能夠編譯類庫了。圖形用戶界面組件--創(chuàng)建GUI程序所需的類庫--將在明年中完成。

          “我們在這個(gè)方面工作的原因是希望升級我們的開發(fā)平臺(tái)來創(chuàng)建我們的Evolution桌面應(yīng)用程序,”de Icazo說。Evolution是Ximian公司的電子郵件客戶端及個(gè)人和工作組信息管理程序?!爱?dāng)我們看見.Net framework的時(shí)候,我們覺得這些就是我們將用來開發(fā)我們下一代產(chǎn)品要使用的工具,”他說。

          Ximian并不將Mono和它自己看作是給Linux開發(fā)者一種途徑在可用的開發(fā)工具方面趕上Windows。其實(shí),Linux開發(fā)者將更喜歡用他們目前使用的工具來編寫的編譯應(yīng)用程序。Ximian 將另一個(gè)開放源代碼項(xiàng)目,SharpDevelop看作是用來提供與微軟Visual Studio .Net類似的集成開發(fā)環(huán)境的一種途徑。

          通過以開放源代碼的方式開發(fā)Mono,這個(gè)項(xiàng)目包含了許多對開發(fā)過程擁有廣泛興趣的人們。雖然Ximian可能希望找一些改進(jìn)的開發(fā)工具來加速它的應(yīng)用程序的開發(fā)過程,但其它的開發(fā)者可能是希望找到能夠讓他們在Windows上編寫程序然后在Linux系統(tǒng)上運(yùn)行它們的開發(fā)工具。

          其中的一個(gè)大問題是如何避免微軟的知識(shí)產(chǎn)權(quán)保護(hù)。“我們避免知識(shí)產(chǎn)權(quán)保護(hù)的方法是堅(jiān)持非研究性的主題并使用現(xiàn)有的技術(shù)實(shí)現(xiàn)其功能,”de Icaza說。例如,Mono JIT編譯器沒有使用任何先進(jìn)的JIT編譯器技術(shù)。相反Mono的版本是基于老的JIT技術(shù)的。

          De Icaza還聲稱Mono必須“著眼大處”還不僅僅是去年ECMA規(guī)定了些什么。也就是說,Ximian計(jì)劃參與標(biāo)準(zhǔn)的制定過程并創(chuàng)建類庫來提高.Net framework的薄弱之處,比方說電子郵件管理。

          據(jù)Giga Information Group的副分析師Stacey Quandt稱,微軟不太可能支持Mono因?yàn)槠涫跈?quán)是與GNU 通用公眾證書為C#的授權(quán)和GNU 弱公眾證書為類庫和運(yùn)行庫的授權(quán)聯(lián)系在一起的。

          但即使微軟不支持Mono,Mono的存在也證實(shí)了微軟對于.Net能夠移植到其它平臺(tái)的聲明是正確的。

          Quandt說面向更廣泛的開發(fā)團(tuán)體是Mono面臨的另一個(gè)挑戰(zhàn)。例如IBM和Sun都在Java上花費(fèi)了巨額的投資,自然也就很難容忍競爭行為。
          posted @ 2005-10-11 08:46 Michael 閱讀(195) | 評論 (0)編輯 收藏

          2005年10月8日 #

          結(jié)合 JavaBean 和 JDBC,我們可以編寫出結(jié)構(gòu)清晰,使用方便的數(shù)據(jù)庫應(yīng)用程序。

          db 類封裝了數(shù)據(jù)庫操作,包括建立和關(guān)閉連接,以及執(zhí)行SQL查詢操作。
          emp類使用db類并針對EMP 表完成了根據(jù)工號(hào)查詢員工資料的功能,并提供了員工姓名的getter方法。

          package db;

          import java.net.*;
          import java.sql.*;
          import java.io.*;


          public class db {
           Connection conn;
           Statement stmt;
           ResultSet rs;
           
           //數(shù)據(jù)庫連接
           public void getConnection(){
            try{
             Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
             conn = DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=Hotel;User=sa;Password=sa");
            }
            catch (Exception e){
             System.out.println(e.getMessage());
             }
            }
           
           //關(guān)閉連接
           public void closeConnection(){
            try{
             if (conn != null){
              conn.close();
             }
            }
            catch(Exception e){
             System.out.println(e.getMessage());
            }
           }
           
           //對數(shù)據(jù)庫進(jìn)行操作
           public ResultSet executeQuery(String sql){
            rs = null;
            try{
             getConnection();
             if (conn != null){
              stmt = conn.createStatement();
              rs = stmt.executeQuery(sql);
             }
            }
            catch (Exception e){
             System.out.println(e.getMessage());
            }
            return rs;
           }

          }

          package db;

          import java.sql.*;


          public class emp extends db {
           private String empno;
           private String ename;
           
           public emp(String em){
            empno = em;
           }
           
           //執(zhí)行Sql語句 對屬性ename賦值
           public void query(){
            try{
             String sSql = "select * from emp where empno =" + empno;
             ResultSet rs = executeQuery(sSql);
             if (rs.next()){
              ename = rs.getString("ename");
             }
             
            }
            catch (Exception e){
             System.out.println(e.getMessage());
            }
           }
           
           //得到ename
           public String getEname(){
            return ename;
           }

          }


          package db;

          import java.io.*;
          import java.sql.*;


          public class TestBean {
           public static void main(String args[]){
            String empno;
            emp em;
            
            try{
             System.out.println("請輸入工號(hào):");
             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
             empno = br.readLine();
             em = new em(empno);
             em.query();
             System.out.println("工號(hào)為" + empno + "的員工姓名是:" + em.getEname());
             em.closeConnection();
             
            }
            catch (Exception e){
             System.out.println(e.getMessage());
            }
            
           }

          }


          posted @ 2005-10-08 21:28 Michael 閱讀(396) | 評論 (0)編輯 收藏

          Java數(shù)據(jù)庫連接(JDBC)API是一系列能夠讓Java編程人員訪問數(shù)據(jù)庫的接口,各個(gè)開發(fā)商的接口并不完全相同。在使用多年的Oracle公司的JDBC后,我積累了許多技巧,這些技巧能夠使我們更好地發(fā)揮系統(tǒng)的性能和實(shí)現(xiàn)更多的功能。

            1、在客戶端軟件開發(fā)中使用Thin驅(qū)動(dòng)程序

            在開發(fā)Java軟件方面,Oracle的數(shù)據(jù)庫提供了四種類型的驅(qū)動(dòng)程序,二種用于應(yīng)用軟件、applets、servlets等客戶端軟件,另外二種用于數(shù)據(jù)庫中的Java存儲(chǔ)過程等服務(wù)器端軟件。在客戶機(jī)端軟件的開發(fā)中,我們可以選擇OCI驅(qū)動(dòng)程序或Thin驅(qū)動(dòng)程序。OCI驅(qū)動(dòng)程序利用Java本地化接口(JNI),通過Oracle客戶端軟件與數(shù)據(jù)庫進(jìn)行通訊。Thin驅(qū)動(dòng)程序是純Java驅(qū)動(dòng)程序,它直接與數(shù)據(jù)庫進(jìn)行通訊。為了獲得最高的性能,Oracle建議在客戶端軟件的開發(fā)中使用OCI驅(qū)動(dòng)程序,這似乎是正確的。但我建議使用Thin驅(qū)動(dòng)程序,因?yàn)橥ㄟ^多次測試發(fā)現(xiàn),在通常情況下,Thin驅(qū)動(dòng)程序的性能都超過了OCI驅(qū)動(dòng)程序。

            2、關(guān)閉自動(dòng)提交功能,提高系統(tǒng)性能

            在第一次建立與數(shù)據(jù)庫的連接時(shí),在缺省情況下,連接是在自動(dòng)提交模式下的。為了獲得更好的性能,可以通過調(diào)用帶布爾值false參數(shù)的Connection類的setAutoCommit()方法關(guān)閉自動(dòng)提交功能,如下所示:

            conn.setAutoCommit(false);

            值得注意的是,一旦關(guān)閉了自動(dòng)提交功能,我們就需要通過調(diào)用Connection類的commit()和rollback()方法來人工的方式對事務(wù)進(jìn)行管理。

            3、在動(dòng)態(tài)SQL或有時(shí)間限制的命令中使用Statement對象

            在執(zhí)行SQL命令時(shí),我們有二種選擇:可以使用PreparedStatement對象,也可以使用Statement對象。無論多少次地使用同一個(gè)SQL命令,PreparedStatement都只對它解析和編譯一次。當(dāng)使用Statement對象時(shí),每次執(zhí)行一個(gè)SQL命令時(shí),都會(huì)對它進(jìn)行解析和編譯。這可能會(huì)使你認(rèn)為,使用PreparedStatement對象比使用Statement對象的速度更快。然而,我進(jìn)行的測試表明,在客戶端軟件中,情況并非如此。因此,在有時(shí)間限制的SQL操作中,除非成批地處理SQL命令,我們應(yīng)當(dāng)考慮使用Statement對象。

            此外,使用Statement對象也使得編寫動(dòng)態(tài)SQL命令更加簡單,因?yàn)槲覀兛梢詫⒆址B接在一起,建立一個(gè)有效的SQL命令。因此,我認(rèn)為,Statement對象可以使動(dòng)態(tài)SQL命令的創(chuàng)建和執(zhí)行變得更加簡單。

            4、利用helper函數(shù)對動(dòng)態(tài)SQL命令進(jìn)行格式化

            在創(chuàng)建使用Statement對象執(zhí)行的動(dòng)態(tài)SQL命令時(shí),我們需要處理一些格式化方面的問題。例如,如果我們想創(chuàng)建一個(gè)將名字O'Reilly插入表中的SQL命令,則必須使用二個(gè)相連的“''”號(hào)替換O'Reilly中的“'”號(hào)。完成這些工作的最好的方法是創(chuàng)建一個(gè)完成替換操作的helper方法,然后在連接字符串心服用公式表達(dá)一個(gè)SQL命令時(shí),使用創(chuàng)建的helper方法。與此類似的是,我們可以讓helper方法接受一個(gè)Date型的值,然后讓它輸出基于Oracle的to_date()函數(shù)的字符串表達(dá)式。

            5、利用PreparedStatement對象提高數(shù)據(jù)庫的總體效率

            在使用PreparedStatement對象執(zhí)行SQL命令時(shí),命令被數(shù)據(jù)庫進(jìn)行解析和編譯,然后被放到命令緩沖區(qū)。然后,每當(dāng)執(zhí)行同一個(gè)PreparedStatement對象時(shí),它就會(huì)被再解析一次,但不會(huì)被再次編譯。在緩沖區(qū)中可以發(fā)現(xiàn)預(yù)編譯的命令,并且可以重新使用。在有大量用戶的企業(yè)級應(yīng)用軟件中,經(jīng)常會(huì)重復(fù)執(zhí)行相同的SQL命令,使用PreparedStatement對象帶來的編譯次數(shù)的減少能夠提高數(shù)據(jù)庫的總體性能。如果不是在客戶端創(chuàng)建、預(yù)備、執(zhí)行PreparedStatement任務(wù)需要的時(shí)間長于Statement任務(wù),我會(huì)建議在除動(dòng)態(tài)SQL命令之外的所有情況下使用PreparedStatement對象。

            6、在成批處理重復(fù)的插入或更新操作中使用PreparedStatement對象

            如果成批地處理插入和更新操作,就能夠顯著地減少它們所需要的時(shí)間。Oracle提供的Statement和 CallableStatement并不真正地支持批處理,只有PreparedStatement對象才真正地支持批處理。我們可以使用addBatch()和executeBatch()方法選擇標(biāo)準(zhǔn)的JDBC批處理,或者通過利用PreparedStatement對象的setExecuteBatch()方法和標(biāo)準(zhǔn)的executeUpdate()方法選擇速度更快的Oracle專有的方法。要使用Oracle專有的批處理機(jī)制,可以以如下所示的方式調(diào)用setExecuteBatch():
          PreparedStatement pstmt3D null;
          try {
          ((OraclePreparedStatement)
          pstmt).setExecuteBatch(30);
          ...
          pstmt.executeUpdate();
          }


            調(diào)用setExecuteBatch()時(shí)指定的值是一個(gè)上限,當(dāng)達(dá)到該值時(shí),就會(huì)自動(dòng)地引發(fā)SQL命令執(zhí)行,標(biāo)準(zhǔn)的executeUpdate()方法就會(huì)被作為批處理送到數(shù)據(jù)庫中。我們可以通過調(diào)用PreparedStatement類的sendBatch()方法隨時(shí)傳輸批處理任務(wù)。

            7、使用Oracle locator方法插入、更新大對象(LOB)

            Oracle的PreparedStatement類不完全支持BLOB和CLOB等大對象的處理,尤其是Thin驅(qū)動(dòng)程序不支持利用PreparedStatement對象的setObject()和setBinaryStream()方法設(shè)置BLOB的值,也不支持利用setCharacterStream()方法設(shè)置CLOB的值。只有l(wèi)ocator本身中的方法才能夠從數(shù)據(jù)庫中獲取LOB類型的值??梢允褂肞reparedStatement對象插入或更新LOB,但需要使用locator才能獲取LOB的值。由于存在這二個(gè)問題,因此,我建議使用locator的方法來插入、更新或獲取LOB的值。

            8、使用SQL92語法調(diào)用存儲(chǔ)過程

            在調(diào)用存儲(chǔ)過程時(shí),我們可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并沒有什么實(shí)際的好處,而且會(huì)給以后維護(hù)你的應(yīng)用程序的開發(fā)人員帶來麻煩,因此,我建議在調(diào)用存儲(chǔ)過程時(shí)使用SQL92。

            9、使用Object SQL將對象模式轉(zhuǎn)移到數(shù)據(jù)庫中

            既然可以將Oracle的數(shù)據(jù)庫作為一種面向?qū)ο蟮臄?shù)據(jù)庫來使用,就可以考慮將應(yīng)用程序中的面向?qū)ο竽J睫D(zhuǎn)到數(shù)據(jù)庫中。目前的方法是創(chuàng)建Java bean作為偽裝的數(shù)據(jù)庫對象,將它們的屬性映射到關(guān)系表中,然后在這些bean中添加方法。盡管這樣作在Java中沒有什么問題,但由于操作都是在數(shù)據(jù)庫之外進(jìn)行的,因此其他訪問數(shù)據(jù)庫的應(yīng)用軟件無法利用對象模式。如果利用Oracle的面向?qū)ο蟮募夹g(shù),可以通過創(chuàng)建一個(gè)新的數(shù)據(jù)庫對象類型在數(shù)據(jù)庫中模仿其數(shù)據(jù)和操作,然后使用JPublisher等工具生成自己的Java bean類。如果使用這種方式,不但Java應(yīng)用程序可以使用應(yīng)用軟件的對象模式,其他需要共享你的應(yīng)用中的數(shù)據(jù)和操作的應(yīng)用軟件也可以使用應(yīng)用軟件中的對象模式。

            10、利用SQL完成數(shù)據(jù)庫內(nèi)的操作

            我要向大家介紹的最重要的經(jīng)驗(yàn)是充分利用SQL的面向集合的方法來解決數(shù)據(jù)庫處理需求,而不是使用Java等過程化的編程語言。

            如果編程人員要在一個(gè)表中查找許多行,結(jié)果中的每個(gè)行都會(huì)查找其他表中的數(shù)據(jù),最后,編程人員創(chuàng)建了獨(dú)立的UPDATE命令來成批地更新第一個(gè)表中的數(shù)據(jù)。與此類似的任務(wù)可以通過在set子句中使用多列子查詢而在一個(gè)UPDATE命令中完成。當(dāng)能夠在單一的SQL命令中完成任務(wù),何必要讓數(shù)據(jù)在網(wǎng)上流來流去的?我建議用戶認(rèn)真學(xué)習(xí)如何最大限度地發(fā)揮SQL的功能。
          posted @ 2005-10-08 18:25 Michael 閱讀(209) | 評論 (0)編輯 收藏

          2005年10月6日 #

          第一,談?wù)刦inal, finally, finalize的區(qū)別。

              第二,Anonymous Inner Class (匿名內(nèi)部類) 是否可以extends(繼承)其它類,是否可以implements(實(shí)現(xiàn))interface(接口)?

              第三,Static Nested Class 和 Inner Class的不同,說得越多越好(面試題有的很籠統(tǒng))。

              第四,&和&&的區(qū)別。

              第五,HashMap和Hashtable的區(qū)別。

              第六,Collection 和 Collections的區(qū)別。

              第七,什么時(shí)候用assert.

              第八,GC是什么? 為什么要有GC?

              第九,String s = new String("xyz");創(chuàng)建了幾個(gè)String Object?

              第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

              第十一,short s1 = 1; s1 = s1 + 1;有什么錯(cuò)? short s1 = 1; s1 += 1;有什么錯(cuò)?

              第十二,sleep() 和 wait() 有什么區(qū)別?

              第十三,Java有沒有g(shù)oto?

              第十四,數(shù)組有沒有l(wèi)ength()這個(gè)方法? String有沒有l(wèi)ength()這個(gè)方法?

              第十五,Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類型?

              第十六,Set里的元素是不能重復(fù)的,那么用什么方法來區(qū)分重復(fù)與否呢? 是用==還是equals()? 它們有何區(qū)別?

              第十七,給我一個(gè)你最常見到的runtime exception.

              第十八,error和exception有什么區(qū)別?

              第十九,List, Set, Map是否繼承自Collection接口?

              第二十,abstract class和interface有什么區(qū)別?

              第二十一,abstract的method是否可同時(shí)是static,是否可同時(shí)是native,是否可同時(shí)是synchronized?

              第二十二,接口是否可繼承接口? 抽象類是否可實(shí)現(xiàn)(implements)接口? 抽象類是否可繼承實(shí)體類(concrete class)?

              第二十三,啟動(dòng)一個(gè)線程是用run()還是start()?

              第二十四,構(gòu)造器Constructor是否可被override?

              第二十五,是否可以繼承String類?

              第二十六,當(dāng)一個(gè)線程進(jìn)入一個(gè)對象的一個(gè)synchronized方法后,其它線程是否可進(jìn)入此對象的其它方法?

              第二十七,try {}里有一個(gè)return語句,那么緊跟在這個(gè)try后的finally {}里的code會(huì)不會(huì)被執(zhí)行,什么時(shí)候被執(zhí)行,在return前還是后?

              第二十八,編程題: 用最有效率的方法算出2乘以8等於幾?

              第二十九,兩個(gè)對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?

              第三十,當(dāng)一個(gè)對象被當(dāng)作參數(shù)傳遞到一個(gè)方法后,此方法可改變這個(gè)對象的屬性,并可返回變化后的結(jié)果,那么這里到底是值傳遞還是引用傳遞?

              第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

              第三十二,編程題: 寫一個(gè)Singleton出來。


          以下是答案

              第一,談?wù)刦inal, finally, finalize的區(qū)別。

              final?修飾符(關(guān)鍵字)如果一個(gè)類被聲明為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個(gè)類不能既被聲明為 abstract的,又被聲明為final的。將變量或方法聲明為final,可以保證它們在使用中不被改變。被聲明為final的變量必須在聲明時(shí)給定初值,而在以后的引用中只能讀取,不可修改。被聲明為final的方法也同樣只能使用,不能重載
          finally?再異常處理時(shí)提供 finally 塊來執(zhí)行任何清除操作。如果拋出一個(gè)異常,那么相匹配的 catch 子句就會(huì)執(zhí)行,然后控制就會(huì)進(jìn)入 finally 塊(如果有的話)。

              finalize?方法名。Java 技術(shù)允許使用 finalize() 方法在垃圾收集器將對象從內(nèi)存中清除出去之前做必要的清理工作。這個(gè)方法是由垃圾收集器在確定這個(gè)對象沒有被引用時(shí)對這個(gè)對象調(diào)用的。它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統(tǒng)資源或者執(zhí)行其他清理工作。finalize() 方法是在垃圾收集器刪除對象之前對這個(gè)對象調(diào)用的。

              第二,Anonymous Inner Class (匿名內(nèi)部類) 是否可以extends(繼承)其它類,是否可以implements(實(shí)現(xiàn))interface(接口)?

              匿名的內(nèi)部類是沒有名字的內(nèi)部類。不能extends(繼承) 其它類,但一個(gè)內(nèi)部類可以作為一個(gè)接口,由另一個(gè)內(nèi)部類實(shí)現(xiàn)。

              第三,Static Nested Class 和 Inner Class的不同,說得越多越好(面試題有的很籠統(tǒng))。

              Nested Class (一般是C++的說法),Inner Class (一般是JAVA的說法)。Java內(nèi)部類與C++嵌套類最大的不同就在于是否有指向外部的引用上。具體可見http: //www.frontfree.net/articles/services/view.asp?id=704&page=1

              注: 靜態(tài)內(nèi)部類(Inner Class)意味著1創(chuàng)建一個(gè)static內(nèi)部類的對象,不需要一個(gè)外部類對象,2不能從一個(gè)static內(nèi)部類的一個(gè)對象訪問一個(gè)外部類對象

              第四,&和&&的區(qū)別。

              &是位運(yùn)算符。&&是布爾邏輯運(yùn)算符。

              第五,HashMap和Hashtable的區(qū)別。

              都屬于Map接口的類,實(shí)現(xiàn)了將惟一鍵映射到特定的值上。

              HashMap 類沒有分類或者排序。它允許一個(gè) null 鍵和多個(gè) null 值。

              Hashtable 類似于 HashMap,但是不允許 null 鍵和 null 值。它也比 HashMap 慢,因?yàn)樗峭降摹?

              第六,Collection 和 Collections的區(qū)別。

              Collections是個(gè)java.util下的類,它包含有各種有關(guān)集合操作的靜態(tài)方法。

              Collection是個(gè)java.util下的接口,它是各種集合結(jié)構(gòu)的父接口。

          第七,什么時(shí)候用assert。 

            斷言是一個(gè)包含布爾表達(dá)式的語句,在執(zhí)行這個(gè)語句時(shí)假定該表達(dá)式為 true。如果表達(dá)式計(jì)算為 false,那么系統(tǒng)會(huì)報(bào)告一個(gè) AssertionError。它用于調(diào)試目的: 

          assert(a > 0); // throws an AssertionError if a <= 0 

            斷言可以有兩種形式: 

            assert Expression1 ; 
            assert Expression1 : Expression2 ; 

            Expression1 應(yīng)該總是產(chǎn)生一個(gè)布爾值。 
            Expression2 可以是得出一個(gè)值的任意表達(dá)式。這個(gè)值用于生成顯示更多調(diào)試信息的 String 消息。 
          斷言在默認(rèn)情況下是禁用的。要在編譯時(shí)啟用斷言,需要使用 source 1.4 標(biāo)記: 

            javac -source 1.4 Test.java 

            要在運(yùn)行時(shí)啟用斷言,可使用 -enableassertions 或者 -ea 標(biāo)記。 
            要在運(yùn)行時(shí)選擇禁用斷言,可使用 -da 或者 -disableassertions 標(biāo)記。 
            要系統(tǒng)類中啟用斷言,可使用 -esa 或者 -dsa 標(biāo)記。還可以在包的基礎(chǔ)上啟用或者禁用斷言。 

            可以在預(yù)計(jì)正常情況下不會(huì)到達(dá)的任何位置上放置斷言。斷言可以用于驗(yàn)證傳遞給私有方法的參數(shù)。不過,斷言不應(yīng)該用于驗(yàn)證傳遞給公有方法的參數(shù),因?yàn)椴还苁欠駟⒂昧藬嘌裕蟹椒ǘ急仨殭z查其參數(shù)。不過,既可以在公有方法中,也可以在非公有方法中利用斷言測試后置條件。另外,斷言不應(yīng)該以任何方式改變程序的狀態(tài)。 


            第八,GC是什么? 為什么要有GC? (基礎(chǔ))。 

            GC是垃圾收集器。Java 程序員不用擔(dān)心內(nèi)存管理,因?yàn)槔占鲿?huì)自動(dòng)進(jìn)行管理。要請求垃圾收集,可以調(diào)用下面的方法之一: 

            System.gc() 
            Runtime.getRuntime().gc() 

            第九,String s = new String("xyz");創(chuàng)建了幾個(gè)String Object? 

            兩個(gè)對象,一個(gè)是“xyx”,一個(gè)是指向“xyx”的引用對象s。 

            第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少? 

            Math.round(11.5)返回(long)12,Math.round(-11.5)返回(long)-11; 

            第十一,short s1 = 1; s1 = s1 + 1;有什么錯(cuò)? short s1 = 1; s1 += 1;有什么錯(cuò)? 

            short s1 = 1; s1 = s1 + 1;有錯(cuò),s1是short型,s1+1是int型,不能顯式轉(zhuǎn)化為short型??尚薷臑閟1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正確。 

            第十二,sleep() 和 wait() 有什么區(qū)別? 搞線程的最愛 

            sleep()方法是使線程停止一段時(shí)間的方法。在sleep 時(shí)間間隔期滿后,線程不一定立即恢復(fù)執(zhí)行。這是因?yàn)樵谀莻€(gè)時(shí)刻,其它線程可能正在運(yùn)行而且沒有被調(diào)度為放棄執(zhí)行,除非(a)“醒來”的線程具有更高的優(yōu)先級,(b)正在運(yùn)行的線程因?yàn)槠渌蚨枞?nbsp;

            wait()是線程交互時(shí),如果線程對一個(gè)同步對象x 發(fā)出一個(gè)wait()調(diào)用,該線程會(huì)暫停執(zhí)行,被調(diào)對象進(jìn)入等待狀態(tài),直到被喚醒或等待時(shí)間到。 

            第十三,Java有沒有g(shù)oto? 

            Goto?java中的保留字,現(xiàn)在沒有在java中使用。 

            第十四,數(shù)組有沒有l(wèi)ength()這個(gè)方法? String有沒有l(wèi)ength()這個(gè)方法? 

            數(shù)組沒有l(wèi)ength()這個(gè)方法,有l(wèi)ength的屬性。 
            String有有l(wèi)ength()這個(gè)方法。 

            第十五,Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類型? 

            方法的重寫Overriding和重載Overloading是Java多態(tài)性的不同表現(xiàn)。重寫Overriding是父類與子類之間多態(tài)性的一種表現(xiàn),重載Overloading是一個(gè)類中多態(tài)性的一種表現(xiàn)。如果在子類中定義某方法與其父類有相同的名稱和參數(shù),我們說該方法被重寫 (Overriding)。子類的對象使用這個(gè)方法時(shí),將調(diào)用子類中的定義,對它而言,父類中的定義如同被“屏蔽”了。如果在一個(gè)類中定義了多個(gè)同名的方法,它們或有不同的參數(shù)個(gè)數(shù)或有不同的參數(shù)類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型。 

            第十六,Set里的元素是不能重復(fù)的,那么用什么方法來區(qū)分重復(fù)與否呢? 是用==還是equals()? 它們有何區(qū)別? 

            Set里的元素是不能重復(fù)的,那么用iterator()方法來區(qū)分重復(fù)與否。equals()是判讀兩個(gè)Set是否相等。 

            equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,為的是當(dāng)兩個(gè)分離的對象的內(nèi)容和類型相配的話,返回真值。 

            第十七,給我一個(gè)你最常見到的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  

            第十八,error和exception有什么區(qū)別? 

            error 表示恢復(fù)不是不可能但很困難的情況下的一種嚴(yán)重問題。比如說內(nèi)存溢出。不可能指望程序能處理這樣的情況。

            exception 表示一種設(shè)計(jì)或?qū)崿F(xiàn)問題。也就是說,它表示如果程序運(yùn)行正常,從不會(huì)發(fā)生的情況。 


            第十九,List, Set, Map是否繼承自Collection接口? 

            List,Set是 

            Map不是 

            第二十,abstract class和interface有什么區(qū)別? 

            聲明方法的存在而不去實(shí)現(xiàn)它的類被叫做抽象類(abstract class),它用于要?jiǎng)?chuàng)建一個(gè)體現(xiàn)某些基本行為的類,并為該類聲明方法,但不能在該類中實(shí)現(xiàn)該類的情況。不能創(chuàng)建abstract 類的實(shí)例。然而可以創(chuàng)建一個(gè)變量,其類型是一個(gè)抽象類,并讓它指向具體子類的一個(gè)實(shí)例。不能有抽象構(gòu)造函數(shù)或抽象靜態(tài)方法。Abstract 類的子類為它們父類中的所有抽象方法提供實(shí)現(xiàn),否則它們也是抽象類為。取而代之,在子類中實(shí)現(xiàn)該方法。知道其行為的其它類可以在類中實(shí)現(xiàn)這些方法。 

            接口(interface)是抽象類的變體。在接口中,所有方法都是抽象的。多繼承性可通過實(shí)現(xiàn)這樣的接口而獲得。接口中的所有方法都是抽象的,沒有一個(gè)有程序體。接口只可以定義static final成員變量。接口的實(shí)現(xiàn)與子類相似,除了該實(shí)現(xiàn)類不能從接口定義中繼承行為。當(dāng)類實(shí)現(xiàn)特殊接口時(shí),它定義(即將程序體給予)所有這種接口的方法。然后,它可以在實(shí)現(xiàn)了該接口的類的任何對象上調(diào)用接口的方法。由于有抽象類,它允許使用接口名作為引用變量的類型。通常的動(dòng)態(tài)聯(lián)編將生效。引用可以轉(zhuǎn)換到接口類型或從接口類型轉(zhuǎn)換,instanceof 運(yùn)算符可以用來決定某對象的類是否實(shí)現(xiàn)了接口。 

            第二十一,abstract的method是否可同時(shí)是static,是否可同時(shí)是native,是否可同時(shí)是synchronized? 

            都不能 

            第二十二,接口是否可繼承接口? 抽象類是否可實(shí)現(xiàn)(implements)接口? 抽象類是否可繼承實(shí)體類(concrete class)? 

            接口可以繼承接口。抽象類可以實(shí)現(xiàn)(implements)接口,抽象類是否可繼承實(shí)體類,但前提是實(shí)體類必須有明確的構(gòu)造函數(shù)。 

            第二十三,啟動(dòng)一個(gè)線程是用run()還是start()? 

            啟動(dòng)一個(gè)線程是調(diào)用start()方法,使線程所代表的虛擬處理機(jī)處于可運(yùn)行狀態(tài),這意味著它可以由JVM調(diào)度并執(zhí)行。這并不意味著線程就會(huì)立即運(yùn)行。run()方法可以產(chǎn)生必須退出的標(biāo)志來停止一個(gè)線程。 

           

            第二十四,構(gòu)造器Constructor是否可被override? 

            構(gòu)造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading。 

            第二十五,是否可以繼承String類? 

            String類是final類故不可以繼承。 

            第二十六,當(dāng)一個(gè)線程進(jìn)入一個(gè)對象的一個(gè)synchronized方法后,其它線程是否可進(jìn)入此對象的其它方法? 

            不能,一個(gè)對象的一個(gè)synchronized方法只能由一個(gè)線程訪問。 

            第二十七,try {}里有一個(gè)return語句,那么緊跟在這個(gè)try后的finally {}里的code會(huì)不會(huì)被執(zhí)行,什么時(shí)候被執(zhí)行,在return前還是后? 

            會(huì)執(zhí)行,在return前執(zhí)行。 

            第二十八,編程題: 用最有效率的方法算出2乘以8等於幾? 

            有C背景的程序員特別喜歡問這種問題。 

            2 << 3 

            第二十九,兩個(gè)對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對? 

            不對,有相同的hash code。 

            第三十,當(dāng)一個(gè)對象被當(dāng)作參數(shù)傳遞到一個(gè)方法后,此方法可改變這個(gè)對象的屬性,并可返回變化后的結(jié)果,那么這里到底是值傳遞還是引用傳遞? 

            是值傳遞。Java 編程語言只由值傳遞參數(shù)。當(dāng)一個(gè)對象實(shí)例作為一個(gè)參數(shù)被傳遞到方法中時(shí),參數(shù)的值就是對該對象的引用。對象的內(nèi)容可以在被調(diào)用的方法中改變,但對象的引用是永遠(yuǎn)不會(huì)改變的。 


            第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上? 

            switch(expr1)中,expr1是一個(gè)整數(shù)表達(dá)式。因此傳遞給 switch 和 case 語句的參數(shù)應(yīng)該是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。 

            第三十二,編程題: 寫一個(gè)Singleton出來。

            Singleton模式主要作用是保證在Java應(yīng)用程序中,一個(gè)類Class只有一個(gè)實(shí)例存在。 

            一般Singleton模式通常有幾種種形式: 

            第一種形式: 定義一個(gè)類,它的構(gòu)造函數(shù)為private的,它有一個(gè)static的private的該類變量,在類初始化時(shí)實(shí)例話,通過一個(gè)public的getInstance方法獲取對它的引用,繼而調(diào)用其中的方法。 

          public class Singleton { 
            private Singleton(){} 
            //在自己內(nèi)部定義自己一個(gè)實(shí)例,是不是很奇怪? 
            //注意這是private 只供內(nèi)部調(diào)用 
            private static Singleton instance = new Singleton(); 
            //這里提供了一個(gè)供外部訪問本class的靜態(tài)方法,可以直接訪問   
            public static Singleton getInstance() { 
              return instance;    
             } 

            第二種形式: 

          public class Singleton { 
            private static Singleton instance = null; 
            public static synchronized Singleton getInstance() { 
            //這個(gè)方法比上面有所改進(jìn),不用每次都進(jìn)行生成對象,只是第一次      
            //使用時(shí)生成實(shí)例,提高了效率! 
            if (instance==null) 
              instance=new Singleton(); 
          return instance;   } 

            其他形式: 

            定義一個(gè)類,它的構(gòu)造函數(shù)為private的,所有方法為static的。 

            一般認(rèn)為第一種形式要更加安全些 

            第三十三 Hashtable和HashMap 

            Hashtable繼承自Dictionary類,而HashMap是Java1.2引進(jìn)的Map interface的一個(gè)實(shí)現(xiàn) 

            HashMap允許將null作為一個(gè)entry的key或者value,而Hashtable不允許 

            還有就是,HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因?yàn)閏ontains方法容易讓人引起誤解。 

            最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個(gè)線程訪問Hashtable時(shí),不需要自己為它的方法實(shí)現(xiàn)同步,而HashMap就必須為之提供外同步。 

            Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會(huì)有很大的差異。 

          版權(quán)聲明  本篇文章對您是否有幫助?  投票: 是    否     投票結(jié)果:     24       0
           
           
           
          作者其它文章:
          Java多線程程序設(shè)計(jì)
          前車之覆,后車之鑒 --開源項(xiàng)目經(jīng)驗(yàn)談
          Resin服務(wù)器的使用
          用Java的加密機(jī)制來保護(hù)你的數(shù)據(jù)
          使用XML封裝數(shù)據(jù)庫操作語句的實(shí)現(xiàn)
          作者全部文章     查看作者的Blog 
           
           
            評論人:onefox    參與分: 40162    專家分: 965  發(fā)表時(shí)間: 2005-03-21 21:21 
          很有自信的能回答的,大概就 30%題目。

          其他很多涉及的問題平時(shí)都用自己的一套過濾掉了。

          沒有仔細(xì)研究過 
           
            評論人:javasleepless    參與分: 312    專家分: 10  發(fā)表時(shí)間: 2005-03-25 19:27 
          8錯(cuò),可以借此機(jī)會(huì)弄清那些混淆的概念 
           
            評論人:andersonmao    參與分: 94    專家分: 0  發(fā)表時(shí)間: 2005-05-12 10:51 
          關(guān)于26,沒有說詳細(xì)。
          =============================================
            第二十六,當(dāng)一個(gè)線程進(jìn)入一個(gè)對象的一個(gè)synchronized方法后,其它線程是否可進(jìn)入此對象的其它方法? 
            不能,一個(gè)對象的一個(gè)synchronized方法只能由一個(gè)線程訪問。 
          =============================================關(guān)于26,沒有說詳細(xì)。
          =============================================
              第二十六,當(dāng)一個(gè)線程進(jìn)入一個(gè)對象的一個(gè)synchronized方法后,其它線程是否可進(jìn)入此對象的其它方法? 
              不能,一個(gè)對象的一個(gè)synchronized方法只能由一個(gè)線程訪問。 
          =============================================
              一個(gè)對象的所有synchronized方法在同一個(gè)時(shí)間只能由一個(gè)線程訪問。這個(gè)對象的其它不是synchronized方法不受這個(gè)限制。就是說

          當(dāng)一個(gè)線程正在執(zhí)行這個(gè)對象的一個(gè)synchronized時(shí)。這個(gè)對象的所有synchronized方法都不能被其它線程訪問,但是這個(gè)對象的不是

          synchronized的方法可以被其它線程訪問。
              例子:
          SynObject.java
          ====
          public class SynObject{   
              public synchronized void SynMethod(int index){
                  System.out.println("Thread Index="+index+" In SynMethod - Begin");
                  try{
                      Thread.sleep(100);
                  }catch(Exception e){
                  }
                  System.out.println("Thread Index="+index+" In SynMethod - End");
              }
              public void NoneSynMethod(int index){
                  System.out.println("Thread Index="+index+" In NoneSynMethod");
              }
          }
          ====
          ThreadTest.java
          ====
          public class ThreadTest extends Thread{
              int threadNo;
              static SynObject obj=new SynObject();
              public void run(){
                  System.out.println("Thread No="+threadNo+" Begin run");
                  for(int i=0;i<3;i++){
                      obj.SynMethod(threadNo);
                      obj.NoneSynMethod(threadNo);
                  }
              }
              public ThreadTest(int No){
                  threadNo=No;
              }
              public static void main(String[] a){
                  Thread th1=new ThreadTest(1);
                  Thread th2=new ThreadTest(2);
                  th1.start();
                  th2.start();
              }   
          }
          ====
          運(yùn)行 java ThreadTest
          可能的結(jié)果為(因?yàn)榫€程相關(guān),結(jié)果可能不一樣):
          Thread No=1 Begin run
          Thread Index=1 In SynMethod - Begin
          Thread No=2 Begin run
          Thread Index=1 In SynMethod - End
          Thread Index=2 In SynMethod - Begin
          Thread Index=1 In NoneSynMethod            //在Thread 2 執(zhí)行SynMethod() 過程中,Thread 1 執(zhí)行了 NoneSynMethod()
          Thread Index=2 In SynMethod - End
          Thread Index=2 In NoneSynMethod
          Thread Index=1 In SynMethod - Begin
          Thread Index=1 In SynMethod - End
          Thread Index=2 In SynMethod - Begin
          Thread Index=1 In NoneSynMethod
          Thread Index=2 In SynMethod - End
          Thread Index=1 In SynMethod - Begin
          Thread Index=2 In NoneSynMethod
          Thread Index=1 In SynMethod - End
          Thread Index=1 In NoneSynMethod
          Thread Index=2 In SynMethod - Begin
          Thread Index=2 In SynMethod - End
          Thread Index=2 In NoneSynMethod


          1. 使類盡可能短小精悍,而且只解決一個(gè)特定的問題。下面是對類設(shè)計(jì)的一些建議:

            一個(gè)復(fù)雜的開關(guān)語句:考慮采用"多形"機(jī)制;
            數(shù)量眾多的方法涉及到類型差別極大的操作:考慮用幾個(gè)類來分別實(shí)現(xiàn);
            許多成員變量在特征上有很大的差別:考慮使用幾個(gè)類.


          2. 在多線程環(huán)境中,隱私是特別重要的一個(gè)因素--只有private字段才能在非同步使用的情況下受到保護(hù)。

          3. 任何時(shí)候只要發(fā)現(xiàn)類與類之間結(jié)合得非常緊密,就需要考慮是否采用內(nèi)部類,從而改善編碼及維護(hù)工作(參見第14章14.1.2小節(jié)的"用內(nèi)部類改進(jìn)代碼")。
           
           
           


            

          posted @ 2005-10-06 12:05 Michael 閱讀(266) | 評論 (0)編輯 收藏

          Hibernate 提供了比較好的分頁查詢api極大地方便了使用者。以下是我在項(xiàng)目中寫的一個(gè)Hibernate 分頁查詢的代碼:
          //根據(jù)Message 對象所封裝的查詢條件分頁查詢Message對象,S
          public List getPageinMessage(Message message,int startRow,int rows) throws DAOException {       
                  StringBuffer queryString=new StringBuffer(" from Message as message where ");
                  //ActionExceptionHandler actionHandler=new ActionExceptionHandler();
                  if(message.getSource()!=null){
                      queryString.append("message.source.id="+message.getSource().getId());
                      queryString.append(" and senderDelFlag=0");
                  }else if(message.getTarget()!=null){
                      //if message's target is not null query message base on target's id
                      logger.debug("query inbox==================");
                      queryString.append("message.target.id="+message.getTarget().getId());
                      queryString.append(" and receiverDelFlag=0");
                  } else{
                      throw new BusinessException("未選定消息發(fā)送者或接受者"); 
                  }
                  queryString.append(" order by message.creatDate DESC");
                  Query query=null;
                  List messageList=null;
                  Session session=this.getSession();       
                  try {
                      query=session.createQuery(queryString.toString());
                      query.setFirstResult(startRow);
                      query.setMaxResults(rows);
                      logger.debug("first row===="+startRow+"===row amount==="+rows);
                      messageList=query.list();
                      if(messageList.size()>0){
                          Message message2=(Message)messageList.get(0);              
                          logger.debug("messageList's length==="+message2);           
                          logger.debug("messageList's length==="+messageList.size());
                      }
                  } catch (HibernateException e) {
                      // TODO Auto-generated catch block          
                      e.printStackTrace();
                      throw new BusinessException("讀取頁面數(shù)據(jù)發(fā)生錯(cuò)誤"); 
                  }finally{
                      if(session!=null&&session.isOpen()){
                          try {
                              session.close();
                          } catch (HibernateException e1) {
                              e1.printStackTrace();
                              throw new BusinessException("會(huì)話關(guān)閉異常");                   
                          }
                      }
                  }          
                  return messageList;       
              }
          posted @ 2005-10-06 11:05 Michael 閱讀(244) | 評論 (0)編輯 收藏

          2005年10月5日 #

          Java Servlet及其特點(diǎn)

            Servlet是Java技術(shù)對CGI編程的回答。Servlet程序在服務(wù)器端運(yùn)行,動(dòng)態(tài)地生成Web頁面。與傳統(tǒng)的CGI和許多其他類似CGI的技術(shù)相比,Java Servlet具有更高的效率,更容易使用,功能更強(qiáng)大,具有更好的可移植性,更節(jié)省投資。

                高效

            在傳統(tǒng)的CGI中,每個(gè)請求都要啟動(dòng)一個(gè)新的進(jìn)程,如果CGI程序本身的執(zhí)行時(shí)間較短,啟動(dòng)進(jìn)程所需要的開銷很可能反而超過實(shí)際執(zhí)行時(shí)間。而在Servlet中,每個(gè)請求由一個(gè)輕量級的Java線程處理(而不是重量級的操作系統(tǒng)進(jìn)程)。

            在傳統(tǒng)CGI中,如果有N個(gè)并發(fā)的對同一CGI程序的請求,則該CGI程序的代碼在內(nèi)存中重復(fù)裝載了N次;而對于Servlet,處理請求的是N個(gè)線程,只需要一份Servlet類代碼。在性能優(yōu)化方面,Servlet也比CGI有著更多的選擇,比如緩沖以前的計(jì)算結(jié)果,保持?jǐn)?shù)據(jù)庫連接的活動(dòng),等等。

             其實(shí)CGI是Common Gateway Interface(公共網(wǎng)關(guān)接口)

            方便

            Servlet提供了大量的實(shí)用工具例程,例如自動(dòng)地解析和解碼HTML表單數(shù)據(jù)、讀取和設(shè)置HTTP頭、處理Cookie、跟蹤會(huì)話狀態(tài)等。

            功能強(qiáng)大

            在Servlet中,許多使用傳統(tǒng)CGI程序很難完成的任務(wù)都可以輕松地完成。例如,Servlet能夠直接和Web服務(wù)器交互,而普通的CGI程序不能。Servlet還能夠在各個(gè)程序之間共享數(shù)據(jù),使得數(shù)據(jù)庫連接池之類的功能很容易實(shí)現(xiàn)。

            可移植性好

            Servlet用Java編寫,Servlet API具有完善的標(biāo)準(zhǔn)。因此,為I-Planet Enterprise Server寫的Servlet無需任何實(shí)質(zhì)上的改動(dòng)即可移植到Apache、Microsoft IIS或者WebStar。幾乎所有的主流服務(wù)器都直接或通過插件支持Servlet。

            節(jié)省投資

            不僅有許多廉價(jià)甚至免費(fèi)的Web服務(wù)器可供個(gè)人或小規(guī)模網(wǎng)站使用,而且對于現(xiàn)有的服務(wù)器,如果它不支持Servlet的話,要加上這部分功能也往往是免費(fèi)的(或只需要極少的投資)。

           


           JSP及其特點(diǎn)

            JavaServer Pages(JSP)是一種實(shí)現(xiàn)普通靜態(tài)HTML和動(dòng)態(tài)HTML混合編碼的技術(shù)

          許多由CGI程序生成的頁面大部分仍舊是靜態(tài)HTML,動(dòng)態(tài)內(nèi)容只在頁面中有限的幾個(gè)部分出現(xiàn)。但是包括Servlet在內(nèi)的大多數(shù)CGI技術(shù)及其變種,總是通過程序生成整個(gè)頁面。JSP使得我們可以分別創(chuàng)建這兩個(gè)部分。例如,下面就是一個(gè)簡單的JSP頁面:

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
          <HTML>
          <HEAD><TITLE>歡迎訪問網(wǎng)上商店</TITLE></HEAD>
          <BODY>
          <H1>歡迎</H1>
          <SMALL>歡迎,
          <!-- 首次訪問的用戶名字為"New User" -->
          <% out.println(Utils.getUserNameFromCookie(request)); %>
          要設(shè)置帳號(hào)信息,請點(diǎn)擊
          <A HREF="Account-Settings.html">這里</A></SMALL>
          <P>
          頁面的其余內(nèi)容。.
          </BODY></HTML>

            下面是JSP和其他類似或相關(guān)技術(shù)的一個(gè)簡單比較:

            JSP和Active Server Pages(ASP)相比

            Microsoft的ASP是一種和JSP類似的技術(shù)。JSP和ASP相比具有兩方面的優(yōu)點(diǎn)。首先,動(dòng)態(tài)部分用Java編寫,而不是VB Script或其他Microsoft語言,不僅功能更強(qiáng)大而且更易于使用。第二,JSP應(yīng)用可以移植到其他操作系統(tǒng)和非Microsoft的Web服務(wù)器上。

            JSP和純Servlet相比

            JSP并沒有增加任何本質(zhì)上不能用Servlet實(shí)現(xiàn)的功能。但是,在JSP中編寫靜態(tài)HTML更加方便,不必再用 println語句來輸出每一行HTML代碼。更重要的是,借助內(nèi)容和外觀的分離,頁面制作中不同性質(zhì)的任務(wù)可以方便地分開:比如,由頁面設(shè)計(jì)專家進(jìn)行HTML設(shè)計(jì),同時(shí)留出供Servlet程序員插入動(dòng)態(tài)內(nèi)容的空間。

            JSP和服務(wù)器端包含(Server-Side Include,SSI)相比

            SSI是一種受到廣泛支持的在靜態(tài)HTML中引入外部代碼的技術(shù)。JSP在這方面的支持更為完善,因?yàn)樗梢杂肧ervlet而不是獨(dú)立的程序來生成動(dòng)態(tài)內(nèi)容。另外,SSI實(shí)際上只用于簡單的包含,而不是面向那些能夠處理表單數(shù)據(jù)、訪問數(shù)據(jù)庫的“真正的”程序。

            JSP和JavaScript相比

            JavaScript能夠在客戶端動(dòng)態(tài)地生成HTML。雖然JavaScript很有用,但它只能處理以客戶端環(huán)境為基礎(chǔ)的動(dòng)態(tài)信息。除了Cookie之外,HTTP狀態(tài)和表單提交數(shù)據(jù)對JavaScript來說都是不可用的。另外,由于是在客戶端運(yùn)行,JavaScript不能訪問服務(wù)器端資源,比如數(shù)據(jù)庫、目錄信息等等

          posted @ 2005-10-05 20:06 Michael 閱讀(647) | 評論 (0)編輯 收藏

          1 javascript ,設(shè)置一個(gè)變量,只允許提交一次。 

            <script language="javascript">

             var checkSubmitFlg = false;

             function checkSubmit() {

             if (checkSubmitFlg == true) {

             return false;

             }

             checkSubmitFlg = true;

             return true;

             }

             document.ondblclick = function docondblclick() {

             window.event.returnValue = false;

             }

             document.onclick = function doconclick() {

             if (checkSubmitFlg) {

             window.event.returnValue = false;

             }

             }

            </script>
          <html:form action="myAction.do" method="post" onsubmit="return checkSubmit();">
            

            2 還是javascript,將提交按鈕或者image置為disable  

             <html:form action="myAction.do" method="post"

             onsubmit="getElById('submitInput').disabled = true; return true;">   

             <html:image styleId="submitInput" src="images/ok_b.gif" border="0" /> 

             </html:form>  

            3 利用struts的同步令牌機(jī)制  

            利用同步令牌(Token)機(jī)制來解決Web應(yīng)用中重復(fù)提交的問題,Struts也給出了一個(gè)參考實(shí)現(xiàn)。

            基本原理: 

            服務(wù)器端在處理到達(dá)的請求之前,會(huì)將請求中包含的令牌值與保存在當(dāng)前用戶會(huì)話中的令牌值進(jìn)行比較,看是否匹配。在處理完該請求后,且在答復(fù)發(fā)送給客戶端之前,將會(huì)產(chǎn)生一個(gè)新的令牌,該令牌除傳給客戶端以外,也會(huì)將用戶會(huì)話中保存的舊的令牌進(jìn)行替換。這樣如果用戶回退到剛才的提交頁面并再次提交的話,客戶端傳過來的令牌就和服務(wù)器端的令牌不一致,從而有效地防止了重復(fù)提交的發(fā)生?!?

            if (isTokenValid(request, true)) {

             // your code here

             return mapping.findForward("success");

            } else {

             saveToken(request);

             return mapping.findForward("submitagain");

            } 

            Struts根據(jù)用戶會(huì)話ID和當(dāng)前系統(tǒng)時(shí)間來生成一個(gè)唯一(對于每個(gè)會(huì)話)令牌的,具體實(shí)現(xiàn)可以參考TokenProcessor類中的generateToken()方法。  

            1. //驗(yàn)證事務(wù)控制令牌,<html:form >會(huì)自動(dòng)根據(jù)session中標(biāo)識(shí)生成一個(gè)隱含input代表令牌,防止兩次提交

            2. 在action中:  

             //<input type="hidden" name="org.apache.struts.taglib.html.TOKEN"

             // value="6aa35341f25184fd996c4c918255c3ae">

             if (!isTokenValid(request)) errors.add(ActionErrors.GLOBAL_ERROR,

             new ActionError("error.transaction.token"));

             resetToken(request); //刪除session中的令牌  

            3. action有這樣的一個(gè)方法生成令牌  

             protected String generateToken(HttpServletRequest request) {  

             HttpSession session = request.getSession();

             try {

             byte id[] = session.getId().getBytes();

             byte now[] =

             new Long(System.currentTimeMillis()).toString().getBytes();

             MessageDigest md = MessageDigest.getInstance("MD5");

             md.update(id);

             md.update(now);

             return (toHex(md.digest()));

             } catch (IllegalStateException e) {

             return (null);

             } catch (NoSuchAlgorithmException e) {

             return (null);

             }

             }

          posted @ 2005-10-05 20:04 Michael 閱讀(235) | 評論 (0)編輯 收藏

          僅列出標(biāo)題  
          主站蜘蛛池模板: 两当县| 永吉县| 华坪县| 嘉善县| 凤台县| 吴桥县| 延寿县| 突泉县| 竹溪县| 建水县| 长垣县| 金塔县| 彩票| 垣曲县| 新兴县| 黔江区| 中宁县| 玉屏| 高碑店市| 丹东市| 香河县| 介休市| 巴楚县| 娄底市| 临海市| 焉耆| 舟山市| 鲜城| 贺兰县| 唐河县| 金山区| 阿合奇县| 徐闻县| 略阳县| 池州市| 柘城县| 前郭尔| 林西县| 桐柏县| 五华县| 连平县|