婷婷中文字幕一区三区,日韩三级中文字幕,九九热播视频在线精品6http://www.aygfsteel.com/isoft/感悟人生,領(lǐng)悟世界,創(chuàng)造生活,創(chuàng)新社會(huì)zh-cnWed, 18 Jun 2025 11:32:32 GMTWed, 18 Jun 2025 11:32:32 GMT60J2EE架構(gòu)的最佳實(shí)踐http://www.aygfsteel.com/isoft/archive/2008/01/03/172475.html夢(mèng)幻流星夢(mèng)幻流星Thu, 03 Jan 2008 06:25:00 GMThttp://www.aygfsteel.com/isoft/archive/2008/01/03/172475.htmlhttp://www.aygfsteel.com/isoft/comments/172475.htmlhttp://www.aygfsteel.com/isoft/archive/2008/01/03/172475.html#Feedback0http://www.aygfsteel.com/isoft/comments/commentRss/172475.htmlhttp://www.aygfsteel.com/isoft/services/trackbacks/172475.html   首先,本文的目標(biāo)讀者是正在從事技術(shù)工作的架構(gòu)師。為了避免浪費(fèi)大家的才智,我會(huì)避免講述一些陳腐的最佳實(shí)踐,例如“日常構(gòu)建(build daily)”、“測(cè)試一切(test everything)”和“經(jīng)常集成( integrate often)。 任何具有稱職架構(gòu)師的項(xiàng)目都有分工明確的、定義良好的團(tuán)隊(duì)結(jié)構(gòu)。他們還為進(jìn)行編碼檢查、構(gòu)建代碼(每日或在需要時(shí))、進(jìn)行測(cè)試(單元、集成和系統(tǒng)的)、部署和配置/釋放管理而具備已記錄的過(guò)程。
  其次,我將跳過(guò)通常吹捧的最佳實(shí)踐,例如“基于接口的設(shè)計(jì)”、“使用著名的設(shè)計(jì)模型”以及“使用面向服務(wù)的架構(gòu)”等。相反,我將集中講述我曾學(xué)過(guò)并且使用了若干年的6(不是很多)個(gè)方面的in-the-trench課程。最后,本文的目的是讓您思考一下自己的架構(gòu),提供工作代碼示例或者解決方案超出了本文的范圍。下面就讓我介紹一下這6課:
1、切勿繞過(guò)服務(wù)器端驗(yàn)證
2、安全并非是附加物
3、國(guó)際化(I18N)不再是紙上談兵
4、在MVC表示中避免共同的錯(cuò)誤
5、不要被POJO束縛住手腳
6、數(shù)據(jù)訪問(wèn)并不能托管O/R映射


第1課:切勿繞過(guò)服務(wù)器端驗(yàn)證
  作為一位軟件顧問(wèn),我曾有機(jī)會(huì)不但設(shè)計(jì)并實(shí)現(xiàn)了Web應(yīng)用程序,而且還評(píng)估/審核了許多Web應(yīng)用程序。在復(fù)雜的、并且用JavaScript客戶端封裝的應(yīng)用程序內(nèi),我經(jīng)常遇到對(duì)用戶輸入信息執(zhí)行大量檢查的Web頁(yè)面。即使HTML元素具有數(shù)據(jù)有效性的屬性也如此,例如MAXLENGTH。只有在成功驗(yàn)證所有輸入信息后,才能提交HTML表單。結(jié)果,一旦服務(wù)器端收到通知表單(請(qǐng)求),便恰當(dāng)?shù)貓?zhí)行業(yè)務(wù)邏輯。
  在此,您發(fā)現(xiàn)問(wèn)題了么?開(kāi)發(fā)人員已經(jīng)做了許多重要的假設(shè)。例如,他們假設(shè)所有的Web應(yīng)用程序用戶都同樣誠(chéng)實(shí)。開(kāi)發(fā)人員還假設(shè)所有用戶將總是使用他們測(cè)試過(guò)的瀏覽器訪問(wèn)Web應(yīng)用程序。還有很多其他的假設(shè)。這些開(kāi)發(fā)人員忘記了利用可以免費(fèi)得到的工具,通過(guò)命令行很容易地模擬類似瀏覽器的行為。事實(shí)上,通過(guò)在瀏覽器窗口中鍵入適當(dāng)?shù)腢RL,您可以發(fā)送任何“posted”表單,盡管如此,通過(guò)禁用這些頁(yè)面的GET請(qǐng)求,您很容易地阻止這樣的“表單發(fā)送”。但是,您不能阻止人們模擬甚至創(chuàng)建他們自己的瀏覽器來(lái)入侵您的系統(tǒng)。
根本的問(wèn)題在于開(kāi)發(fā)人員不能確定客戶端驗(yàn)證與服務(wù)器端驗(yàn)證的主要差別。兩者的主要差別不在于驗(yàn)證究竟發(fā)生在哪里,例如在客戶端或者在服務(wù)器端。主要的差別在于驗(yàn)證背后的目的不同。
  客戶端驗(yàn)證僅僅是方便。執(zhí)行它可為用戶提供快速反饋??使應(yīng)用程序似乎做出響應(yīng),給人一種運(yùn)行桌面應(yīng)用程序的錯(cuò)覺(jué)。
  另一方面,服務(wù)器端驗(yàn)證是構(gòu)建安全Web應(yīng)用程序必需的。不管在客戶端一側(cè)輸入的是什么,它可以確保客戶端送往服務(wù)器的所有數(shù)據(jù)都是有效的。
  因而,只有服務(wù)器端驗(yàn)證才可以提供真正應(yīng)用程序級(jí)的安全。許多開(kāi)發(fā)人員陷入了錯(cuò)誤感覺(jué)的圈套:只有在客戶端進(jìn)行所有數(shù)據(jù)的驗(yàn)證才能確保安全。下面是說(shuō)明此觀點(diǎn)的一個(gè)常見(jiàn)的示例:
  一個(gè)典型的登錄頁(yè)面擁有一個(gè)用來(lái)輸入用戶名的文本框和一個(gè)輸入密碼的文本框。在服務(wù)器端,某人在接收servlet中可能遇到一些代碼,這些代碼構(gòu)成了下面形式的SQL查詢:
"SELECT * FROM SecurityTable WHERE username = @#" + form.getParameter("username") + "@# AND password = @#" + form.getParameter("password") + "@#;",并執(zhí)行這些代碼。如果查詢?cè)诮Y(jié)果集的某一行返回,則用戶登錄成功,否則用戶登錄失敗。
  第一個(gè)問(wèn)題是構(gòu)造SQL的方式,但現(xiàn)在讓我們暫時(shí)忽略它。如果用戶在用戶名中輸入“Alice@#--”會(huì)怎樣呢?假設(shè)名為“Alice”的用戶已經(jīng)在SecurityTable中,這時(shí)此用戶(更恰當(dāng)?shù)恼f(shuō)法是黑客)成功地登錄。我將把找出為什么會(huì)出現(xiàn)這種情況的原因做為留給您的一道習(xí)題。
  許多創(chuàng)造性的客戶端驗(yàn)證可以阻止一般的用戶從瀏覽器中這樣登錄。但對(duì)于已經(jīng)禁用了JavaScript的客戶端,或者那些能夠使用其他類似瀏覽器程序直接發(fā)送命令(HTTP POST和GET命令)的高級(jí)用戶(或者說(shuō)黑客)來(lái)說(shuō),我們又有什么辦法呢?服務(wù)器端驗(yàn)證是防止這種漏洞類型所必須的。這時(shí),SSL、防火墻等都派不上用場(chǎng)了。

第2課:安全并非是附加物
  如第1課所述,我曾有幸研究過(guò)許多Web應(yīng)用程序。我發(fā)現(xiàn)所有的JavaServer Page(JSP)都有一個(gè)共同的主題,那就是具有類似下面?zhèn)未a的布局:

<%
User user =
session.getAttribute("User");
if(user == null)
{
// redirect to
// the logon page…
}
if(!user.role.equals("manager"))
{
// redirect to the
// "unauthorized" page…
}
%>

<!-
HTML, JavaScript, and JSP
code to display data and
allow user interaction -->

  如果項(xiàng)目使用諸如Struts這樣的MVC框架,所有的Action Bean都會(huì)具有類似的代碼。盡管最后這些代碼可能運(yùn)行得很好,但如果您發(fā)現(xiàn)一個(gè)bug,或者您必須添加一個(gè)新的角色(例如,“guest”或者“admin”),這就會(huì)代表一場(chǎng)維護(hù)惡夢(mèng)。
  此外,所有的開(kāi)發(fā)人員,不管您多年輕,都需要熟悉這種編碼模式。當(dāng)然,您可以用一些JSP標(biāo)簽來(lái)整理JSP代碼,可以創(chuàng)建一個(gè)清除派生Action Bean的基本Action Bean。盡管如此,由于與安全相關(guān)的代碼會(huì)分布到多個(gè)地方,所以維護(hù)時(shí)的惡夢(mèng)仍舊存在。由于Web應(yīng)用程序的安全是強(qiáng)迫建立在應(yīng)用程序代碼的級(jí)別上(由多個(gè)開(kāi)發(fā)人員),而不是建立在架構(gòu)級(jí)別上,所以Web應(yīng)用程序還是很可能存在弱點(diǎn)。
  很可能,根本的問(wèn)題是在項(xiàng)目接近完成時(shí)才處理安全性問(wèn)題。最近作為一名架構(gòu)師,我曾在一年多的時(shí)間里親歷了某一要實(shí)現(xiàn)項(xiàng)目的6個(gè)版本,而直到第四版時(shí)我們才提到了安全性??即使該項(xiàng)目會(huì)將高度敏感的個(gè)人數(shù)據(jù)暴露于Web上,我們也沒(méi)有注意到安全性。為了更改發(fā)布計(jì)劃,我們卷入了與項(xiàng)目資助人及其管理人員的爭(zhēng)斗中,以便在第一版中包含所有與安全相關(guān)的功能,并將一些“業(yè)務(wù)”功能放在后續(xù)的版本中。最終,我們贏得了勝利。而且由于應(yīng)用程序的安全性相當(dāng)高,能夠保護(hù)客戶的私有數(shù)據(jù),這一點(diǎn)我們引以為榮,我們的客戶也非常高興。
  遺憾的是,在大多數(shù)應(yīng)用程序中,安全性看起來(lái)并未增加任何實(shí)際的商業(yè)價(jià)值,所以直到最后才解決。發(fā)生這種情況時(shí),人們才匆忙開(kāi)發(fā)與安全相關(guān)的代碼,而絲毫沒(méi)有考慮解決方案的長(zhǎng)期可維護(hù)性或者健壯性。忽視該安全性的另一個(gè)征兆是缺乏全面的服務(wù)器端驗(yàn)證,如我在第1課中所述,這一點(diǎn)是安全Web應(yīng)用程序的一個(gè)重要組成部分。
  記?。篔2EE Web應(yīng)用程序的安全性并非僅僅是在Web.xml 和ejb-jar.xml文件中使用合適的聲明,也不是使用J2EE技術(shù),如Java 認(rèn)證和授權(quán)服務(wù)(Java Authentication and Authorization Service,JAAS)。而是經(jīng)過(guò)深思熟慮后的設(shè)計(jì),且實(shí)現(xiàn)一個(gè)支持它的架構(gòu)。

