<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

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

    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é)用戶(hù)界面 顯示的代碼(即視圖??通常通過(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)來(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)試。

    類(lèi)似地,我們也經(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è)試您的圖形用戶(hù)界面(GUI)。分層的測(cè)試使測(cè)試及維護(hù)工作變得極其簡(jiǎn)單。

    在過(guò)去的幾年中,在方法學(xué)領(lǐng)域有了 相當(dāng)大的革新,例如新出現(xiàn)的被稱(chēng)為 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í)際上,還有一種被 稱(chēng)為 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ì)話(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] 將 此原則稱(chēng)為移植工作的基本最佳實(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)題的主要原因。類(lèi)似地,要使用 servlet 和 EJB 規(guī)范提供的授權(quán)機(jī)制,并且如果您要偏離這些規(guī)范的話(huà),要確保使用規(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 方法(例如線(xiàn)程或 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)題,在類(lèi)似這樣的情況下,我們建 議當(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)用戶(hù)訪問(wèn)。不要問(wèn)為什么??照著做就是了。?

    在與我們合作的客戶(hù)中,一開(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 廠商那里買(mǎi)來(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)控制以滿(mǎ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)證信息(用戶(hù) 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ì)類(lèi)似地開(kāi)始在容器管理的持久性 EJB 組件之上使用簡(jiǎn)單的會(huì)話(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 中有一種稱(chēng)為 ModelFirst 的過(guò)程,這個(gè) 過(guò)程涉及到首先構(gòu)建域模型作為一種機(jī)制來(lái)組織和實(shí)現(xiàn)用戶(hù)場(chǎng)景。基本說(shuō)來(lái),您要構(gòu)建域模型作為您要實(shí)現(xiàn)的用戶(hù)場(chǎng)景的首要部分,然后在域 模型之上構(gòu)建一個(gè)用戶(hù)界面(UI)作為用戶(hù)場(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ì)話(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à),這往往會(huì)出現(xiàn)災(zāi)難性的后果。

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



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

    當(dāng)使用 EJB 組件時(shí) ,使用一個(gè)會(huì)話(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)銷(xiāo),而且在 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ì)話(huà) Facades 和它包含的整個(gè) EJB 對(duì)于彼此來(lái)說(shuō)都應(yīng)該是本地的,我們建議對(duì)會(huì)話(huà) Facades 后面的實(shí)體 bean 使用本地接口。然而,會(huì)話(huà) Facades 本身的實(shí)現(xiàn)(典型例子如無(wú)狀態(tài)會(huì)話(huà) bean)應(yīng)該設(shè)計(jì)為遠(yuǎn)程接口。

    為了性能的優(yōu)化,可以將一個(gè)本地接口添加到會(huì)話(huà) Facades。這樣做利用了這樣一個(gè)事實(shí):在大多數(shù)情況下(至少在 Web 應(yīng)用程序中),您的 EJB 客戶(hù)端和 EJB 會(huì)共同存在于同一個(gè) Java 虛擬機(jī)(JVM)中。另外一種情況,如果會(huì)話(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ì)話(huà) Facades 中使用遠(yuǎn)程接口(而不是本地接口),您也可以將同樣的會(huì) 話(huà) Facades 在 J2EE 1.4 中以兼容的方式作為 Web 服務(wù)來(lái)配置。這是因?yàn)?JSR 109(J2EE 1.4 中的 Web 服務(wù)部署部分)要求使用無(wú)狀態(tài)會(huì) 話(huà) bean 的遠(yuǎn)程接口作為 EJB Web 服務(wù)和 EJB 實(shí)現(xiàn)的接口。這樣做是值得的,因?yàn)檫@樣做可以為您的業(yè)務(wù)邏輯增加客戶(hù)端類(lèi)型的數(shù)量。

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

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

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

    J2EE 應(yīng)用服務(wù)器為有狀態(tài)會(huì) 話(huà) bean 提供的故障轉(zhuǎn)移(failover)能夠解決一些問(wèn)題,但是有狀態(tài)的解決方案沒(méi)有無(wú)狀態(tài)的解決方案易于擴(kuò)展。例如,在 WebSphere Application Server 中,對(duì)無(wú)狀態(tài)會(huì)話(huà) bean 的請(qǐng)求,是通過(guò)對(duì)部署無(wú)狀態(tài)會(huì)話(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ì)話(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ì)話(huà) bean 方法。任何在處理時(shí)需要 使用的與用戶(hù)相關(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 和其他管理界面的情況下。

    避免使用有狀態(tài)性不只是對(duì) IBM/WebSphere 的建議,這是一個(gè)基本的 J2EE 設(shè)計(jì)原則。

    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 的 話(huà),模塊 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)重的客戶(hù)及商業(yè)糾紛源自不一致的狀態(tài) 。

    我們時(shí)常看到一些客戶(hù)應(yīng)用程序試圖實(shí)現(xiàn)他們自己的解決方案。也許會(huì)通過(guò)應(yīng)用程序的代碼在數(shù)據(jù)庫(kù)更新失敗的時(shí)候 "撤銷(xiāo)"對(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 作為表示層的首選

    只有在需要多種表示輸出類(lèi)型,并且輸出類(lèi)型被一個(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ā)人員容易在視圖中加入"類(lèi)似模型"的行為,而實(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ì)話(huà)持久性。

    HttpSessions 對(duì)于存儲(chǔ)應(yīng)用程序狀態(tài)信息是非常有用的。其 API 易于使用和理解。遺憾的是,開(kāi)發(fā)人員常常遺忘了 HttpSession 的目的----用來(lái)保持暫時(shí)的用戶(hù)狀態(tài)。它不是任意的數(shù)據(jù)緩存。我們已經(jīng) 見(jiàn)到過(guò)太多的系統(tǒng)為每個(gè)用戶(hù)的會(huì)話(huà)放入了大量的數(shù)據(jù)(達(dá)到兆字節(jié))。那好了,如果同時(shí)有 1000 個(gè)登錄系統(tǒng)的用戶(hù),每個(gè)用戶(hù)擁有 1MB 的 會(huì)話(huà)數(shù)據(jù),那么就需要 1G 或者更多的內(nèi)存用于這些會(huì)話(huà)。要使這些 HTTP 會(huì)話(huà)數(shù)據(jù)較小一些,不然的話(huà),您的應(yīng)用程序的性能將會(huì)下降。一 個(gè)大約比較合適的數(shù)據(jù)量應(yīng)該是每個(gè)用戶(hù)的會(huì)話(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à)。由于會(huì)話(huà)是持久性的,進(jìn)行不必要的序列化以及寫(xiě)入數(shù)據(jù)是一種很奢侈的決定。相反地,應(yīng)該使用內(nèi)存中的哈希表 來(lái)緩存數(shù)據(jù),并且在會(huì)話(huà)中保存一個(gè)對(duì)此數(shù)據(jù)進(jìn)行引用的關(guān)鍵字。這樣,如果不能成功登錄到另外的應(yīng)用服務(wù)器的話(huà),就可以重新創(chuàng)建數(shù)據(jù)。

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

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

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

    通 過(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)用程序都需要一些類(lèi)型的 O/R 映射。J2EE 廠商提供一種 O/R 映射機(jī)制,這種機(jī)制在不同的廠商間是可移植的,高效的,并且能夠被一些標(biāo)準(zhǔn)及工具很好地支持。這就是 EJB 規(guī)范中的 CMP(容器管理的持久性)部分。

    早期的 CMP 實(shí)現(xiàn)以表現(xiàn)不佳及不支持許多 SQL 結(jié)構(gòu)而著稱(chēng)。然而,隨著 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ò)在相同的查詢(xún)中隨意地 檢索相關(guān)的數(shù)據(jù)作為父數(shù)據(jù)而減少與數(shù)據(jù)庫(kù)的交互。如果相關(guān)的數(shù)據(jù)要通過(guò)使用并發(fā)的查詢(xún)來(lái)訪問(wèn)的話(huà),這種方法可以得到性能的改進(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)始使用任何持久性解決方案之前,您需要掌握查詢(xún)以及數(shù)據(jù)庫(kù)鎖定如何工作這些基礎(chǔ)知識(shí)。如果您選擇使用 CMP EJB,您要確保您已經(jīng)通過(guò)一些書(shū)籍(例如 [Brown] 和 [Barcia])知道如何使用它們。在鎖定及爭(zhēng)用方面有一些微妙的交互難以理解,但是, 在您耗費(fèi)一定的時(shí)間及努力后會(huì)將其掌握的

    posted on 2006-09-25 13:37 77 閱讀(137) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    <2006年9月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(12)

    隨筆分類(lèi)

    隨筆檔案

    文章分類(lèi)

    文章檔案

    新聞檔案

    相冊(cè)

    API文檔

    java開(kāi)發(fā)與研究

    にほん

    上海房產(chǎn)

    東京生活

    數(shù)據(jù)庫(kù)大全

    編程與開(kāi)發(fā)

    美國(guó)開(kāi)發(fā)生活

    走向管理

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 色妞WWW精品免费视频| 亚洲成无码人在线观看| 女人张腿给男人桶视频免费版| 中文字幕在线免费播放| 亚洲av无码专区首页| 亚洲六月丁香六月婷婷蜜芽| 国产精品亚洲аv无码播放| 国产人成免费视频| 2020久久精品国产免费| 日韩插啊免费视频在线观看 | 国产99视频精品免费视频76| 亚洲乱码在线卡一卡二卡新区| 亚洲人成电影亚洲人成9999网| 亚洲午夜福利精品无码| 国产成人免费片在线视频观看| 欧亚精品一区三区免费| 无人在线直播免费观看| 久久青草免费91观看| 国产线视频精品免费观看视频| 色哟哟国产精品免费观看| 亚洲av成人无码网站…| 亚洲国产成人综合| 亚洲精品在线不卡| 亚洲视频在线观看| 亚洲AV无码久久精品狠狠爱浪潮 | jlzzjlzz亚洲jzjzjz| 亚洲国产一区在线| 亚洲国产精品一区| 亚洲va久久久噜噜噜久久男同| 亚洲热线99精品视频| 综合亚洲伊人午夜网| 伊人婷婷综合缴情亚洲五月| 国产偷国产偷亚洲高清日韩| 中文字幕不卡亚洲 | 亚洲男人电影天堂| 久久精品国产亚洲AV麻豆网站 | 久久免费看黄a级毛片| 99re在线精品视频免费| 一区二区三区在线免费看 | 亚洲国产精品久久网午夜| 亚洲日韩国产精品无码av|