第3課:國(guó)際化(I18N)不再是紙上談兵
  當(dāng)今世界的事實(shí)是許多英語(yǔ)非母語(yǔ)的人們將訪問(wèn)您的公共Web應(yīng)用程序。隨著電子政務(wù)的實(shí)行,由于它允許人們(某個(gè)國(guó)家的居民)在線與政府機(jī)構(gòu)交互,所以這一點(diǎn)特別真實(shí)。這樣的例子包括換發(fā)駕照或者車輛登記證。許多第一語(yǔ)言不是英語(yǔ)的人們很可能將訪問(wèn)這樣的應(yīng)用程序。國(guó)際化(即:“i18n”,因?yàn)樵?#8220;internationalization”這個(gè)單詞中,字母i和字母n之間一共有18個(gè)字母)使得您的應(yīng)用程序能夠支持多種語(yǔ)言。
  顯然,如果您的JSP 頁(yè)面中有硬編碼的文本,或者您的Java代碼返回硬編碼的錯(cuò)誤消息,那么您要花費(fèi)很多時(shí)間開(kāi)發(fā)此Web應(yīng)用程序的西班牙語(yǔ)版本。然而,在Web應(yīng)用程序中,為了支持多種語(yǔ)言,文本不是惟一必須“具體化”的部分。因?yàn)樵S多圖像中嵌有文字,所以圖形和圖像也應(yīng)該是可配置的。在極端的情況下,圖像(或者顏色)在不同的文化背景中可能有完全不同的意思。類似地,任何格式化數(shù)字和日期的Java代碼也必須本地化。但問(wèn)題是:您的頁(yè)面布局可能也需要更改。
  例如,如果您使用HTML表格來(lái)格式化和顯示菜單選項(xiàng)、應(yīng)用程序題頭或注腳,則您可能必須為每一種支持的語(yǔ)言更改每一欄的最小寬度和表格其他可能的方面。為了適應(yīng)不同的字體和顏色,您可能必須為每一種語(yǔ)言使用單獨(dú)的樣式表。
  顯然,現(xiàn)在創(chuàng)建一個(gè)國(guó)際化的Web應(yīng)用程序面臨的是架構(gòu)挑戰(zhàn)而不是應(yīng)用程序方面的挑戰(zhàn)。一個(gè)架構(gòu)良好的Web應(yīng)用程序意味著您的JSP頁(yè)面和所有與業(yè)務(wù)相關(guān)的(應(yīng)用程序特有的)Java代碼都不知不覺(jué)地選擇了本地化。要記住的教訓(xùn)是:不要因?yàn)镴ava、J2EE支持國(guó)際化而不考慮國(guó)際化。您必須從第一天起就記住設(shè)計(jì)具有國(guó)際化的解決方案。

第4課:在MVC表示中避免共同的錯(cuò)誤
  J2EE開(kāi)發(fā)已經(jīng)足夠成熟,在表示層,大多數(shù)項(xiàng)目使用MVC架構(gòu)的某些形式,例如Struts。在這樣的項(xiàng)目中,我常見(jiàn)到的現(xiàn)象是對(duì)MVC模式的誤用。下面是幾個(gè)示例。
  常見(jiàn)的誤用是在模型層(例如,在Struts的Action Bean中)實(shí)現(xiàn)了所有的業(yè)務(wù)邏輯。不要忘了,表示層的模型層仍然是表示層的一部分。使用該模型層的正確方法是調(diào)用適當(dāng)?shù)臉I(yè)務(wù)層服務(wù)(或?qū)ο螅┎⒔Y(jié)果發(fā)送到視圖層(view layer)。用設(shè)計(jì)模式術(shù)語(yǔ)來(lái)說(shuō),MVC表示層的模型應(yīng)該作為業(yè)務(wù)層的外觀(Fa?ade)來(lái)實(shí)現(xiàn)。更好的方法是,使用核心J2EE模式(Core J2EE Patterns)中論述到的Business Delegate模式。這段自書(shū)中摘錄的內(nèi)容精彩地概述了將您的模型作為Business Delegate來(lái)實(shí)現(xiàn)的要點(diǎn)和優(yōu)點(diǎn):
  Business Delegate起到客戶端業(yè)務(wù)抽象化的作用。它抽象化,進(jìn)而隱藏業(yè)務(wù)服務(wù)的實(shí)現(xiàn)。使用Business Delegate,可以降低表示層客戶端和系統(tǒng)的業(yè)務(wù)服務(wù).之間的耦合程度。根據(jù)實(shí)現(xiàn)策略不同,Business Delegate可以在業(yè)務(wù)服務(wù)API的實(shí)現(xiàn)中,保護(hù)客戶端不受可能的變動(dòng)性影響。這樣,在業(yè)務(wù)服務(wù)API或其底層實(shí)現(xiàn)變化時(shí),可以潛在地減少必須修改表示層客戶端代碼的次數(shù)。
  另一個(gè)常見(jiàn)的錯(cuò)誤是在模型層中放置許多表示類型的邏輯。例如,如果JSP頁(yè)面需要以指定方式格式化的日期或者以指定方式排序的數(shù)據(jù),某些人可能將該邏輯放置在模型層,對(duì)該邏輯來(lái)說(shuō),這是錯(cuò)誤的地方。實(shí)際上,它應(yīng)該在JSP頁(yè)面使用的一組helper類中。當(dāng)業(yè)務(wù)層返回?cái)?shù)據(jù)時(shí),Action Bean應(yīng)該將數(shù)據(jù)轉(zhuǎn)發(fā)給視圖層。這樣,無(wú)需創(chuàng)建模型和視圖之間多余的耦合,就能夠靈活支持多個(gè)視圖層(JSP、Velocity、XML等)。也使視圖能夠確定向用戶顯示數(shù)據(jù)的最佳方式。
  最后,我見(jiàn)過(guò)的大多數(shù)MVC應(yīng)用程序都有未充分應(yīng)用的控制器。例如,絕大多數(shù)的Struts應(yīng)用程序?qū)?chuàng)建一個(gè)基本的Action類,并完成所有與安全相關(guān)的功能。其他所有的Action Bean都是此基類的派生類。這種功能應(yīng)該是控制器的一部分,因?yàn)槿绻麤](méi)有滿足安全條件,則首先調(diào)用不應(yīng)該到達(dá)Action Bean(即:模型)。記住,一個(gè)設(shè)計(jì)良好的MVC架構(gòu)的最強(qiáng)大功能之一是存在一個(gè)健壯的、可擴(kuò)展的控制器。您應(yīng)該利用該能力以加強(qiáng)自己的優(yōu)勢(shì)。

第5課:不要被POJO束縛住手腳
  我曾目睹許多項(xiàng)目為了使用Enterprise JavaBean而使用Enterprise JavaBean。因?yàn)镋JB似乎給項(xiàng)目帶來(lái)優(yōu)越感和妄自尊大的表現(xiàn),所以有時(shí)它是顯酷的要素(coolness factor)。而其他時(shí)候,它會(huì)使J2EE和EJB引起混淆。記住,J2EE和EJB不是同意詞。EJB只是J2EE 的一部分,J2EE 是包含JSP、servlet、Java 消息服務(wù)(JMS)、Java數(shù)據(jù)庫(kù)連接(JDBC)、JAAS、 Java管理擴(kuò)展(JMX)和EJB在內(nèi)的一系列技術(shù),同樣也是有關(guān)如何共同使用這些技術(shù)建立解決方案的一組指導(dǎo)原則和模式。
  如果在不需要使用EJB的情況下使用EJB,它們可能會(huì)影響程序的性能。與老的Web服務(wù)器相比,EJB一般對(duì)應(yīng)用服務(wù)器有更多的需求。EJB提供的所有增值服務(wù)一般需要消耗更大的內(nèi)存和更多的CPU時(shí)間。許多應(yīng)用程序不需要這些服務(wù),因此應(yīng)用服務(wù)器要與應(yīng)用程序爭(zhēng)奪資源。
  在某些情況下,不必要地使用EJB可能使應(yīng)用程序崩潰。例如,最近我遇到了一個(gè)在開(kāi)源應(yīng)用服務(wù)器上開(kāi)發(fā)的應(yīng)用程序。業(yè)務(wù)邏輯封裝在一系列有狀態(tài)會(huì)話bean(EJB)中。開(kāi)發(fā)人員為了在應(yīng)用服務(wù)器中完全禁用這些bean的“鈍化”費(fèi)了很大的勁??蛻舳艘髴?yīng)用程序部署在某一商用應(yīng)用服務(wù)器上,而該服務(wù)器是客戶端技術(shù)棧的一部分。該應(yīng)用服務(wù)器卻不允許關(guān)閉“鈍化”功能。事實(shí)上,客戶端不想改變與其合作的應(yīng)用服務(wù)器的設(shè)任何置。結(jié)果,開(kāi)發(fā)商碰到了很大的麻煩。(似乎)有趣的事情是開(kāi)發(fā)商自己都不能給出為什么將代碼用EJB(而且還是有狀態(tài)會(huì)話bean)實(shí)現(xiàn)的好理由。不僅僅是開(kāi)發(fā)商會(huì)遇到性能問(wèn)題,他們的程序在客戶那里也無(wú)法工作。
  在Web應(yīng)用程序中,無(wú)格式普通Java 對(duì)象(POJO)是EJB強(qiáng)有力的競(jìng)爭(zhēng)者。POJO是輕量級(jí)的,不像EJB那樣負(fù)擔(dān)額外的負(fù)擔(dān)。在我看來(lái),對(duì)許多EJB的優(yōu)點(diǎn),例如對(duì)象入池,估計(jì)過(guò)高。POJO是您的朋友,不要被它束縛住手腳。

第6課:數(shù)據(jù)訪問(wèn)并不能托管O/R映射
  我曾參與過(guò)的所有Web應(yīng)用程序都向用戶提供從其他地方存取的數(shù)據(jù),并且因此需要一個(gè)數(shù)據(jù)訪問(wèn)層。這并不是說(shuō)所有的項(xiàng)目都需要標(biāo)識(shí)并建立這樣一個(gè)層,這僅僅說(shuō)明這樣層的存在不是隱含的就是明確的。如果是隱含的數(shù)據(jù)層,數(shù)據(jù)層是業(yè)務(wù)對(duì)象(即:業(yè)務(wù)服務(wù))層的一部分。這適用于小型應(yīng)用程序,但通常與大一些項(xiàng)目所接受的架構(gòu)指導(dǎo)原則相抵觸。
  總之,數(shù)據(jù)訪問(wèn)層必須滿足或超出以下四個(gè)標(biāo)準(zhǔn):
  具有透明性
  業(yè)務(wù)對(duì)象在不知道數(shù)據(jù)源實(shí)現(xiàn)的具體細(xì)節(jié)情況下,可以使用數(shù)據(jù)源。由于實(shí)現(xiàn)細(xì)節(jié)隱藏在數(shù)據(jù)訪問(wèn)層的內(nèi)部,所以訪問(wèn)是透明的。
  易于遷移
  數(shù)據(jù)訪問(wèn)層使應(yīng)用程序很容易遷移到其他數(shù)據(jù)庫(kù)實(shí)現(xiàn)。業(yè)務(wù)對(duì)象不了解底層的數(shù)據(jù)實(shí)現(xiàn),所以遷移僅僅涉及到修改數(shù)據(jù)訪問(wèn)層。進(jìn)一步地說(shuō),如果您正在部署某種工廠策略,您可以為每個(gè)底層的存儲(chǔ)實(shí)現(xiàn)提供具體的工廠實(shí)現(xiàn)。如果是那樣的話,遷移到不同的存儲(chǔ)實(shí)現(xiàn)意味著為應(yīng)用程序提供一個(gè)新的工廠實(shí)現(xiàn)。
  盡量減少業(yè)務(wù)對(duì)象中代碼復(fù)雜性
  因?yàn)閿?shù)據(jù)訪問(wèn)層管理著所有的數(shù)據(jù)訪問(wèn)復(fù)雜性,所以它可以簡(jiǎn)化業(yè)務(wù)對(duì)象和使用數(shù)據(jù)訪問(wèn)層的其他數(shù)據(jù)客戶端的代碼。數(shù)據(jù)訪問(wèn)層,而不是業(yè)務(wù)對(duì)象,含有許多與實(shí)現(xiàn)相關(guān)的代碼(例如SQL語(yǔ)句)。這樣給開(kāi)發(fā)人員帶來(lái)了更高的效率、更好的可維護(hù)性、提高了代碼的可讀性等一系列好處。
  把所有的數(shù)據(jù)訪問(wèn)集中在單獨(dú)的層上
  由于所有的數(shù)據(jù)訪問(wèn)操作現(xiàn)在都委托給數(shù)據(jù)訪問(wèn)層,所以您可以將這個(gè)單獨(dú)的數(shù)據(jù)訪問(wèn)層看做能夠?qū)?yīng)用程序的其他部分與數(shù)據(jù)訪問(wèn)實(shí)現(xiàn)相互隔離的層。這種集中化可以使應(yīng)用程序易于維護(hù)和管理。
  注意:這些標(biāo)準(zhǔn)都不能明確地調(diào)出對(duì)O/R(對(duì)象到關(guān)系)映射層的需求。O/R映射層一般用O/R映射工具創(chuàng)建,它提供對(duì)象對(duì)關(guān)系數(shù)據(jù)結(jié)構(gòu)的查看和感知(look-and-feel)。在我看來(lái),在項(xiàng)目中使用O/R映射與使用EJB類似。在大多數(shù)情況下,并不要求它。對(duì)于包含中等規(guī)模的聯(lián)合以及多對(duì)多關(guān)系的關(guān)系型數(shù)據(jù)庫(kù)來(lái)說(shuō),O/R映射會(huì)變得相當(dāng)復(fù)雜。由于增加O/R 映射解決方案本身的內(nèi)在復(fù)雜性,例如延遲加載(lazy loading)、高速緩沖等,您將為您的項(xiàng)目帶來(lái)更大的復(fù)雜性(和風(fēng)險(xiǎn))。
  為了進(jìn)一步支持我的觀點(diǎn),我將指出按照Sun Microsystem所普及的實(shí)體Bean(O/R映射的一種實(shí)現(xiàn))的許多失敗的嘗試,這是自1.0版以來(lái)一直折磨人的難題。在SUN的防衛(wèi)措施中,一些早期的問(wèn)題是有關(guān)EJB規(guī)范的開(kāi)發(fā)商實(shí)現(xiàn)的。這依次證明了實(shí)體Bean規(guī)范自身的復(fù)雜性。結(jié)果,大多數(shù)J2EE架構(gòu)師一般認(rèn)為從實(shí)體Bean中脫離出來(lái)是一個(gè)好主意。
  大多數(shù)應(yīng)用程序在處理他們的數(shù)據(jù)時(shí),只能進(jìn)行有限次數(shù)的查詢。在這樣的應(yīng)用程序中,訪問(wèn)數(shù)據(jù)的一種有效方法是實(shí)現(xiàn)一個(gè)數(shù)據(jù)訪問(wèn)層,該層實(shí)現(xiàn)執(zhí)行這些查詢的一系列服務(wù)(或?qū)ο?、或API)。如上所述,在這種情況下,不需要O/R映射。當(dāng)您要求查詢靈活性時(shí),O/R映射正合適,但要記住:這種附加的靈活性并不是沒(méi)有代價(jià)的。
  就像我承諾的那樣,在本文中,我盡量避免陳腐的最佳實(shí)踐。相反,關(guān)于J2EE項(xiàng)目中每一位架構(gòu)師必須做出的最重要的決定,我集中講解了我的觀點(diǎn)。最后,您應(yīng)該記?。篔2EE并非某種具體的技術(shù),也不是強(qiáng)行加入到解決方案中的一些首字母縮寫(xiě)。相反,您應(yīng)該在適當(dāng)?shù)臅r(shí)機(jī),恰當(dāng)?shù)牡胤剑褂煤线m的技術(shù),并遵循J2EE的指導(dǎo)原則和J2EE中所包含的比技術(shù)本身重要得多的實(shí)踐。


JAVA 12個(gè)最重要的J2EE最佳實(shí)踐

1、始終使用 MVC 框架。
2、在每一層都應(yīng)用自動(dòng)單元測(cè)試和測(cè)試管理。
3、按照規(guī)范來(lái)進(jìn)行開(kāi)發(fā),而不是按照應(yīng)用服務(wù)器來(lái)進(jìn)行開(kāi)發(fā)。
4、從一開(kāi)始就計(jì)劃使用 J2EE 安全性。
5、創(chuàng)建您所知道的。
6、當(dāng)使用 EJB 組件時(shí),始終使用會(huì)話 Facades。
7、使用無(wú)狀態(tài)會(huì)話 bean,而不是有狀態(tài)會(huì)話 bean.
8、使用容器管理的事務(wù)。
9、將 JSP 作為表示層的首選。
10、當(dāng)使用 HttpSession 時(shí),盡量只將當(dāng)前事務(wù)所需要的狀態(tài)保存其中,其他內(nèi)容不要保存在 HttpSession 中。
11、在 WebSphere 中,啟動(dòng)動(dòng)態(tài)緩存,并使用 WebSphere servlet 緩存機(jī)制。
12、為了提高程序員的工作效率,將 CMP 實(shí)體 bean 作為 O/R 映射的首選解決方案。


1. 始終使用 MVC 框架。

MVC 框架可以將業(yè)務(wù)邏輯(Java beans 和 EJB 組件)、控制器邏輯(Servlets/Struts 動(dòng)作)、表示層(JSP、XML/XSLT)清晰地分離開(kāi)來(lái)。良好的分層可以帶來(lái)許多好處。

MVC 框架對(duì)于成功使用 J2EE 是如此重要,以致沒(méi)有其他最佳實(shí)踐可以與其相提并論。模型-視圖-控制器(MVC)是設(shè)計(jì) J2EE 應(yīng)用程序的基礎(chǔ)。MVC 將您的程序代碼簡(jiǎn)單地劃分下面幾個(gè)部分:

負(fù)責(zé)業(yè)務(wù)邏輯的代碼(即模型——通常使用 EJB 或者普通的 Java 對(duì)象來(lái)實(shí)現(xiàn))。

負(fù)責(zé)用戶界面顯示的代碼(即視圖——通常通過(guò) JSP 及標(biāo)記庫(kù)來(lái)實(shí)現(xiàn),有時(shí)也使用 XML 和 XSLT 來(lái)實(shí)現(xiàn))。

負(fù)責(zé)應(yīng)用程序流程的代碼(即控制器——通常使用 Java Servlet 或像 Struts 控制器這樣的類來(lái)實(shí)現(xiàn))。

如果您不遵循基本的 MVC 框架,在開(kāi)發(fā)過(guò)程中就會(huì)出現(xiàn)許多的問(wèn)題。最常見(jiàn)的問(wèn)題就是在視圖部分添加了太多的成分,例如,可能存在使用 JSP 標(biāo)記來(lái)執(zhí)行數(shù)據(jù)庫(kù)訪問(wèn),或者在 JSP 中進(jìn)行應(yīng)用程序的流程控制,這在小規(guī)模的應(yīng)用程序中是比較常見(jiàn)的,但是,隨著后期的開(kāi)發(fā),這樣做將會(huì)帶來(lái)問(wèn)題,因?yàn)?JSP 逐步變得越來(lái)越難以維護(hù)和調(diào)試。

類似地,我們也經(jīng)常看到將視圖層構(gòu)建到業(yè)務(wù)邏輯的情況。例如,一個(gè)常見(jiàn)的問(wèn)題就是將在構(gòu)建視圖時(shí)使用的 XML 解析技術(shù)直接應(yīng)用到業(yè)務(wù)層。業(yè)務(wù)層應(yīng)該對(duì)業(yè)務(wù)對(duì)象——而不是綁定到視圖的特定數(shù)據(jù)表示進(jìn)行操作。

然而,只是具有合適的組件并不一定意味著可以使您的應(yīng)用程序得到合適的分層。我們常常見(jiàn)到一些應(yīng)用程序包含 servlet、JSP 和 EJB 組件所有這三項(xiàng),然而,其主要的業(yè)務(wù)邏輯卻是在 servlet 層實(shí)現(xiàn)的,或者應(yīng)用程序?qū)Ш绞窃?JSP 中處理的。您必須進(jìn)行嚴(yán)格的代碼檢查并重構(gòu)您的代碼,以確保應(yīng)用程序的業(yè)務(wù)邏輯只在模型層(Model layer)進(jìn)行處理,應(yīng)用程序?qū)Ш街煌ㄟ^(guò)控制器層(Controller layer)進(jìn)行處理,而您的視圖(Views)只是將傳遞過(guò)來(lái)的模型對(duì)象以 HTML 及 JavaScript 的形式表示出來(lái)。


2. 在應(yīng)用程序的每一層都使用自動(dòng)單元測(cè)試和測(cè)試管理。

不要只是測(cè)試您的圖形用戶界面(GUI)。分層的測(cè)試使測(cè)試及維護(hù)工作變得極其簡(jiǎn)單。

在過(guò)去的幾年中,在方法學(xué)領(lǐng)域有了相當(dāng)大的革新,例如新出現(xiàn)的被稱為 Agile(例如 SCRUM [Schwaber] 和極限編程 [Beck1])的輕量級(jí)方法現(xiàn)在已經(jīng)得到了很普遍的應(yīng)用。幾乎所有的這些方法中的一個(gè)共同的特征是它們都提倡使用自動(dòng)的測(cè)試工具,這些工具可以幫助開(kāi)發(fā)人員用更少的時(shí)間進(jìn)行回歸測(cè)試 (regression testing),并可以幫助他們避免由于不充分的回歸測(cè)試造成的錯(cuò)誤,因此可以用來(lái)提高程序員的工作效率。實(shí)際上,還有一種被稱為 Test-First Development [Beck2] 的方法,這種方法甚至提倡在開(kāi)發(fā)實(shí)際的代碼之前就先編寫(xiě)單元測(cè)試。然而,在您測(cè)試代碼之前,您需要將代碼分割成一些可測(cè)試的片斷。一個(gè)“大泥球”是難以測(cè)試的,因?yàn)樗皇侵粚?shí)現(xiàn)一個(gè)簡(jiǎn)單的易于識(shí)別的功能。如果您的每個(gè)代碼片斷實(shí)現(xiàn)多個(gè)方面的功能,這樣的代碼將難以保證其完全的正確性。

MVC 框架(以及 J2EE 中的 MVC 實(shí)現(xiàn))的一個(gè)優(yōu)點(diǎn)就是元素的組件化能夠(實(shí)際上,相當(dāng)?shù)暮?jiǎn)單)對(duì)您的應(yīng)用程序進(jìn)行單元測(cè)試。因此,您可以方便地對(duì)實(shí)體 bean、會(huì)話 bean 以及 JSP 獨(dú)立編寫(xiě)測(cè)試用例,而不必考慮其他的代碼。現(xiàn)在有許多用于 J2EE 測(cè)試的框架和工具,這些框架及工具使得這一過(guò)程更加簡(jiǎn)單。例如,JUnit(是一種由 junit.org 開(kāi)發(fā)的開(kāi)放源代碼工具)和 Cactus(由 Apache 開(kāi)發(fā)的開(kāi)放源代碼工具)對(duì)于測(cè)試 J2EE 組件都非常有用。[Hightower] 詳細(xì)探討了如何在 J2EE 中使用這些工具。

盡管所有這些詳述了怎樣徹底地測(cè)試您的應(yīng)用程序,但是我們?nèi)匀豢吹揭恍┤苏J(rèn)為只要他們測(cè)試了 GUI(可能是基于 Web 的 GUI,或者是獨(dú)立的 Java 應(yīng)用程序),則他們就全面地測(cè)試了整個(gè)應(yīng)用程序。GUI 測(cè)試很難達(dá)到全面的測(cè)試,有以下幾種原因。首先,使用 GUI 測(cè)試很難徹底地測(cè)試到系統(tǒng)的每一條路徑,GUI 僅僅是影響系統(tǒng)的一種方式,可能存在后臺(tái)運(yùn)算、腳本和各種各樣的其他訪問(wèn)點(diǎn),這也需要進(jìn)行測(cè)試。然而,它們通常并不具有 GUI。第二,GUI 級(jí)的測(cè)試是一種非常粗粒度的測(cè)試。這種測(cè)試只是在宏觀水平上測(cè)試系統(tǒng)的行為。這意味著一旦發(fā)現(xiàn)存在問(wèn)題,則與此問(wèn)題相關(guān)的整個(gè)子系統(tǒng)都要進(jìn)行檢查,這使得找出 bug(缺陷)將是非常困難的事情。第三,GUI 測(cè)試通常只有在整個(gè)開(kāi)發(fā)周期的后期才能很好地得到測(cè)試,這是因?yàn)橹挥羞@那個(gè)時(shí)候 GUI 才得到完整的定義。這意味著只有在后期才可能發(fā)現(xiàn)潛在的 bug。第四,一般的開(kāi)發(fā)人員可能沒(méi)有自動(dòng)的 GUI 測(cè)試工具。因此,當(dāng)一個(gè)開(kāi)發(fā)人員對(duì)代碼進(jìn)行更改時(shí),沒(méi)有一種簡(jiǎn)單的方法來(lái)重新測(cè)試受到影響的子系統(tǒng)。這實(shí)際上不利于進(jìn)行良好的測(cè)試。如果開(kāi)發(fā)人員具有自動(dòng)的代碼級(jí)單元測(cè)試工具,開(kāi)發(fā)人員就能夠很容易地運(yùn)行這些工具以確保所做的更改不會(huì)破壞已經(jīng)存在的功能。最后,如果添加了自動(dòng)構(gòu)建功能,則在自動(dòng)構(gòu)建過(guò)程中添加一個(gè)自動(dòng)的單元測(cè)試工具是非常容易的事情。當(dāng)完成這些設(shè)置以后,整個(gè)系統(tǒng)就可以有規(guī)律地進(jìn)行重建,并且回歸測(cè)試幾乎不需要人的參與。

另外,我們必須強(qiáng)調(diào),使用 EJB 和 Web 服務(wù)進(jìn)行分布式的、基于組件的開(kāi)發(fā)使得測(cè)試單個(gè)的組件變得非常必要。如果沒(méi)有“GUI”需要測(cè)試,您就必須進(jìn)行低級(jí)(lower-level)測(cè)試。最好以這種方式開(kāi)始測(cè)試,省得當(dāng)您將分布式的組件或 Web 服務(wù)作為您的應(yīng)用程序的一部分時(shí),您不得不花費(fèi)心思重新進(jìn)行測(cè)試。

總之,通過(guò)使用自動(dòng)的單元測(cè)試,能夠很快地發(fā)現(xiàn)系統(tǒng)的缺陷,并且也易于發(fā)現(xiàn)這些缺陷,使得測(cè)試工作變得更加系統(tǒng)化,因此整體的質(zhì)量也得以提高。


3. 按照規(guī)范來(lái)進(jìn)行開(kāi)發(fā),而不是按照應(yīng)用服務(wù)器來(lái)進(jìn)行開(kāi)發(fā)。
要將規(guī)范熟記于心,如果要背離規(guī)范,要經(jīng)過(guò)慎密的考慮后才可以這樣做。這是因?yàn)楫?dāng)您背離規(guī)則的時(shí)候,您所做的事情往往并不是您應(yīng)該做的事情。

當(dāng)您要背離 J2EE 可以允許您做的事情的時(shí)候,這很容易讓使您遭受不幸。我們發(fā)現(xiàn)有一些開(kāi)發(fā)人員鉆研一些 J2EE 允許之外的東西,他們認(rèn)為這樣做可以“稍微”改善J2EE的性能,而他們最終只會(huì)發(fā)現(xiàn)這樣做會(huì)引起嚴(yán)重的性能問(wèn)題,或者在以后的移植(從一個(gè)廠商到另一個(gè)廠商,或者是更常見(jiàn)的從一個(gè)版本到另一個(gè)版本)中會(huì)出現(xiàn)問(wèn)題。實(shí)際上,這種移植問(wèn)題是如此嚴(yán)重,以致 [Beaton] 將此原則稱為移植工作的基本最佳實(shí)踐。

現(xiàn)在有好幾個(gè)地方如果不直接使用 J2EE 提供的方法肯定會(huì)產(chǎn)生問(wèn)題。一個(gè)常見(jiàn)的例子就是開(kāi)發(fā)人員通過(guò)使用 JAAS 模塊來(lái)替代 J2EE 安全性,而不是使用內(nèi)置的遵循規(guī)范的應(yīng)用程序服務(wù)器機(jī)制來(lái)進(jìn)行驗(yàn)證和授權(quán)。要注意不要脫離 J2EE 規(guī)范提供的驗(yàn)證機(jī)制,如果脫離了此規(guī)范,這將是系統(tǒng)存在安全漏洞以及廠商兼容性問(wèn)題的主要原因。類似地,要使用 servlet 和 EJB 規(guī)范提供的授權(quán)機(jī)制,并且如果您要偏離這些規(guī)范的話,要確保使用規(guī)范定義的 API(例如 getCallerPrincipal())作為實(shí)現(xiàn)的基礎(chǔ)。通過(guò)這種方式,您將能夠利用廠商提供的強(qiáng)安全性基礎(chǔ)設(shè)施,其中,業(yè)務(wù)要求需要支持復(fù)雜的授權(quán)規(guī)則。

其他常見(jiàn)的問(wèn)題包括使用不遵循 J2EE 規(guī)范的持久性機(jī)制(這使得事務(wù)管理變得困難)、在J2EE程序中使用不適當(dāng)?shù)腏2SE 方法(例如線程或 singleton),以及使用您自己的方法解決程序到程序(program-to-program)的通信,而不是使用 J2EE 內(nèi)在支持的機(jī)制(例如 JCA、JMS 或 Web 服務(wù))。當(dāng)您將一個(gè)遵循 J2EE 的服務(wù)器移植到其他的服務(wù)器上,或者移植到相同服務(wù)器的新版本上,上述的設(shè)計(jì)選擇將會(huì)造成無(wú)數(shù)的問(wèn)題。唯一要背離規(guī)范的情況是,當(dāng)一個(gè)問(wèn)題在規(guī)范的范圍內(nèi)無(wú)法解決的時(shí)候。例如,安排執(zhí)行定時(shí)的業(yè)務(wù)邏輯在 EJB2.1 出現(xiàn)之前是一個(gè)問(wèn)題,在類似這樣的情況下,我們建議當(dāng)有廠商提供的解決方案時(shí)就使用廠商提供的解決方案(例如 WebSphere Application Server Enterprise 中的 Scheduler 工具),而在沒(méi)有廠商提供的解決方案時(shí)就使用第三方提供的工具。如果使用廠商提供的解決方案,應(yīng)用程序的維護(hù)以及將其移植到新的規(guī)范版本將是廠商的問(wèn)題,而不是您的問(wèn)題。

最后,要注意不要太早地采用新技術(shù)。太過(guò)于熱衷采用還沒(méi)有集成到 J2EE 規(guī)范的其他部分或者還沒(méi)有集成到廠商的產(chǎn)品中的技術(shù)常會(huì)帶來(lái)災(zāi)難性的后果。支持是關(guān)鍵的——如果您的廠商不直接支持一種特定的在 JSR 中提出的技術(shù),但此技術(shù)還沒(méi)有被 J2EE 所接受,那么您就不應(yīng)該采用此技術(shù)。畢竟,我們中的大多數(shù)人從事解決業(yè)務(wù)問(wèn)題,而不是推進(jìn)技術(shù)的發(fā)展。


4. 從一開(kāi)始就計(jì)劃使用 J2EE 安全性。

啟用 WebSphere 安全性。這使您的 EJB 和 URL 至少可以讓所有授權(quán)用戶訪問(wèn)。不要問(wèn)為什么——照著做就是了。

在與我們合作的客戶中,一開(kāi)始就打算啟用 WebSphere J2EE 安全性的顧客是非常少的,這一點(diǎn)一直讓我們感到吃驚。據(jù)我們估計(jì)大約只有 50% 的顧客一開(kāi)始就打算使用此特性。例如,我們?cè)c一些大型的金融機(jī)構(gòu)(銀行、代理等等)合作過(guò),他們也沒(méi)有打算啟用安全性。幸運(yùn)的是,這種問(wèn)題在部署之前的檢查時(shí)就得以解決.

不使用 J2EE 安全性是危險(xiǎn)的事情。假設(shè)您的應(yīng)用程序需要安全性(幾乎所有的應(yīng)用程序都需要),您敢打賭您的開(kāi)發(fā)人員能夠構(gòu)建出自己的安全性系統(tǒng),而這個(gè)系統(tǒng)比您從 J2EE 廠商那里買來(lái)的更好。這可不是個(gè)好的賭注,為分布式的應(yīng)用程序提供安全性是異常困難的。例如,您需要使用網(wǎng)絡(luò)安全加密令牌控制對(duì) EJB 的訪問(wèn)。以我們的經(jīng)驗(yàn)看來(lái),大多數(shù)自己構(gòu)建的安全性系統(tǒng)是不安全的,并且有重大的缺陷,這使產(chǎn)品系統(tǒng)極其脆弱。

一些不使用 J2EE 安全性的理由包括:擔(dān)心性能的下降,相信其他的安全性(例如 Netegrity SiteMinder)可以取代 J2EE 安全性,或者是不知道 WebSphere Application Server 安全特性及功能。不要陷入這些陷阱之中,尤其是,盡管像 Netegrity SiteMinder 這樣的產(chǎn)品能夠提供優(yōu)秀的安全特性,但是僅僅其自身不可能保護(hù)整個(gè) J2EE 應(yīng)用程序。這些產(chǎn)品必須與 J2EE 應(yīng)用程序服務(wù)器聯(lián)合起來(lái)才可能全面地保護(hù)您的系統(tǒng)。

其他的一種常見(jiàn)的不使用 J2EE 安全性的原因是:基于角色的模型沒(méi)有提供足夠的粒度訪問(wèn)控制以滿足復(fù)雜的業(yè)務(wù)規(guī)則。盡管事實(shí)是這樣的,但這也不應(yīng)該成為不使用 J2EE 安全性的理由。相反地,應(yīng)該將 J2EE 驗(yàn)證及 J2EE 角色與特定的擴(kuò)展規(guī)則結(jié)合起來(lái)。如果復(fù)雜的業(yè)務(wù)規(guī)則需要做出安全性決策,那就編寫(xiě)相應(yīng)的代碼,其安全性決策要基于可以直接使用的以及可靠的 J2EE 驗(yàn)證信息(用戶 ID 和角色)。


5. 創(chuàng)建您所知道的。

反復(fù)的開(kāi)發(fā)工作將使您能夠逐漸地掌握所有的 J2EE 模塊。要從創(chuàng)建小而簡(jiǎn)單的模塊開(kāi)始而不是從一開(kāi)始就馬上涉及到所有的模塊。

我們必須承認(rèn) J2EE 是龐大的體系。如果一個(gè)開(kāi)發(fā)小組只是開(kāi)始使用 J2EE,這將很難一下子就能掌握它。在 J2EE 中有太多的概念和 API 需要掌握。在這種情況下,成功掌握 J2EE 的關(guān)鍵是從簡(jiǎn)單的步驟開(kāi)始做起。

這種方法可以通過(guò)在您的應(yīng)用程序中創(chuàng)建小而簡(jiǎn)單的模塊來(lái)得到最好的實(shí)現(xiàn)。如果一個(gè)開(kāi)發(fā)小組通過(guò)創(chuàng)建一個(gè)簡(jiǎn)單的域模型以及后端的持久性機(jī)制(也許使用的是 JDBC),并且對(duì)其進(jìn)行了完整的測(cè)試,這會(huì)增強(qiáng)他們的自信心,于是他們會(huì)使用該域模型去掌握使用 servlet 和 JSP 的前端開(kāi)發(fā)。如果一個(gè)開(kāi)發(fā)組發(fā)現(xiàn)有必要使用 EJB,他們也會(huì)類似地開(kāi)始在容器管理的持久性 EJB 組件之上使用簡(jiǎn)單的會(huì)話 Facades,或者使用基于 JDBC 的數(shù)據(jù)訪問(wèn)對(duì)象(JDBC-based Data Access Objects,DAO),而不是跳過(guò)這些去使用更加復(fù)雜的構(gòu)造(例如消息驅(qū)動(dòng)bean和JMS)。

這種方法并不是什么新方法,但是很少有開(kāi)發(fā)組以這種方式來(lái)培養(yǎng)他們的技能。相反地,多數(shù)開(kāi)發(fā)組由于嘗試馬上就構(gòu)建所有的模塊,同時(shí)涉及 MVC 中的視圖層、模型層和控制器層,這樣做的結(jié)果是他們往往會(huì)陷入進(jìn)度的壓力之中。他們應(yīng)該考慮一些敏捷(Agile)開(kāi)發(fā)方法,例如極限編程(XP),這種開(kāi)發(fā)方法采用一種增量學(xué)習(xí)及開(kāi)發(fā)方法。在 XP 中有一種稱為 ModelFirst 的過(guò)程,這個(gè)過(guò)程涉及到首先構(gòu)建域模型作為一種機(jī)制來(lái)組織和實(shí)現(xiàn)用戶場(chǎng)景。基本說(shuō)來(lái),您要構(gòu)建域模型作為您要實(shí)現(xiàn)的用戶場(chǎng)景的首要部分,然后在域模型之上構(gòu)建一個(gè)用戶界面(UI)作為用戶場(chǎng)景實(shí)現(xiàn)的結(jié)果。這種方法非常適合讓一個(gè)開(kāi)發(fā)組一次只學(xué)到一種技術(shù),而不是讓他們同時(shí)面對(duì)很多種情況(或者讓他們讀很多書(shū)),這會(huì)令他們崩潰的。

還有,對(duì)每個(gè)應(yīng)用程序?qū)又貜?fù)的開(kāi)發(fā)可能會(huì)包含一些適當(dāng)?shù)哪J郊白罴褜?shí)踐。如果您從應(yīng)用程序的底層開(kāi)始應(yīng)用一些模式如數(shù)據(jù)訪問(wèn)對(duì)象和會(huì)話 Facades,您就不應(yīng)該在您的JSP和其他視圖對(duì)象中使用域邏輯。

最后,當(dāng)您開(kāi)發(fā)一些簡(jiǎn)單的模塊時(shí),在開(kāi)始的初期就可以對(duì)您的應(yīng)用程序進(jìn)行性能測(cè)試。如果直到應(yīng)用程序開(kāi)發(fā)的后期才進(jìn)行性能測(cè)試的話,這往往會(huì)出現(xiàn)災(zāi)難性的后果。


6. 當(dāng)使用 EJB 組件時(shí),始終使用會(huì)話 Facades。

決不要將實(shí)體 bean 直接暴露給任何用戶類型。對(duì)實(shí)體 bean 只可以使用本地 EJB 接口(Local EJB interfaces)。

當(dāng)使用 EJB 組件時(shí),使用一個(gè)會(huì)話 Facades 是一個(gè)確認(rèn)無(wú)疑的最佳實(shí)踐。實(shí)際上,這個(gè)通用的實(shí)踐被廣泛地應(yīng)用到任何分布式的技術(shù)中,包括 CORBA、EJB 和 DCOM。從根本上講,您的應(yīng)用程序的分布“交叉區(qū)域”越是底層化,對(duì)小塊的數(shù)據(jù)由于多次重復(fù)的網(wǎng)絡(luò)中繼造成的時(shí)間消耗就越少。要達(dá)到這個(gè)目的的方法就是:創(chuàng)建大粒度的 Facades 對(duì)象,這個(gè)對(duì)象包含邏輯子系統(tǒng),因而可以通過(guò)一個(gè)方法調(diào)用就可以完成一些有用的業(yè)務(wù)功能。這種方法不但能夠降低網(wǎng)絡(luò)開(kāi)銷,而且在 EJB 內(nèi)部通過(guò)為整個(gè)業(yè)務(wù)功能創(chuàng)建一個(gè)事務(wù)環(huán)境也可以大大地減少對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)次數(shù)。

EJB 本地接口(從 EJB 2.0 規(guī)范開(kāi)始使用)為共存的 EJB 提供了性能優(yōu)化方法。本地接口必須被您的應(yīng)用程序顯式地進(jìn)行訪問(wèn),這需要代碼的改變和防止以后配置 EJB 時(shí)需要應(yīng)用程序的改變。由于會(huì)話 Facades 和它包含的整個(gè) EJB 對(duì)于彼此來(lái)說(shuō)都應(yīng)該是本地的,我們建議對(duì)會(huì)話 Facades 后面的實(shí)體 bean 使用本地接口。然而,會(huì)話 Facades 本身的實(shí)現(xiàn)(典型例子如無(wú)狀態(tài)會(huì)話 bean)應(yīng)該設(shè)計(jì)為遠(yuǎn)程接口。

為了性能的優(yōu)化,可以將一個(gè)本地接口添加到會(huì)話 Facades。這樣做利用了這樣一個(gè)事實(shí):在大多數(shù)情況下(至少在 Web 應(yīng)用程序中),您的 EJB 客戶端和 EJB 會(huì)共同存在于同一個(gè) Java 虛擬機(jī)(JVM)中。另外一種情況,如果會(huì)話 Facades 在本地被調(diào)用,可以使用 J2EE 應(yīng)用服務(wù)器配置優(yōu)化(configuration optimizations),例如 WebSphere 中的“No Local Copies”。然而,您必須注意到這些可供選擇的方案會(huì)將交互方法從按值傳遞(pass-by-value)改變?yōu)榘匆脗鬟f(pass-by-reference)。這可能會(huì)在您的代碼中產(chǎn)生很微妙的錯(cuò)誤。當(dāng)您要利用這些方案時(shí),您應(yīng)該在一開(kāi)始就考慮其可行性。

如果在您的會(huì)話 Facades 中使用遠(yuǎn)程接口(而不是本地接口),您也可以將同樣的會(huì)話 Facades 在 J2EE 1.4 中以兼容的方式作為 Web 服務(wù)來(lái)配置。這是因?yàn)?JSR 109(J2EE 1.4 中的 Web 服務(wù)部署部分)要求使用無(wú)狀態(tài)會(huì)話 bean 的遠(yuǎn)程接口作為 EJB Web 服務(wù)和 EJB 實(shí)現(xiàn)的接口。這樣做是值得的,因?yàn)檫@樣做可以為您的業(yè)務(wù)邏輯增加客戶端類型的數(shù)量。


7. 使用無(wú)狀態(tài)會(huì)話 bean,而不是有狀態(tài)會(huì)話 bean。

這樣做可以使您的系統(tǒng)經(jīng)得起錯(cuò)誤的終止。使用 HttpSession 存儲(chǔ)和用戶相關(guān)的狀態(tài)。

以我們的觀點(diǎn)看來(lái),有狀態(tài)會(huì)話 bean 的概念已經(jīng)過(guò)時(shí)了。如果您仔細(xì)對(duì)其考慮一下,一個(gè)有狀態(tài)會(huì)話 bean 實(shí)際上與一個(gè) CORBA 對(duì)象在體系結(jié)構(gòu)上是完全相同的,無(wú)非就是一個(gè)對(duì)象實(shí)例,綁定到一個(gè)服務(wù)器,并且依賴于服務(wù)器來(lái)管理其生命周期。如果服務(wù)器關(guān)閉了,這種對(duì)象也就不存在,那么這個(gè) bean 的客戶端的信息也就不存在。

J2EE 應(yīng)用服務(wù)器為有狀態(tài)會(huì)話 bean 提供的故障轉(zhuǎn)移(failover)能夠解決一些問(wèn)題,但是有狀態(tài)的解決方案沒(méi)有無(wú)狀態(tài)的解決方案易于擴(kuò)展。例如,在 WebSphere Application Server 中,對(duì)無(wú)狀態(tài)會(huì)話 bean 的請(qǐng)求,是通過(guò)對(duì)部署無(wú)狀態(tài)會(huì)話的成員集群進(jìn)行平衡加載來(lái)實(shí)現(xiàn)。相反地,J2EE 應(yīng)用服務(wù)器不能對(duì)有狀態(tài) bean 的請(qǐng)求進(jìn)行平衡加載。這意味著您的集群中的服務(wù)器的加載過(guò)程會(huì)是不均衡的。此外,使用有狀態(tài)會(huì)話 bean 將會(huì)再添加一些狀態(tài)到您的應(yīng)用服務(wù)器上,這也是不好的做法。這樣就增加了系統(tǒng)的復(fù)雜性,并且在出現(xiàn)故障的情況下使問(wèn)題變得復(fù)雜化。創(chuàng)建健壯的分布式系統(tǒng)的一個(gè)關(guān)鍵原則是盡量使用無(wú)狀態(tài)行為。

因此,我們建議對(duì)大多數(shù)應(yīng)用程序使用無(wú)狀態(tài)會(huì)話 bean 方法。任何在處理時(shí)需要使用的與用戶相關(guān)的狀態(tài)應(yīng)該以參數(shù)的形式傳送到 EJB 的方法中(并且通過(guò)使用一種機(jī)制如 HttpSession 來(lái)存儲(chǔ)它)或者從持久性的后端存儲(chǔ)(例如通過(guò)使用實(shí)體 bean)作為 EJB 事務(wù)的一部分來(lái)進(jìn)行檢索。在合適的情況下,這個(gè)信息可以緩存到內(nèi)存中,但是要注意在分布式的環(huán)境中保存這種緩存所潛在的挑戰(zhàn)性。緩存非常適合于只讀數(shù)據(jù)。

總之,您要確保從一開(kāi)始就要考慮到可伸展性。檢查設(shè)計(jì)中的所有設(shè)想,并且考慮到當(dāng)您的應(yīng)用程序要在多個(gè)服務(wù)器上運(yùn)行時(shí),是否也可以正常運(yùn)行。這個(gè)規(guī)則不但適合上述情況的應(yīng)用程序代碼,也適用于如 MBean 和其他管理界面的情況下。


8. 使用容器管理的事務(wù)。

學(xué)習(xí)一下 J2EE 中的兩階段提交事務(wù),并且使用這種方式,而不是開(kāi)放您自己的事務(wù)管理。容器在事務(wù)優(yōu)化方面幾乎總是比較好的。

使用容器管理的事務(wù)(CMT)提供了兩個(gè)關(guān)鍵的優(yōu)勢(shì)(如果沒(méi)有容器支持這幾乎是不可能的):可組合的工作單元和健壯的事務(wù)行為。

如果您的應(yīng)用程序代碼顯式地使用了開(kāi)始和結(jié)束事務(wù)(也許使用 javax.jts.UserTransaction 或者甚至是本地資源事務(wù)),而將來(lái)的要求需要組合模塊(也許會(huì)是代碼重構(gòu)的一部分),這種情況下往往需要改變事務(wù)代碼。例如,如果模塊 A 開(kāi)始了一個(gè)數(shù)據(jù)庫(kù)事務(wù),更新數(shù)據(jù)庫(kù),隨后提交事務(wù),并且有模塊 B 做出同樣的處理,請(qǐng)考慮一下當(dāng)您在模塊 C 中嘗試使用上述兩個(gè)模塊,會(huì)出現(xiàn)什么情況呢?現(xiàn)在,模塊 C 正在執(zhí)行一個(gè)邏輯動(dòng)作,而這個(gè)動(dòng)作實(shí)際上將調(diào)用兩個(gè)獨(dú)立的事務(wù)。如果模塊 B 在執(zhí)行中失敗了,而模塊 A 的事務(wù)仍然能被提交。這是我們所不希望出現(xiàn)的行為。如果,相反地,模塊 A 和模塊 B 都使用 CMT 的話,模塊 C 也可以開(kāi)始一個(gè) CMT(通常通過(guò)配置描述符),并且在模塊 A 和模塊 B 中的事務(wù)將是同一個(gè)事務(wù)的隱含部分,這樣就不再需要復(fù)雜的重寫(xiě)代碼的工作了。

如果您的應(yīng)用程序在同一個(gè)操作中需要訪問(wèn)多種資源,您就要使用兩階段提交事務(wù)。例如,如果從 JMS 隊(duì)列中刪除一個(gè)消息,并且隨后更新基于這條消息的紀(jì)錄,這時(shí),要保證這兩個(gè)操作都會(huì)執(zhí)行或都不會(huì)執(zhí)行就變得尤為重要。如果一條消息已經(jīng)從隊(duì)列中被刪除,而系統(tǒng)沒(méi)有更新與此消息相關(guān)的數(shù)據(jù)庫(kù)中的紀(jì)錄,那么這種系統(tǒng)是不穩(wěn)定的。一些嚴(yán)重的客戶及商業(yè)糾紛源自不一致的狀態(tài)。

我們時(shí)??吹揭恍┛蛻魬?yīng)用程序試圖實(shí)現(xiàn)他們自己的解決方案。也許會(huì)通過(guò)應(yīng)用程序的代碼在數(shù)據(jù)庫(kù)更新失敗的時(shí)候 “撤銷”對(duì)隊(duì)列的操作。我們不提倡這樣做。這種實(shí)現(xiàn)要比您最初的想象要復(fù)雜得多,并且還有許多其他的情況(想象一下如果應(yīng)用程序在執(zhí)行此操作的過(guò)程中突然崩潰的情況)。作為替代的方式,應(yīng)該使用兩階段提交事務(wù)。如果您使用 CMT,并且在一個(gè)單一的 CMT 中訪問(wèn)兩階段提交的資源(例如 JMS 和大多數(shù)數(shù)據(jù)庫(kù)),WebSphere 將會(huì)處理所有的復(fù)雜工作。它將確保整個(gè)事務(wù)被執(zhí)行或者都不被執(zhí)行,包括系統(tǒng)崩潰、數(shù)據(jù)庫(kù)崩潰或其他的情況。其實(shí)現(xiàn)在事務(wù)日志中保存著事務(wù)狀態(tài)。當(dāng)應(yīng)用程序訪問(wèn)多種資源的時(shí)候,我們?cè)趺磸?qiáng)調(diào)使用 CMT 事務(wù)的必要性都不為過(guò)。


9. 將 JSP 作為表示層的首選。

只有在需要多種表示輸出類型,并且輸出類型被一個(gè)單一的控制器及后端支持時(shí)才使用 XML/XSLT。

我們常聽(tīng)到一些爭(zhēng)論說(shuō),為什么您選擇 XML/XSLT 而不是 JSP 作為表示層技術(shù)。選擇 XML/XSLT 的人的觀點(diǎn)是,JSP“ 允許您將模型和視圖混合在一起”,而 XML/XSLT 不會(huì)有這種問(wèn)題。遺憾的是,這種觀點(diǎn)并不完全正確,或者至少不像白與黑那樣分的清楚。實(shí)際上,XSL 和 XPath 是編程語(yǔ)言。XSL 是圖靈完成的(Turing-complete),盡管它不符合大多數(shù)人定義的編程語(yǔ)言,因?yàn)樗腔谝?guī)則的,并且不具備程序員習(xí)慣的控制工具。

現(xiàn)在的問(wèn)題是既然給予了這種靈活性,開(kāi)發(fā)人員就會(huì)利用這種靈活性。盡管每個(gè)人都認(rèn)同 JSP 使開(kāi)發(fā)人員容易在視圖中加入“類似模型”的行為,而實(shí)際上,在 XSL 中也有可能做出一些同樣的事情。盡管從 XSL 中進(jìn)行訪問(wèn)數(shù)據(jù)庫(kù)這樣的事情會(huì)非常困難,但是我們?cè)?jīng)見(jiàn)到過(guò)一些異常復(fù)雜的 XSLT 樣式表執(zhí)行復(fù)雜的轉(zhuǎn)換,這實(shí)際上是模型代碼。

然而,應(yīng)該選擇 JSP 作為首選的表示技術(shù)的最基本的原因是,JSP 是現(xiàn)在支持最廣泛的、也是最被廣泛理解的 J2EE 視圖技術(shù)。而隨著自定義標(biāo)記庫(kù)、JSTL 和 JSP2.0 的新特性的引入,創(chuàng)建 JSP 變得更加容易,并且不需要任何 Java 代碼,以及可以將模型和視圖清晰的分離開(kāi)。在一些開(kāi)發(fā)環(huán)境中(如 WebSphere Studio)加入了對(duì) JSP(包括對(duì)調(diào)試的支持)的強(qiáng)大支持,并且許多開(kāi)發(fā)人員發(fā)現(xiàn)使用 JSP 進(jìn)行開(kāi)發(fā)要比使用 XLS 簡(jiǎn)單,一些支持 JSP 的圖形設(shè)計(jì)工具及其他特征(尤其在 JSF 這樣的框架下)使得開(kāi)發(fā)人員可以以所見(jiàn)即所得的方式進(jìn)行 JSP 的開(kāi)發(fā),而對(duì)于 XSL 有時(shí)不容易做到。

最后一個(gè)要謹(jǐn)慎考慮使用 JSP 的原因是速度問(wèn)題。在 IBM 所作的對(duì)比 XSL 和 JSP 相對(duì)速度的性能測(cè)試顯示:在大多數(shù)情況下,JSP 在生成同樣的 HTML 的時(shí)候,要比 XSL 快好幾倍,甚至使用編譯過(guò)的 XSL 也是如此。盡管多數(shù)情況下這不是問(wèn)題,但在性能要求很高的情況下,這就會(huì)成為問(wèn)題。

然而,這也不能說(shuō),您永遠(yuǎn)也不要使用 XSL。在一些情況下,XSL 能夠表示一組固定的數(shù)據(jù),并且可以基于不同的樣式表來(lái)以不同的方式顯示這些數(shù)據(jù)的能力是顯示視圖的最佳解決方案。然而,這只是一種例外的情況,而不是通用的規(guī)則。如果您只是生成 HTML 來(lái)表達(dá)每一個(gè)頁(yè)面,那么在大多數(shù)情況下,XSL 是一種不必要的技術(shù),并且,它給您的開(kāi)發(fā)人員所帶來(lái)的問(wèn)題遠(yuǎn)比它所能解決的問(wèn)題多。


10. 當(dāng)使用 HttpSession 時(shí),盡量只將當(dāng)前事務(wù)所需要的狀態(tài)保存其中,其他內(nèi)容不要保存在 HttpSession 中。

啟用會(huì)話持久性。

HttpSessions 對(duì)于存儲(chǔ)應(yīng)用程序狀態(tài)信息是非常有用的。其 API 易于使用和理解。遺憾的是,開(kāi)發(fā)人員常常遺忘了 HttpSession 的目的——用來(lái)保持暫時(shí)的用戶狀態(tài)。它不是任意的數(shù)據(jù)緩存。我們已經(jīng)見(jiàn)到過(guò)太多的系統(tǒng)為每個(gè)用戶的會(huì)話放入了大量的數(shù)據(jù)(達(dá)到兆字節(jié))。那好了,如果同時(shí)有 1000 個(gè)登錄系統(tǒng)的用戶,每個(gè)用戶擁有 1MB 的會(huì)話數(shù)據(jù),那么就需要 1G 或者更多的內(nèi)存用于這些會(huì)話。要使這些 HTTP 會(huì)話數(shù)據(jù)較小一些,不然的話,您的應(yīng)用程序的性能將會(huì)下降。一個(gè)大約比較合適的數(shù)據(jù)量應(yīng)該是每個(gè)用戶的會(huì)話數(shù)據(jù)在 2K-4K 之間,這不是一個(gè)硬性的規(guī)則,8K 仍然沒(méi)有問(wèn)題,但是顯然會(huì)比 2K 時(shí)的速度要慢。一定要注意,不要使 HttpSession 變成數(shù)據(jù)堆積的場(chǎng)所。

一個(gè)常見(jiàn)的問(wèn)題是使用 HttpSession 緩存一些很容易再創(chuàng)建的信息,如果有必要的話。由于會(huì)話是持久性的,進(jìn)行不必要的序列化以及寫(xiě)入數(shù)據(jù)是一種很奢侈的決定。相反地,應(yīng)該使用內(nèi)存中的哈希表來(lái)緩存數(shù)據(jù),并且在會(huì)話中保存一個(gè)對(duì)此數(shù)據(jù)進(jìn)行引用的關(guān)鍵字。這樣,如果不能成功登錄到另外的應(yīng)用服務(wù)器的話,就可以重新創(chuàng)建數(shù)據(jù)。

當(dāng)談及會(huì)話持久性時(shí),不要忘記要啟用這項(xiàng)功能。如果您沒(méi)有啟用會(huì)話持久性,或者服務(wù)器因?yàn)槟撤N原因停止了(服務(wù)器故障或正常的維護(hù)),則所有此應(yīng)用服務(wù)的當(dāng)前用戶的會(huì)話將會(huì)丟失。這是件令人非常不高興的事情。用戶不得不重新登錄,并且重新做一些他們?cè)?jīng)已經(jīng)做過(guò)的事情。相反地,如果啟用了會(huì)話持久性,WebSphere 會(huì)自動(dòng)將用戶(以及他們的會(huì)話)移到另外一個(gè)應(yīng)用服務(wù)器上去。用戶甚至不知道會(huì)有這種事情的發(fā)生。我們?cè)?jīng)見(jiàn)到過(guò)一些產(chǎn)品系統(tǒng)因?yàn)榇嬖谟诒镜卮a中令人難以忍受的 bug(不是 IBM 的代碼?。┒蝗槐罎⒌那闆r,這這種情況下,上述功能仍然可以運(yùn)行良好。


11. 在 WebSphere 中,使用動(dòng)態(tài)緩存,并使用 WebSphere servlet 緩存機(jī)制.

通過(guò)使用這些功能,系統(tǒng)性能可以得到很大的提高,而開(kāi)銷是很小的。并且不影響編程模型。

通過(guò)緩存來(lái)提高性能的好處是眾所周知的事情。遺憾的是,當(dāng)前的 J2EE 規(guī)范沒(méi)有包括一種用于 servlet/JSP 緩存的機(jī)制。然而,WebSphere 提供了對(duì)頁(yè)面以及片斷緩存的支持,這種支持是通過(guò)其動(dòng)態(tài)緩存功能來(lái)實(shí)現(xiàn)的,并且不需要對(duì)應(yīng)用程序作出任何改變。其緩存的策略是聲明性的,而且其配置是通過(guò) XML 配置描述符來(lái)實(shí)現(xiàn)的。因此,您的應(yīng)用程序不會(huì)受到影響,并保持與 J2EE 規(guī)范的兼容性和移植性,同時(shí)還從 WebSphere 的 servlet 及 JSP 的緩存機(jī)制中得到性能的優(yōu)化。

從 servet 及 JSP 的動(dòng)態(tài)緩存機(jī)制得到的性能的提高是顯而易見(jiàn)的,這取決于應(yīng)用程序的特性。Cox 和 Martin [Cox] 指出對(duì)一個(gè)現(xiàn)有的 RDF(資源描述格式)站點(diǎn)摘要 (RSS)servlet,當(dāng)使用動(dòng)態(tài)緩存時(shí),其性能可以提高 10%。請(qǐng)注意這個(gè)實(shí)驗(yàn)只涉及到一個(gè)簡(jiǎn)單的 servlet,這個(gè)性能的增長(zhǎng)量可能并不能反映一個(gè)復(fù)雜的應(yīng)用程序。

為了更多地提高性能,將 WebSphere servlet/JSP 結(jié)果緩存與 WebSphere 插件 ESI Fragment 處理器、IBM HTTP Server Fast Response Cache Accelerator (FRCA) 和 Edge Server 緩存功能集成在一起。對(duì)于繁重的基于讀取的工作負(fù)荷,通過(guò)使用這些功能可以得到許多額外的好處。


12. 為了提高程序員的工作效率,將 CMP 實(shí)體 bean 作為 O/R 映射的首選解決方案.

通過(guò) WebSphere 框架(readahead、緩存、隔離級(jí)別等)優(yōu)化性能。如果可能,有選擇的應(yīng)用一些模式來(lái)達(dá)到提高性能的目的,例如 Fast-Lane 閱讀器 [Marinescu]。

對(duì)象/關(guān)系(O/R)映射是使用 Java 創(chuàng)建企業(yè)級(jí)的應(yīng)用程序的基礎(chǔ)。幾乎每個(gè) J2EE 應(yīng)用程序都需要一些類型的 O/R 映射。J2EE 廠商提供一種 O/R 映射機(jī)制,這種機(jī)制在不同的廠商間是可移植的,高效的,并且能夠被一些標(biāo)準(zhǔn)及工具很好地支持。這就是 EJB 規(guī)范中的 CMP(容器管理的持久性)部分。

早期的 CMP 實(shí)現(xiàn)以表現(xiàn)不佳及不支持許多 SQL 結(jié)構(gòu)而著稱。然而,隨著 EJB 2.0 及 2.1 規(guī)范的出現(xiàn),以及被一些廠商所采納,并且隨著像 IBM WebSphere Studio Application Developer 的出現(xiàn),這些問(wèn)題已經(jīng)不再是問(wèn)題了。

CMP EJB 組件現(xiàn)在已經(jīng)被廣泛地應(yīng)用于許多高性能的應(yīng)用程序中。WebSphere 包括一些優(yōu)化功能以提高 EJB 組件的性能,優(yōu)化功能包括:對(duì)生命周期的緩存和 read-ahead 能力。這兩者優(yōu)化功能都是配置時(shí)的選項(xiàng),并且不需要對(duì)應(yīng)用程序進(jìn)行修改或者影響可移植性。

處于緩存狀態(tài)的生命周期緩存 CMP 狀態(tài)數(shù)據(jù)并提供基于時(shí)間的無(wú)效性。從處于緩存狀態(tài)的生命周期得到的性能提高可以達(dá)到選項(xiàng) A 的緩存性能,并且仍然可以為您的應(yīng)用程序提供可伸展性。Read-ahead 能力和容器管理的關(guān)系結(jié)合使用。這個(gè)特性通過(guò)在相同的查詢中隨意地檢索相關(guān)的數(shù)據(jù)作為父數(shù)據(jù)而減少與數(shù)據(jù)庫(kù)的交互。如果相關(guān)的數(shù)據(jù)要通過(guò)使用并發(fā)的查詢來(lái)訪問(wèn)的話,這種方法可以得到性能的改進(jìn)。[Gunther]提供了詳細(xì)的描述以及通過(guò)這些特性得到的性能提高的細(xì)節(jié)。

此外,為了完全優(yōu)化您的 EJB 組件,當(dāng)指定隔離級(jí)別時(shí)要特別注意。盡可能使用最低的隔離級(jí)別,并且仍然保持您的數(shù)據(jù)的完整性。較低的隔離級(jí)別可以提供最佳的性能,并且可以降低出現(xiàn)數(shù)據(jù)庫(kù)死鎖的危險(xiǎn)。

這是目前最有爭(zhēng)議的最佳實(shí)踐。已經(jīng)有大量的文章贊揚(yáng) CMP EJB,同樣的貶斥聲也不絕于耳。然而,這里最基本的問(wèn)題是數(shù)據(jù)庫(kù)開(kāi)發(fā)是困難的。當(dāng)您開(kāi)始使用任何持久性解決方案之前,您需要掌握查詢以及數(shù)據(jù)庫(kù)鎖定如何工作這些基礎(chǔ)知識(shí)。如果您選擇使用 CMP EJB,您要確保您已經(jīng)通過(guò)一些書(shū)籍(例如 [Brown] 和 [Barcia])知道如何使用它們。在鎖定及爭(zhēng)用方面有一些微妙的交互難以理解,但是,在您耗費(fèi)一定的時(shí)間及努力后會(huì)將其掌握的。


結(jié)束語(yǔ)

在這個(gè)簡(jiǎn)短的摘要中,我們已經(jīng)向您介紹了 J2EE 中的核心模式和最佳實(shí)踐,這使得 J2EE 開(kāi)發(fā)成為一種可管理的過(guò)程。盡管我們并沒(méi)有給出所有在實(shí)踐中使用這些模式的必要細(xì)節(jié),但是我們希望能夠給您足夠的指點(diǎn)和指導(dǎo),以幫助您決定下一步要做什么。



夢(mèng)幻流星 2008-01-03 14:25 發(fā)表評(píng)論
]]>
中文編碼http://www.aygfsteel.com/isoft/archive/2008/01/03/172440.html夢(mèng)幻流星夢(mèng)幻流星Thu, 03 Jan 2008 05:14:00 GMThttp://www.aygfsteel.com/isoft/archive/2008/01/03/172440.htmlhttp://www.aygfsteel.com/isoft/comments/172440.htmlhttp://www.aygfsteel.com/isoft/archive/2008/01/03/172440.html#Feedback0http://www.aygfsteel.com/isoft/comments/commentRss/172440.htmlhttp://www.aygfsteel.com/isoft/services/trackbacks/172440.html
GB2312:簡(jiǎn)體中文編碼,一個(gè)漢字占用2字節(jié),在大陸是主要編碼方式。當(dāng)文章/網(wǎng)頁(yè)中包含繁體中文、日文、韓文等等時(shí),這些內(nèi)容可能無(wú)法被正確編碼。

BIG5:繁體中文編碼。主要在臺(tái)灣地區(qū)采用。

GBK:支持簡(jiǎn)體及繁體中文,但對(duì)他國(guó)非拉丁字母語(yǔ)言還是有問(wèn)題。

UTF-8:Unicode編碼的一種。Unicode用一些基本的保留字符制定了三套編碼方式,它們分別UTF-8,UTF-16和UTF-32。在UTF-8中,字符是以8位序列來(lái)編碼的,用一個(gè)或幾個(gè)字節(jié)來(lái)表示一個(gè)字符。這種方式的最大好處,是UTF-8保留了ASCII字符的編碼做為它的一部分。UTF-8俗稱“萬(wàn)國(guó)碼”,可以同屏顯示多語(yǔ)種,一個(gè)漢字占用3字節(jié)。為了做到國(guó)際化,網(wǎng)頁(yè)應(yīng)盡可能采用UTF-8編碼。當(dāng)然,處理中文時(shí)http頭也要改成UTF-8編碼的-----加上<meta http-equiv="Content-Type" content="text/html; charset=utf-8">。

夢(mèng)幻流星 2008-01-03 13:14 發(fā)表評(píng)論
]]>
主站蜘蛛池模板: 辽宁省| 康马县| 汶川县| 巴彦县| 海晏县| 新化县| 汉川市| 万山特区| 漳平市| 刚察县| 潜山县| 新化县| 公安县| 博爱县| 沙洋县| 名山县| 克山县| 临沭县| 凌云县| 六枝特区| 沙洋县| 陈巴尔虎旗| 连平县| 瑞昌市| 丰城市| 游戏| 剑川县| 曲阜市| 禹州市| 汉沽区| 涟源市| 西安市| 长汀县| 盈江县| 昔阳县| 孝昌县| 唐海县| 安徽省| 六枝特区| 木兰县| 平江县|