隨筆-18  評(píng)論-20  文章-0  trackbacks-0

                2006 年 11 月發(fā)布   最近,我所工作的機(jī)構(gòu)(威斯康星大學(xué)伊奧克萊爾分校)將一個(gè)用 Cobol 編寫(xiě)且運(yùn)行在 Unisys 大型機(jī)上的老舊系統(tǒng)的一部分移植到了 Java/J2EE 環(huán)境中。 我們的 IT 小組主要使用開(kāi)放源代碼工具(包括 Eclipse、Tomcat 和 Spring)來(lái)編寫(xiě)應(yīng)用程序。但是,許可方式上的更改使我們可以考慮 Oracle 工具,因此我們使用 Oracle JDeveloper 10g 和 Oracle 應(yīng)用程序開(kāi)發(fā)框架 (ADF) 編寫(xiě)了一個(gè)應(yīng)用程序來(lái)測(cè)試開(kāi)發(fā)模型。本文將對(duì)該應(yīng)用程序進(jìn)行描述,從而快速而詳細(xì)地介紹如何使用 Oracle ADF 進(jìn)行 UI 開(kāi)發(fā)。(有關(guān)更進(jìn)一步的技術(shù)信息,請(qǐng)參閱 Oracle 技術(shù)網(wǎng)上的 Oracle ADF 教程和 Oracle ADF 開(kāi)發(fā)人員指南、Oracle ACE Steve Muench 在 Oracle 雜志上內(nèi)容精彩的 ADF 專(zhuān)欄以及 Oracle JDeveloper 論壇中的評(píng)論。)

              在本文中,我不會(huì)描述構(gòu)建應(yīng)用程序所需的每一個(gè)步驟,但希望這里的信息足以使您作出自己的決策。本文假設(shè)您十分了解 Java,熟悉 Eclipse 或 JDeveloper,并具有普通編程知識(shí)。(我沒(méi)有在每個(gè)步驟后提醒您 Save All,但該步驟不應(yīng)省略。)

              改變給定體系結(jié)構(gòu)和開(kāi)發(fā)模型總是很困難,因此我將首先提供一些背景知識(shí),以說(shuō)明 JDeveloper 和 ADF 的價(jià)值所在,從而證明這種轉(zhuǎn)變的有利性。我還會(huì)在一個(gè)單獨(dú)的部分中提供一些“提示與技巧”。

          背景

              當(dāng)前應(yīng)用程序直接使用了 Java (JDK 1.5)、Spring(MVC、Web Flow、JDBC 模板)和 jsp 頁(yè)面。數(shù)據(jù)也復(fù)制到了一個(gè) Oracle 數(shù)據(jù)庫(kù) 10g 第 2 版數(shù)據(jù)庫(kù)中。盡管我們了解如何使用 JBoss Hibernate 作為對(duì)象關(guān)系映射 (ORM) 工具,但我們的數(shù)據(jù)訪問(wèn)既不復(fù)雜也不是動(dòng)態(tài)的,而且 Spring JDBC 模板已經(jīng)充分滿(mǎn)足了我們的需要。

              由于我們?cè)谏a(chǎn)中使用的是 Oracle 數(shù)據(jù)庫(kù) 10g 第 2 版,因此在基于 Windows 的試用版中使用 Oracle 數(shù)據(jù)庫(kù) 10g 快捷版 (XE)(Oracle 數(shù)據(jù)庫(kù)的免費(fèi)入門(mén)級(jí)版本)順理成章,我們希望能夠在其中輕松地訪問(wèn)數(shù)據(jù)。在決定使用 Oracle 的 TopLink ORM 工具后使用 Oracle 數(shù)據(jù)庫(kù)也很有意義,這樣我們就可以輕松地將映射移植到其他數(shù)據(jù)源(如果決定使用測(cè)試用例作為生產(chǎn)應(yīng)用程序的基礎(chǔ))。我們對(duì) XE 所作的唯一更改就是在系統(tǒng)主頁(yè)中更改系統(tǒng)全局區(qū) (SGA),以減少它使用的內(nèi)存。

              我們選擇的 TopLink 比預(yù)期的效果還要好,因?yàn)樗橄罅嗽S多使用 JDBC 甚至接口(如 Spring 的 JDBC 模板)的繁復(fù)的詳細(xì)信息。(Dustin Marx 在 OTN 上的“在 JDBC 編程中添加一些 Spring 代碼”一文中提供了一個(gè)優(yōu)秀示例,該示例使用 JDBC 模板,無(wú)需配置復(fù)雜的 Spring 環(huán)境。)JBoss Hibernate 是一個(gè)出色的 ORM 工具,但在端到端 ADF 解決方案中集成 TopLink 映射的能力也令人大開(kāi)眼界并且非常高效。

              根據(jù) Oracle 的建議,我們創(chuàng)建了一個(gè) EJB 會(huì)話 Bean 來(lái)封裝對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)。這只有在應(yīng)用程序和數(shù)據(jù)庫(kù)之間有一個(gè)層(以便在其中根據(jù)需要使用業(yè)務(wù)邏輯)的情況下才有意義。迄今為止,我們的應(yīng)用程序中沒(méi)有任何需要狀態(tài)的事物,而使用 Session Facade 設(shè)計(jì)模式時(shí)通常會(huì)需要狀態(tài)。

              使用 ADF 的一個(gè)標(biāo)準(zhǔn)步驟是創(chuàng)建一組能夠訪問(wèn)數(shù)據(jù)信息庫(kù)的數(shù)據(jù)控件,我們將遵循該原則。在不需要業(yè)務(wù)邏輯的情況下(通常是查詢(xún),有時(shí)是更新和刪除),通過(guò) UI 控件直接訪問(wèn)信息十分高效。在較復(fù)雜的情況下,可以通過(guò)在會(huì)話 Bean 方法中包含業(yè)務(wù)規(guī)則實(shí)現(xiàn)來(lái)應(yīng)用業(yè)務(wù)規(guī)則。(ADF 開(kāi)發(fā)人員指南第 1.1 章很好地說(shuō)明了 ADF 和 JSF 如何協(xié)同工作以提供高效的開(kāi)發(fā)環(huán)境。)

              我們還使用標(biāo)準(zhǔn)的 JSF 導(dǎo)航創(chuàng)建了一組 jspx 文件。盡管我們熟悉 Struts,但這里并不使用它。我們將使用 jspx 文件,因?yàn)檫@是 Oracle 建議的做法。

              JDeveloper 10.1.3 在整個(gè)項(xiàng)目中充當(dāng) IDE。這可能很明顯,但忘了提醒您它無(wú)法識(shí)別 JDeveloper 在構(gòu)建 ADF 應(yīng)用程序的過(guò)程中所扮演的基本角色。JDeveloper 是一個(gè) Java 開(kāi)發(fā)工具,但它還可以為您提供對(duì) TopLink、ADF UI 及數(shù)據(jù)訪問(wèn)控件的功能、JSF 功能以及 XML 和 JSP 文件的端到端訪問(wèn),還可以提供測(cè)試部署和數(shù)據(jù)庫(kù)訪問(wèn)環(huán)境。

          同時(shí),當(dāng)您在 JDeveloper 中編輯文件時(shí),系統(tǒng)會(huì)自動(dòng)在窗口中調(diào)整更改,您在使用 Eclipse 和其他 IDE 時(shí)通常看不到這些更改。這些更改提供了各種視圖和編輯方法,因此學(xué)習(xí)使用 JDeveloper 的豐富功能是有一定難度的。您需要了解在哪里雙擊、何時(shí)使用 StrUCture 和 Data Control 窗口、何時(shí)在屬性編輯器中設(shè)置值,以及(偶爾)何時(shí)使用 Source 窗口并編寫(xiě) Java 或 JSP 代碼。

           

          項(xiàng)目

              我們的項(xiàng)目是一個(gè)簡(jiǎn)單的學(xué)生會(huì)銀行帳戶(hù)。所需的基本功能是輸入和編輯支出與存款。該項(xiàng)目基本上是 ADF 教程中描述的功能子集,因此熟悉 SRDemo 的人可以識(shí)別出其中許多元素。SRDemo 是一個(gè)完整的示例應(yīng)用程序,您可以通過(guò) JDeveloper 的 Help 下拉菜單中的“檢查更新”機(jī)制下載該應(yīng)用程序。該程序包含完整的源代碼,ADF 開(kāi)發(fā)人員指南使用它來(lái)說(shuō)明如何使用 ADF 進(jìn)行開(kāi)發(fā)。

          第 0 階段:構(gòu)建應(yīng)用程序的初始設(shè)置

          第 1 步:使用 JSF、EJB 和 TopLink 模板創(chuàng)建一個(gè)新的 Web 應(yīng)用程序。(另請(qǐng)參閱 Oracle ADF 教程 1-10。)選擇模板并不重要,所有選項(xiàng)都可用,即使它們最初沒(méi)有被選中。通過(guò)該模板,創(chuàng)建標(biāo)準(zhǔn)的 Model 和 ViewController 項(xiàng)目,從而保留應(yīng)用程序的前端和后端。您應(yīng)該設(shè)置默認(rèn)程序包名稱(chēng),因?yàn)樵趧?chuàng)建 Java 類(lèi)時(shí),該名稱(chēng)可在 JDeveloper 中用作默認(rèn)名稱(chēng)。

          第 2 步:設(shè)置數(shù)據(jù)庫(kù)。盡管我們可以嘗試使用 New Gallery 的 Database Tier 中的 Offline Database Objects,但我們先前已經(jīng)創(chuàng)建了所需的 SQL,以使用一組表(3 個(gè))創(chuàng)建模式。我們登錄到 XE Web 界面,并使用腳本(您可以在 SQL Command 頁(yè)面上的引用中找到該腳本)創(chuàng)建了用戶(hù)和表。為這些表指定主鍵很重要,這樣至少可以使 TopLink 具有足夠的信息來(lái)生成更復(fù)雜的映射:
          • Account 用于保存有關(guān)帳戶(hù)的基本信息。
          • Details 用于保存所有帳戶(hù)的交易信息。
          • Manager 是與帳戶(hù)關(guān)聯(lián)的個(gè)人列表。

              為了填充表,我們編寫(xiě)了一個(gè)使用 DBUnit 的 Java 應(yīng)用程序,并使用引用中的數(shù)據(jù)集創(chuàng)建了一個(gè) CampusAccounts.xml 文件。如果愿意,您可以克隆 XML 元素來(lái)擴(kuò)展數(shù)據(jù)集。由于這是應(yīng)用程序中的第一個(gè) Java 類(lèi),我們選擇在 Model 項(xiàng)目中創(chuàng)建一個(gè) New/General/Java 類(lèi),以便創(chuàng)建程序包。然后,將類(lèi)的主體復(fù)制并粘貼到新創(chuàng)建的類(lèi)中。如果類(lèi)已經(jīng)創(chuàng)建,我們將選擇 File/Import 選項(xiàng)將 Java Source 復(fù)制到 Model 項(xiàng)目中。

          public static void main(String[] argv) throws Exception {
          Class driverClass = Class.forName("oracle.jdbc.OracleDriver");
          Connection jdbcConnection =
          DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE",
          "CampusAccounts", "xxxxxx");
          IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);
          IDataSet dataSet = new FlatXmlDataSet(new File("c:\\CampusAccounts.xml"));
          try {
          DatabaseOperation.CLEAN_INSERT.execute(connection, dataSet);
          }
          finally {
          connection.close();
          }
          }
          
              主要片段的主體演示了利用 DBUnit 功能是多么簡(jiǎn)單。它顯示了用于連接到 Oracle Database XE 數(shù)據(jù)庫(kù)的 URL,這也是標(biāo)準(zhǔn) Oracle JDBC 驅(qū)動(dòng)程序的名稱(chēng)。

           

              但是,您需要在項(xiàng)目中添加一個(gè)來(lái)自 DBUnit 的 jar 文件和一個(gè)庫(kù),以編譯代碼。首先,您需要從 DBUnit zip 文件中提取 jar 文件。從 Model 項(xiàng)目的 Properties 中,選擇 Libraries/Add Jar,然后將 DBUnit jar 文件添加到項(xiàng)目中。通過(guò)從 Model 屬性中選擇 Libraries/Add Library,您可以添加 Oracle JDBC 庫(kù),該庫(kù)包含 Oracle JDBC 驅(qū)動(dòng)程序。一旦 jar 文件和庫(kù)可用,就可以使用 JDeveloper 的 Alt-Enter 代碼完成選項(xiàng)自動(dòng)添加所需的導(dǎo)入。(確保導(dǎo)入了 java.sql.Connection。)要運(yùn)行該 Java 應(yīng)用程序,請(qǐng)?jiān)?Applications 窗口中選擇該文件和綠色箭頭。一旦連接創(chuàng)建(下一步),就簡(jiǎn)單多了。

          第 1 階段:創(chuàng)建初始模型

          第 3 步:在創(chuàng)建模式之后創(chuàng)建 TopLink 對(duì)象關(guān)系映射。(另請(qǐng)參閱 Oracle ADF 教程 1-8 和 2-2。)在使用 TopLink 之前需要?jiǎng)?chuàng)建一個(gè)連接。選擇 View/Connection Navigator(如果窗口未打開(kāi))。 選擇 New Connection on Database,指定一個(gè)名稱(chēng),并確保選擇了 Oracle (JDBC) 類(lèi)型。輸入模式名稱(chēng)和密碼。如果您使用的是 XE,則將 sid 更改為 XE。測(cè)試連接以確保成功。

          返回到 Applications 窗口,右鍵單擊 Model,然后從 Tables 中選擇 New/Business Tier/TopLink/Java Objects。為映射命名并更改連接(如果需要)。查詢(xún)第 2 步中的模式,并加入所有表。檢查程序包名稱(chēng)。系統(tǒng)在您指定的程序包中創(chuàng)建了一組數(shù)據(jù)訪問(wèn)對(duì)象 (DAO),每個(gè)表一個(gè)。通過(guò)打開(kāi) Model 的 TopLink 文件夾中的映射,您可以看到每個(gè)模式表的域映射。如果您在 Structure 窗口中選擇了一個(gè)表,Map 窗口就會(huì)轉(zhuǎn)而顯示映射的不同視圖。嘗試這個(gè)操作是種不錯(cuò)的做法,因?yàn)樗梢宰屇煜?JDeveloper 如何在窗口中調(diào)整更改。

           

              在 Detail 映射中選擇 Queries 選項(xiàng)卡,您會(huì)注意到 TopLink 為每個(gè)表自動(dòng)創(chuàng)建了一個(gè) findAll 查詢(xún)。要添加一個(gè)簡(jiǎn)單查詢(xún)(將得到表行的較小子集),請(qǐng)?jiān)?Named Queries 中選擇 Add,并為查詢(xún)命名。然后,在 Parameters 窗口中選擇 Add,設(shè)置參數(shù)類(lèi)型(通過(guò)指定完全限定的 Java 類(lèi)名,如 java.lang.Integer),然后單擊 Name 列更改參數(shù)名。針對(duì)您需要指定的每個(gè)參數(shù)選擇 Add。在我們的示例中,已經(jīng)將 findAccountTransactionsByAccount() 添加到 Detail 映射以根據(jù)帳號(hào)檢索特定帳戶(hù)的所有行,并將 findOneTransaction() 添加到 Detail 映射以檢索特定交易,交易通過(guò)帳號(hào)(序列號(hào)對(duì))區(qū)分。findOneTransaction() 是一個(gè) ReadObjectQuery,而 findAccountTransactionsByAccount() 是一個(gè) ReadAllQuery:

          了解 Oracle ADF:入門(mén)示例(圖一) 點(diǎn)擊查看大圖

              如果您選擇 Format 選項(xiàng)卡,可以使用 TopLink 編輯器創(chuàng)建查詢(xún)或輸入查詢(xún)字符串。要使用查詢(xún)表達(dá)式創(chuàng)建器,請(qǐng)選擇 EXPression/Edit。在創(chuàng)建器中,選擇 Add,并將 Second Argument 更改為剛剛創(chuàng)建的參數(shù)。如果有其他參數(shù),則再次選擇 Add,創(chuàng)建器將自動(dòng)創(chuàng)建一個(gè) AND 子句:

          了解 Oracle ADF:入門(mén)示例(圖二)

              系統(tǒng)會(huì)創(chuàng)建一個(gè)默認(rèn)的 TopLink 會(huì)話,對(duì)應(yīng)于所創(chuàng)建的連接。您可以打開(kāi) sessions.xml 文件,并通過(guò)在 Structure 窗口中選擇 Default 來(lái)查看默認(rèn)值。更改諸如日志記錄之類(lèi)的選項(xiàng)非常簡(jiǎn)單。

          第 4 步:創(chuàng)建 EJB 會(huì)話。(另請(qǐng)參閱 Oracle ADF 教程 2-14。)對(duì)于 Model,選擇 New/Business Tier/EJB/Session Bean。無(wú)需更改默認(rèn)設(shè)置,除非不需要遠(yuǎn)程接口。如果查看創(chuàng)建的 Bean,您將看到系統(tǒng)已經(jīng)創(chuàng)建了可用于表行的 merge、persist、refresh 和 remove 方法。您還將看到,系統(tǒng)已經(jīng)為您創(chuàng)建的每個(gè)命名查詢(xún)創(chuàng)建了一個(gè)方法。EJB 向?qū)ё詣?dòng)生成的 Java 代碼會(huì)在該方法內(nèi)創(chuàng)建一個(gè)會(huì)話事務(wù)。當(dāng)然,您不必編輯該代碼,并且現(xiàn)有方法的文本也不會(huì)被覆蓋(如果在重新生成 Bean 時(shí),它仍然是您的首選項(xiàng))。

          第 5 步:創(chuàng)建 ADF 數(shù)據(jù)控件。(另請(qǐng)參閱 Oracle ADF 教程 2-16。)ADF 數(shù)據(jù)控件為前面步驟中創(chuàng)建的會(huì)話 Bean 和 DAO 提供了一個(gè)接口。在創(chuàng)建用于訪問(wèn)數(shù)據(jù)庫(kù)的用戶(hù)界面控件時(shí),數(shù)據(jù)控件會(huì)提供“粘合劑”。如果您從 View 菜單中打開(kāi) Data Control 選項(xiàng)板,應(yīng)該看到它是空白的。右鍵單擊會(huì)話 Bean 并選擇最后一項(xiàng):Create Data Control。Data Control 選項(xiàng)板將填充有以下內(nèi)容:

          了解 Oracle ADF:入門(mén)示例(圖三)
          為項(xiàng)目創(chuàng)建可用后端的初步工作就完成了。盡管諸如 ADF 控件之類(lèi)的產(chǎn)物的實(shí)際值在構(gòu)建某些頁(yè)面時(shí)才會(huì)顯現(xiàn)出來(lái),但所花費(fèi)的精力之少仍然令人驚奇。

           

          第 2 階段:創(chuàng)建初始視圖

          第 6 步:使用初始的 faces-config.xml 文件。在首次打開(kāi)應(yīng)用程序時(shí),打開(kāi) Web Content/WEB-INF 文件夾和所創(chuàng)建的 faces-config.xml 文件。如果由于某種原因尚未創(chuàng)建配置文件,則右鍵單擊 ViewController 項(xiàng)目并選擇 New/Web Tier/JSF/JSF Page Flow & Configuration。faces-config.xml 的默認(rèn)名稱(chēng)是正確的。如果您選擇 Overview 選項(xiàng)卡,將看到配置文件的空白視圖:

          了解 Oracle ADF:入門(mén)示例(圖四) 點(diǎn)擊查看大圖


              在 JSF 應(yīng)用程序中,該視圖是進(jìn)入中央配置文件的重要窗口。除了一組描述用戶(hù)如何在 Faces 應(yīng)用程序中從一個(gè)頁(yè)面轉(zhuǎn)換到另一個(gè)頁(yè)面的 XML 元素以外,還有用于 Bean 的元素,這些 Bean 包括在用戶(hù)與界面控件(輔助 Bean)交互時(shí)調(diào)用其方法的 Bean,以及用于存儲(chǔ)長(zhǎng)久信息(如用戶(hù)狀態(tài))的 Bean。

          第 7 步:創(chuàng)建初始導(dǎo)航圖和對(duì)應(yīng)頁(yè)面。(另請(qǐng)參閱 Oracle ADF 教程 3-2。)現(xiàn)在,需要一組初始頁(yè)面(主要基于 SRDemo 中使用的頁(yè)面模板),以及描述用戶(hù)如何從一個(gè)頁(yè)面轉(zhuǎn)移到另一個(gè)頁(yè)面的初始導(dǎo)航規(guī)則。選擇針對(duì) faces-confix.xml 文件的 Diagram 選項(xiàng)卡,確保 Configuration 選項(xiàng)板處于開(kāi)啟狀態(tài),然后將 JSF 頁(yè)面拖到配置圖上。此時(shí),您已經(jīng)在配置文件(而不是頁(yè)面)中創(chuàng)建了一個(gè)導(dǎo)航元素。

              雙擊無(wú)標(biāo)題頁(yè)面圖標(biāo),以啟動(dòng)一個(gè)將實(shí)際創(chuàng)建文件的向?qū)А⒚Q(chēng)更改為 index;將文件后綴更改為 jspx(Oracle 的普遍建議);確保系統(tǒng)沒(méi)有自動(dòng)公開(kāi)該頁(yè)面的 UI 組件;然后移動(dòng) ADF Faces 組件、JSF 內(nèi)核、ADF Faces 和 JSF Html 庫(kù)。選擇您喜歡的 HTML 版本 — 我們?cè)?4.0.1 Transitional 版上運(yùn)行良好。

              index.jspx 將重定向到應(yīng)用程序的實(shí)際第一頁(yè),這是創(chuàng)建 Web 應(yīng)用程序的標(biāo)準(zhǔn)做法。這可能會(huì)創(chuàng)造一個(gè)糟糕的先例,但可以在 Source 窗口中查找 index.jspx,并用以下 scriptlet 替換 f:view 標(biāo)記。注意,您要?jiǎng)?chuàng)建一個(gè)目錄結(jié)構(gòu)來(lái)管理頁(yè)面 — 管理涵蓋所有應(yīng)用程序的所有頁(yè)面,而名為 campusaccounts 的子目錄將用于保存該項(xiàng)目的所有頁(yè)面。將 scriptlet 插入 index.jspx 文件之后,您就可以安全地保存并關(guān)閉該文件了。

          <jsp:scriptlet>
          response.sendRedirect("faces/administration/welcome.jspx");
          </jsp:scriptlet>
          

              從 Component 選項(xiàng)板中,將另一個(gè) JSF 頁(yè)拖到 faces-config.xml 圖上。雙擊圖標(biāo)打開(kāi)向?qū)В栽O(shè)置其 jsp 頁(yè)面。將名稱(chēng)更改為 welcome,將文件類(lèi)型更改為 jspx — 并確保設(shè)置目錄,以創(chuàng)建您希望創(chuàng)建的任何子目錄結(jié)構(gòu)。例如,在本案例中,我們將目錄設(shè)置為 ../public_html/administration,以便對(duì)應(yīng)于 sendRedirect。移動(dòng)選項(xiàng)應(yīng)該與創(chuàng)建 index.jspx 時(shí)所使用的移動(dòng)選項(xiàng)相同,HTML 版本也應(yīng)該相同。

              將內(nèi)容添加到 JSP 頁(yè)面實(shí)際上就是在 Diagram、Property Editor 和 Structure 窗口之間切換。有時(shí),您甚至可以通過(guò) Source 窗口編輯頁(yè)面。在 Structure 窗口中,打開(kāi) faces 視圖元素并刪除默認(rèn)的 f:view 標(biāo)記,以便能夠使用包含面板頁(yè)的以下文本替換它。面板頁(yè)是一個(gè)復(fù)雜的 UI 控件,它包含頁(yè)眉、頁(yè)腳、用于選擇幫助的全局控件以及版權(quán)部分等內(nèi)容。在使用該頁(yè)時(shí),您將發(fā)現(xiàn)使用標(biāo)準(zhǔn)界面組件創(chuàng)建復(fù)雜頁(yè)面是多么輕松。粘貼文本的最簡(jiǎn)單方法就是切換到 Source 窗口,并確保游標(biāo)跟隨文件開(kāi)頭的三個(gè) jsp 標(biāo)記。

          <f:view>
          <f:loadBundle basename="edu.uwec.financial.resources.UIResources"
          var="res"/>
          <af:document title="#{res['uacct.campusAccounts.title']}"
          initialFocusId="start">
          <af:form>
          <af:panelPage>
          <!-- Page Content End -->
          <f:facet name="branding">
          <af:panelHorizontal>
          <af:objectImage source="/images/banner.jpg"/>
          </af:panelHorizontal>
          </f:facet>
          <f:facet name="menu1">
          <af:menuTabs var="menuTab" value="http://www.QQread.com/oracle/2006/12/#{menuModel.model}">
          <f:facet name="nodeStamp">
          <af:commandMenuItem text="#{menuTab.label}"
          action="#{menuTab.getOutcome}"
          rendered="#{menuTab.shown and menuTab.type=='default'}"
          disabled="#{menuTab.readOnly}"/>
          </f:facet>
          </af:menuTabs>
          </f:facet>
          <f:facet name="menu2">
          <af:menuBar/>
          </f:facet>
          <f:facet name="menuGlobal">
          <af:menuButtons>
          <af:commandMenuItem text="#{res['uacct.menu.logout']}"
          action="GlobalLogout" immediate="true"
          icon="images/blafIcons/logout.gif"/>
          <af:commandMenuItem text="#{res['uacct.menu.help']}"
          action="GlobalHelp" immediate="true"
          icon="../images/blafIcons/help.gif"/>
          </af:menuButtons>
          </f:facet>
          <f:facet name="messages">
          <af:messages/>
          </f:facet>
          <f:facet name="appCopyright">
          <!--Copyright msg-->
          <h:panelGroup>
          <af:objectSpacer width="10" height="10" id="objectSpacer4"/>
          <af:panelHorizontal halign="center">
          <af:outputText value="#{res['uacct.copyright']}"/>
          </af:panelHorizontal>
          </h:panelGroup>
          </f:facet>
          <f:facet name="appAbout">
          <!-- The About this Application Link-->
          <af:panelHorizontal halign="center">
          <af:commandLink text="#{res['uacct.about']}" action="GlobalAbout"
          immediate="true"/>
          </af:panelHorizontal>
          </f:facet>
          <f:facet name="infoUser">
          <!-- Show the Logged in user -->
          <h:outputFormat value="#{res['uacct.connectedUser']}"
          rendered="#{userInfo.authenticated}" escape="false">
          <f:param value="#{userInfo.userName}"/>
          </h:outputFormat>
          </f:facet>
          </af:panelPage>
          </af:form>
          </af:document>
          </f:view>
          您將注意到 Structure 窗口中報(bào)告了錯(cuò)誤,這些錯(cuò)誤將在下一步中解決。
          

           

           

          第 8 步:不擇手段地占為己有。(另請(qǐng)參閱 Oracle ADF 教程 4-2。)我們建議從 SRDemo 中借用幾個(gè)文件,以使您快速了解如何創(chuàng)建應(yīng)用程序。由于使用資源文件很簡(jiǎn)單,我們決定始終使用它來(lái)標(biāo)記所有 UI 組件,甚至是按鈕上很明顯的標(biāo)記(如 Submit)。 我們預(yù)計(jì)大部分內(nèi)聯(lián)網(wǎng)應(yīng)用程序都沒(méi)有國(guó)際化需求,但這是一個(gè)設(shè)計(jì)決策,它創(chuàng)造了一個(gè)較好的先例。我們還建議借用幾個(gè)類(lèi)(如 ADFUtils 和 JSFUtils),因?yàn)樗鼈兎浅S杏谩H绻仨毻ㄟ^(guò) Java 代碼訪問(wèn) JSF 和 ADF 框架中存儲(chǔ)的變量,則有一點(diǎn)麻煩。一旦您了解 Oracle 使用的綁定和命名標(biāo)準(zhǔn),就會(huì)覺(jué)得這些實(shí)用程序類(lèi)十分簡(jiǎn)單,示例如下。導(dǎo)入圖像文件夾也很有意義,因?yàn)樗藶g覽器外觀 (BLAF) 文件夾和界面中使用的幾個(gè)圖標(biāo)。

              我們導(dǎo)入文件的方法是選擇 ViewController 項(xiàng)目,選擇 File/Import/Java Source,然后瀏覽到 SRDemo 項(xiàng)目中的類(lèi)。SRDemo 中的完整路徑與 mywork 位于同一級(jí)別 — 參見(jiàn) samples/SRDemo/UserInterface/src/oracle/srdemo/view。將 ADFUtils 和 JSFUtils 添加到 util,然后將它們復(fù)制到程序包結(jié)構(gòu)中(我們?cè)?src 文件夾中使用的是 edu/uwec/financial/util);將 ResourceAdapter 和 UIResources 添加到 resources(我們使用的是 edu/uwec/financial/resources);然后通過(guò)菜單(我們使用的是 edu/uwec/financial/menu)添加 MenuItem、MenuModelAdapter 和 MenuTreeModelAdapter。注意,當(dāng)您導(dǎo)入 Java 文件后,可能需要修改程序包名稱(chēng)以匹配目錄結(jié)構(gòu)。

              您可以導(dǎo)入一些標(biāo)準(zhǔn)圖像,方法是選擇 File/Import/Web Source,瀏覽到 UserInterface/public_html,然后選擇圖像 — 確保將 images 文件夾復(fù)制到 public_html 文件夾中。這個(gè)步驟有一點(diǎn)麻煩,因?yàn)樵跒g覽時(shí)很容易過(guò)于深入:

          了解 Oracle ADF:入門(mén)示例(圖五)

              此時(shí),jspx 文件中的錯(cuò)誤應(yīng)該已經(jīng)消失,但可能需要修正面板頁(yè)上的元素,例如,要包含在 branding 控件 (facet) 中的所有圖像。如果您要將某個(gè)圖像包含在頁(yè)面頂部,應(yīng)將其作為 WebContent 導(dǎo)入 ViewController 項(xiàng)目的 images 文件夾。在 Structure 窗口的面板頁(yè)中,選擇 branding/panelHorizontal,然后在 Properties 窗口中重設(shè)其對(duì)象圖像。您還應(yīng)該確保頁(yè)面上的圖標(biāo)(如 logout 和 help)具有正確的 Source 屬性。在 Property 窗口的 Source 屬性中選擇每個(gè)圖標(biāo)和 ... 按鈕,并在 Source 窗口中查找圖像。您需要在 welcome.jspx 中編輯諸如 loadBundle 標(biāo)記之類(lèi)的項(xiàng),以便與程序包結(jié)構(gòu)相匹配。

          示例屬性文件項(xiàng)與 welcome.jspx 中引用的屬性不對(duì)應(yīng)。以下是我們添加的初始名/值對(duì)集。

          uacct.about=About MyBlugold
          uacct.copyright=\u00a9 2006 University of Wisconsin - Eau Claire
          uacct.menu.help=Help
          uacct.menu.logout=Logout
          uacct.menu.campusAccounts=Campus Accounts
          uacct.campusAccounts.title=Campus Accounts
          uacct.connectedUser=Logged in as <b>{0}</b>
          

              ADFUtils 類(lèi)沒(méi)有編譯,因?yàn)樗枰粋€(gè)庫(kù)。在 ViewController 項(xiàng)目上打開(kāi) Properties,然后添加 ADF Model Runtime 庫(kù)。

              如果您選擇 index.jspx 并運(yùn)行應(yīng)用程序(選擇綠色箭頭),應(yīng)該看到與以下類(lèi)似的內(nèi)容 — 當(dāng)然,還包含標(biāo)幟。

          實(shí)際上,歡迎頁(yè)面將為我們提供更加“全局”的按鈕(如 Help 和 Logout),因?yàn)槟梢詮娜魏雾?yè)面選擇它們。

           

          第 9 步:創(chuàng)建菜單。這一部分將介紹從 SRDemo 中借用以創(chuàng)建菜單的代碼,如果您希望該簡(jiǎn)介簡(jiǎn)短些,可以跳過(guò)該部分。


              管理頂層菜單所需的標(biāo)記和 Java 代碼已添加至項(xiàng)目,但需要在 faces-config.xml 文件中添加相關(guān)項(xiàng)以將其連接。一般而言,JDeveloper 會(huì)提供所需項(xiàng),您也可以打開(kāi) faces-config.xml 文件并從 Overview 選項(xiàng)卡添加 Bean 定義。另一種方法是通過(guò) Source 窗口將以下示例復(fù)制到文件,從而使用托管 Bean 元素作為項(xiàng)模型以獲得類(lèi)似的 Bean(如 Bean 注釋標(biāo)記中所述)。

          <!-- Global menu tab for logout (we also added a tab for help -->
          <managed-bean>
          <managed-bean-name>menuItem_GlobalLogout</managed-bean-name>
          <managed-bean-class>edu.uwec.financial.menu.MenuItem</managed-bean-class>
          <managed-bean-scope>session</managed-bean-scope>
          <managed-property>
          <property-name>label</property-name>
          <value>#{resources['uacct.menu.logout']}</value>
          </managed-property>
          <managed-property>
          <property-name>icon</property-name>
          <value>/images/logout.gif</value>
          </managed-property>
          <managed-property>
          <property-name>type</property-name>
          <value>global</value>
          </managed-property>
          <managed-property>
          <property-name>viewId</property-name>
          <value>/administration/Logout.jsp</value>
          </managed-property>
          <managed-property>
          <property-name>outcome</property-name>
          <value>GlobalLogout</value>
          </managed-property>
          </managed-bean>
          <!-- Campus Accounts menu tab (we also added tabs for Purchasing and Accounting) -->
          <managed-bean>
          <managed-bean-name>menuItem_CampusAccounts</managed-bean-name>
          <managed-bean-class>edu.uwec.financial.menu.MenuItem</managed-bean-class>
          <managed-bean-scope>session</managed-bean-scope>
          <managed-property>
          <property-name>label</property-name>
          <value>#{resources['uacct.menu.campusAccounts']}</value>
          </managed-property>
          <managed-property>
          <property-name>viewId</property-name>
          <value>/administration/campusaccounts/CampusAccounts.jspx</value>
          </managed-property>
          <managed-property>
          <property-name>outcome</property-name>
          <value>GlobalCampusAccounts</value>
          </managed-property>
          </managed-bean>
          <!-- create the main menu menuModel bean, only one needed -->
          <managed-bean>
          <managed-bean-name>menuModel</managed-bean-name>
          <managed-bean-class>edu.uwec.financial.menu.MenuModelAdapter</managed-bean-class>
          <managed-bean-scope>session</managed-bean-scope>
          <managed-property>
          <property-name>viewIdProperty</property-name>
          <value>viewId</value>
          </managed-property>
          <managed-property>
          <property-name>instance</property-name>
          <value>#{menuTreeModel.model}</value>
          </managed-property>
          </managed-bean>
          <!-- create the main menu menuTreeModel bean, only one needed -->
          <managed-bean>
          <managed-bean-name>menuTreeModel</managed-bean-name>
          <managed-bean-class>edu.uwec.financial.menu.MenuTreeModelAdapter</managed-bean-class>
          <managed-bean-scope>session</managed-bean-scope>
          <managed-property>
          <property-name>childProperty</property-name>
          <value>children</value>
          </managed-property>
          <managed-property>
          <property-name>listInstance</property-name>
          <list-entries>
          <value-class>edu.uwec.financial.menu.MenuItem</value-class>
          <value>#{menuItem_GlobalLogout}</value>
          <value>#{menuItem_GlobalHelp}</value>
          <value>#{menuItem_CampusAccounts}</value>
          <value>#{menuItem_Purchasing}</value>
          <value>#{menuItem_Accounting}</value>
          </list-entries>
          </managed-property>
          </managed-bean>
          <managed-bean>
          <managed-bean-name>resources</managed-bean-name>
          <managed-bean-class>edu.uwec.financial.resources.ResourceAdapter</managed-bean-class>
          <managed-bean-scope>application</managed-bean-scope>
          </managed-bean>
          


          由于這些 Bean 將引用資源文件,因此 faces-config.xml 文件還需要一個(gè)為其定義的項(xiàng)。在應(yīng)用程序標(biāo)記中,除了添加 default-render-kit 以外,還需要添加以下 xml 元素:

           

          <message-bundle>edu.uwec.financial.resources.UIResources</message-bundle>
          

              再次運(yùn)行 index.jspx 文件將顯示一個(gè)與以下類(lèi)似的頁(yè)面(如果您沒(méi)有添加用于購(gòu)買(mǎi)、幫助等的托管 Bean,那么該頁(yè)面將只顯示 Campus Accounts 選項(xiàng)卡):

          了解 Oracle ADF:入門(mén)示例(圖七) 點(diǎn)擊查看大圖

           

          第 10 步:創(chuàng)建第一個(gè)輸入頁(yè)面。第一個(gè)“有用的”頁(yè)面將是一個(gè)允許用戶(hù)輸入帳號(hào)的頁(yè)面,這是管理帳戶(hù)的第一步。打開(kāi) faces-config.xml 圖并將一個(gè)新頁(yè)面拖至其上,然后雙擊圖標(biāo)對(duì)該頁(yè)面進(jìn)行編輯。 在本例中,我們希望為校園帳戶(hù) (campusaccounts) 創(chuàng)建另一個(gè)組織級(jí)別,因此在 /administration/campusaccounts 中創(chuàng)建了 choose.jspx(在 public html 之后添加 administration\campusaccounts)。我們決定讓 JDeveloper 在第二步中創(chuàng)建托管 Bean。choose.jspx 的輔助 Bean 將自動(dòng)命名為 Choose.java,并包含每個(gè)用戶(hù)界面組件的域。這意味著,您在每次添加組件時(shí)(即便是如 spacer 般簡(jiǎn)單的組件),它都會(huì)通過(guò)自己的 getter 和 setter 顯示為一個(gè)域。對(duì)于編寫(xiě) Java 代碼以更改 spacer 中的屬性大小(如高度)來(lái)說(shuō),這十分有意義,然而還是會(huì)因此創(chuàng)建出復(fù)雜的輔助 Bean。在本例中,從自動(dòng)創(chuàng)建的輔助 Bean 開(kāi)始要更為簡(jiǎn)單些(如果我們希望了解它執(zhí)行的操作)。

              使用 Structure 窗口,將 替換為 welcome.jspx 中的 view 標(biāo)記。實(shí)質(zhì)上,您已將歡迎頁(yè)面用作模板。在 choose.jspx 的 Structure 窗口中,您可以刪除 view 標(biāo)記,然后將 view 標(biāo)記從 welcome.jspx 復(fù)制并粘貼到 choose.jspx 中。如果您選擇在 Source 窗口中進(jìn)行更改,請(qǐng)注意保留指示 jspx 具有輔助 Bean 的 html 注釋 — 該 Oracle 慣例如下所示:

          <!--oracle-jdev-comment:auto-binding-backing-bean-name:backing_administration_campusaccounts_choose-->
          

              向在 GlobalCampusAccounts 上指定導(dǎo)航規(guī)則的 faces 配置文件添加導(dǎo)航規(guī)則,界面將導(dǎo)航至應(yīng)用程序的第一個(gè)頁(yè)面。這是一個(gè)全局規(guī)則,因?yàn)槟梢酝ㄟ^(guò)在任何應(yīng)用程序的任意位置選擇 CampusAccounts 的選項(xiàng)卡來(lái)更改為 CampusAccounts。在 faces-config.xml 中輸入的標(biāo)記是

          <navigation-rule>
          <navigation-case>
          <from-outcome>GlobalCampusAccounts
          <to-view-id>/administration/campusaccounts/choose.jspx
          </navigation-case>
          </navigation-rule>
          

              您可能需要編輯 commandMenuItems 中的 logout 和 home 圖標(biāo)屬性,并更改它們的圖標(biāo)值以使用 blaf 文件夾中的 gif 文件。

              您需要將 PanelHorizontal 插入面板頁(yè)以保存輸入文本組件。盡管也可以使用組件選項(xiàng)板 (Component palette),但通常我們認(rèn)為利用 Structure 頁(yè)來(lái)執(zhí)行該操作更為簡(jiǎn)單(右鍵單擊 PanelPage 元素并選擇 ADF Faces Core 組件即可)。注意,ADF 表單包含有 PanelPage,因此您已經(jīng)具有了自己的 html 表單元素。向水平面板添加一個(gè) InputText 組件。在 Properties 窗口中,更改標(biāo)簽以使用存儲(chǔ)在資源文件中的屬性。一種簡(jiǎn)單的方法是先編輯資源文件并添加屬性,然后在 Structure 窗口中雙擊 inputText 元素,選擇 Bind 在 JSF 對(duì)象中查找 res,并選擇您剛才輸入的屬性值。一旦您習(xí)慣了訪問(wèn)資源所需的 EL 格式,就會(huì)發(fā)現(xiàn)在 Property Editor 中鍵入屬性值也很簡(jiǎn)單。在水平面板上的輸入文本組件后面添加一個(gè) CommandButton,并更改其名稱(chēng)以使用資源文件中定義的另一個(gè)屬性 — 再次建議您使用 Structure 窗口。

              雙擊按鈕轉(zhuǎn)至輔助 Bean。您需要從 InputText 組件獲取文本,并將其置于用戶(hù)狀態(tài),以便當(dāng)用戶(hù)訪問(wèn) CampusAccounts 應(yīng)用程序的選項(xiàng)時(shí)它始終可用。

          public String commandButton1_action() {
          Object text = getInputText1().getValue();
          UserSystemState.storeCurrentAcctNum(new Integer(acctNum));
          return "list";
          }
          

              注意,此處無(wú)需任何驗(yàn)證,而您在使用 Faces 組件的選項(xiàng)時(shí)會(huì)進(jìn)行不必要的驗(yàn)證。如果您在 InputText 元素上設(shè)置必需屬性,則會(huì)強(qiáng)迫用戶(hù)輸入值。如果您在 InputText 標(biāo)記內(nèi)插入一個(gè) ValidateRegExp 驗(yàn)證程序并添加模式 [0-9]+,則會(huì)要求用戶(hù)至少為帳號(hào)輸入一位數(shù)字。

          在本例中,我們添加了來(lái)自 SRDemo 的 UserSystemState,以將其用作模型并創(chuàng)建用于保存帳號(hào)的靜態(tài)函數(shù)。我們還必須添加 userSystemState(u 為小寫(xiě)) 作為 faces-config.xml 文件中的托管 Bean 的名稱(chēng)。您可以通過(guò) managed-bean-class 域來(lái)推斷我們使用的程序包名。JDeveloper 管理 faces-config.xml 文件的明顯特征之一是,如果在編譯代碼或指定程序包名時(shí)出現(xiàn)問(wèn)題,您就會(huì)在其標(biāo)記中看到警告。JDeveloper 會(huì)主動(dòng)分析 xml 配置文件。

           

          <managed-bean>
          <managed-bean-name>userSystemState</managed-bean-name>
          <managed-bean-class>edu.uwec.financial.view.backing.UserSystemState</managed-bean-class>
          <managed-bean-scope>session</managed-bean-scope>
          </managed-bean>
          

          以下是 UserSystemState 的起始代碼,用于創(chuàng)建 Command 按鈕中使用的靜態(tài)函數(shù);它將替代所有來(lái)自 SRDemo 的域和方法。記住檢查程序包名:

          private HashMap _settings = new HashMap();
          private static final String CURRENT_ACCT_NUM = "CURRENT_ACCT_NUM";
          public Integer getCurrentAcctNum() {
          return (Integer)_settings.get(CURRENT_ACCT_NUM);
          }
          public void setCurrentAcctNum(Integer acctNum) {
          _settings.put(CURRENT_ACCT_NUM, acctNum);
          System.out.println("setCurrentAcctNum:"+acctNum); // some old fashioned testing
          }
          public static void storeCurrentAcctNum(Integer acctNum) {
          JSFUtils.setManagedBeanValue("userSystemState.currentAcctNum", acctNum);
          }
          public static void retrieveCurrentAcctNum() {
          JSFUtils.getManagedBeanValue("userSystemState.currentAcctNum");
          }
          

              該代碼比較奇特。userSystemState.currentAcctNum 似乎是 UserSystemState 中某個(gè)域的引用,但這個(gè)名稱(chēng)沒(méi)有域。JSFUtils.getManagedBeanValue 函數(shù)調(diào)用的參數(shù)被解析為 getter;因此,userSystemState.currentAcctNum 將導(dǎo)致對(duì) getCurrentAcctNum() 進(jìn)行調(diào)用。

              如果運(yùn)行 index.jspx 并選擇 CampusAccounts 選項(xiàng)卡,您應(yīng)該看到應(yīng)用程序的初始頁(yè)面將如下所示:

          了解 Oracle ADF:入門(mén)示例(圖八) 點(diǎn)擊查看大圖

           

          第 11 步:創(chuàng)建第一個(gè) ADF 數(shù)據(jù)控件。(另請(qǐng)參閱 ADF 教程 5-2。)這一步充滿(mǎn)了樂(lè)趣,并且 ADF 的價(jià)值將在這一步真正體現(xiàn)出來(lái)。創(chuàng)建了允許用戶(hù)輸入帳號(hào)的頁(yè)面后,您現(xiàn)在希望獲取所有與該帳號(hào)關(guān)聯(lián)的交易 — 文件上的所有存款和支出。

              在 faces 導(dǎo)航圖中創(chuàng)建一個(gè)名為 /administration/campusaccounts/list.jspx 的頁(yè)面,并在編輯 list.jspx 時(shí)自動(dòng)公開(kāi) UI 組件。復(fù)制來(lái)自 welcome.jspx 的 view 標(biāo)記,如第 9 步中執(zhí)行的操作。

              您需要連接列表頁(yè)以顯示 Detail 表(或 Detail DAO,具體取決于您如何考慮)中的相應(yīng)行。請(qǐng)牢記,ADF 數(shù)據(jù)控件是構(gòu)建 ADF 應(yīng)用程序的關(guān)鍵,因此請(qǐng)打開(kāi) Data Control 選項(xiàng)板。

          了解 Oracle ADF:入門(mén)示例(圖九)

          您可以將 findAccountTransactionsByAccount() 函數(shù)拖放到列表頁(yè) — 在這種情況下,您能夠創(chuàng)建諸如 Command 按鈕或參數(shù)表單之類(lèi)的組件。

              而將 Detail 拖放到 panelPage 將創(chuàng)建一組可以從 Detail 表顯示的行 — 這些行具有一個(gè)通用帳號(hào)。考慮到在這種情形下一個(gè)較長(zhǎng)的組件列表比較有用,因此選擇 Tables/ADF Read-only Table...Action Binding Editor 將顯示,因此您需要從選擇頁(yè)面獲取為帳號(hào)存儲(chǔ)的值,并將其作為要用于 findAccountTransactionsByAccount 的值進(jìn)行綁定:

          了解 Oracle ADF:入門(mén)示例(圖十)


              現(xiàn)在,顯示所有域并啟用選擇和排序功能。您還可以通過(guò)在 Structure 窗口中雙擊每一列,來(lái)編輯列屬性以有選擇地啟用/禁用排序功能并更改列標(biāo)題。在本例中,我們向資源文件添加了列標(biāo)題,然后將 HeaderText 綁定到引用,如 #{res['uacct.campusAccounts.account']}。(您還可以通過(guò)在 Structure 窗口中雙擊組件,來(lái)重置表的選擇控件中的文本。)我們發(fā)現(xiàn) Bind 按鈕比較有用。

              如果運(yùn)行該應(yīng)用程序并輸入一個(gè)有效帳號(hào),您希望看到的內(nèi)容將如下所示:

          了解 Oracle ADF:入門(mén)示例(圖十) 點(diǎn)擊查看大圖

              如果輸入 1000 作為帳號(hào),您會(huì)發(fā)現(xiàn)自己仍位于選擇頁(yè)面。您需要指定一個(gè)從選擇頁(yè)面到列表頁(yè)面的轉(zhuǎn)換。在 faces-config.xml 文件中,打開(kāi) Design 窗口并確保 Component 選項(xiàng)板可見(jiàn)。選擇 JSF Navigation Case,然后單擊選擇頁(yè)面和列表頁(yè)面(請(qǐng)按此順序操作)。編輯轉(zhuǎn)換標(biāo)簽并將 success 更改為 list,從而與 Choose.java 中 Command 按鈕操作返回的值相對(duì)應(yīng)。現(xiàn)在,數(shù)據(jù)將顯示在列表頁(yè)面中。

              注意顯示這個(gè)表(包含 Detail 數(shù)據(jù)庫(kù)表中的項(xiàng))是多么輕松。界面組件是一個(gè) ADF JSF 組件,因此可以說(shuō)您免費(fèi)獲得了包括各種功能在內(nèi)的復(fù)雜顯示對(duì)象,如分頁(yè)(總共 33 行結(jié)果,一次打印 10 行,如果結(jié)果全部匹配,可以一次打印全部 33 行)、分層(每行具有一種不同的顏色)、排序以及通過(guò)單選按鈕選擇單個(gè)行的能力(例如,能夠編輯其中的內(nèi)容)。這個(gè)頁(yè)面的外觀使用默認(rèn)的 Oracle 外觀,但是,更改用于指定組件標(biāo)簽的 Css 文件可以獲得不同的顏色、字體和圖標(biāo)。

              此外,您還會(huì)注意到利用 ADF 提供的復(fù)雜數(shù)據(jù)控件可以十分輕松地實(shí)現(xiàn)數(shù)據(jù)訪問(wèn)。在將 ADF Read-Only 表拖放到頁(yè)面之后,系統(tǒng)會(huì)推斷返回的輔助對(duì)象類(lèi)型 (Detail.java),并自動(dòng)將其用于創(chuàng)建相應(yīng)列。系統(tǒng)提供了行集行為(一次 10 行),正如基于派生自原始數(shù)據(jù)庫(kù)表的元數(shù)據(jù)的類(lèi)型解析一樣。

          第 12 步:創(chuàng)建編輯頁(yè)面。(另請(qǐng)參閱 Oracle ADF 教程 10-2。)在列表頁(yè)面上,用于選擇的 Table 控件 (facet) 包含一個(gè) af:tableSelectOne 標(biāo)記,該標(biāo)記內(nèi)部有一個(gè) Command 按鈕。如果雙擊 Command 按鈕,將打開(kāi)輔助 Bean,您可以在其中調(diào)用輔助函數(shù)來(lái)獲取數(shù)據(jù)以唯一標(biāo)識(shí)選定行,以便將其存儲(chǔ)以用于下一頁(yè)面的檢索。

          public String commandButton1_action() {
          setCurrentTransactionIdFromRow();
          return "edit";
          }
          
          List.java 中的輔助函數(shù)如下所示:
          private void setCurrentTransactionIdFromRow() {
          FacesContext ctx = FacesContext.getCurrentInstance();
          JUCtrlValueBindingRef tableRowRef = 
          (JUCtrlValueBindingRef) this.getTable1().getRowData(); Integer transId = (Integer)tableRowRef.getRow().getAttribute("cdPostSequence"); UserSystemState.storeCurrentTransId(transId); }
          
          

              需要將 storeCurrentTransId() 添加至 UserSystemState,以便將第 9 步中的 storeCurrentAcctNum() 用作模型。

              到目前為止,已經(jīng)介紹了選擇要編輯的行所需進(jìn)行的更改。現(xiàn)在,需要?jiǎng)?chuàng)建一個(gè)要在其中進(jìn)行編輯的新 jspx 頁(yè)面。在 faces-config.xml 文件中,添加一個(gè) jsp 頁(yè)面,然后對(duì)其進(jìn)行編輯以命名為 edit.jspx。在 Component 選項(xiàng)板中,選擇 JSF Navigation Case,并在 Design 窗口中將轉(zhuǎn)換標(biāo)簽更改為編輯,以匹配 Command 按鈕中指定的返回值。

              轉(zhuǎn)到 edit.jspx 頁(yè)面,從 Data Control 選項(xiàng)板中選擇 findOneTransaction/Detail,并使用 Forms/ADF Form 將其拖放至面板頁(yè)。在其中包含一個(gè) Submit 按鈕,并更改域順序(如果需要)。將參數(shù)設(shè)置為 JSF 對(duì)象中的值,以使用 UserSystemState 中的 acctNum 和 transId。完成操作綁定之后,您可以將不希望用戶(hù)編輯的域的 readOnly 屬性設(shè)置為 true。在 Structure 窗口中雙擊每一個(gè) inputText 域,然后從資源文件設(shè)置它們的標(biāo)簽。首先在資源文件中編輯值要更為簡(jiǎn)單。允許用戶(hù)從編輯頁(yè)面退出可能是最好的做法,因此您可以用 PanelGroup 圍繞 Submit 按鈕,然后在 Submit 之前或之后添加另一個(gè) CommandButton。您需要選擇這些按鈕并添加返回值。對(duì)于 Cancel 按鈕,無(wú)需調(diào)用與該按鈕對(duì)應(yīng)的輔助函數(shù),就可以編輯 action 屬性并指定導(dǎo)航轉(zhuǎn)換值。Cancel 按鈕的一些原始內(nèi)容(如“cancel”)將生效。在 faces-config.xml Design 窗口中添加一個(gè)用于提交返回值的 jsf 導(dǎo)航示例,以便從編輯頁(yè)面返回列表頁(yè)面。另一種比較好的方法是,首先在 faces-config.xml 文件中設(shè)置導(dǎo)航值,在這種情況下,選擇這些按鈕的 action 屬性值時(shí),該值將顯示為選項(xiàng) — JDeveloper 使用配置文件比較有利。


              您仍然需要編寫(xiě)代碼來(lái)保持在編輯頁(yè)面上所作的更改。但在本示例中,您將再次使用 ADF 開(kāi)發(fā)范例。換言之,與其在輔助 Bean 中編寫(xiě)代碼,不如依靠 JDeveloper/ADF 向?qū)?lái)編寫(xiě)保持更改所需的代碼。您還將使用在最初創(chuàng)建 ORM 并生成會(huì)話 Bean 時(shí)自動(dòng)創(chuàng)建的 mergeEntity() 函數(shù)。

              如 ADF 教程第 10 章所建議,在 edit.jspx 頁(yè)面上打開(kāi) Design 窗口,然后打開(kāi) Data Control 選項(xiàng)板。將 mergeEntity() 方法拖放到 Submit 按鈕上,并選擇 Bind Existing CommandButton。下一個(gè)顯示的頁(yè)面是 Action Binding Editor。 雙擊向?qū)乱徊街械闹悼颍ɑ蛉绻?... 按鈕顯示選擇該按鈕),打開(kāi) ADF Bindings 中的綁定。請(qǐng)牢記該綁定引用 ADF 中提供的所有綁定。打開(kāi) findOneTransactionIter 節(jié)點(diǎn)并選擇 currentRow 中的 dataprovider。構(gòu)建的表達(dá)式(指定當(dāng)前記錄)是 ${bindings.findOneTransactionIter.currentRow.dataProvider}。注意,Submit 按鈕的 ActionListener 屬性已重置為 #{bindings.mergeEntity.execute}。可將 action 屬性設(shè)置為“list”,以便完成對(duì)數(shù)據(jù)庫(kù)的更改后,我們的界面將返回到列表頁(yè)面。將其值可進(jìn)行更改的所有文本域的 immediate 屬性設(shè)置為 true。編輯頁(yè)面應(yīng)如下所示:

          了解 Oracle ADF:入門(mén)示例(圖十二)
          此外,ADF 可以非常輕松地添加編輯事務(wù)的功能。雖然此處未提及,但您還可以向會(huì)話 Bean 添加另一個(gè)函數(shù),以便在調(diào)用 mergeEntity 之前將業(yè)務(wù)規(guī)則應(yīng)用到編輯域 (Apply Business Rules to Edited Field)。

          適可而止

           

          還有許多演示無(wú)法全部囊括在本次練習(xí)中,但您仍可以通過(guò)教程或開(kāi)發(fā)人員指南來(lái)完成:

          • 您沒(méi)有為應(yīng)用程序添加任何安全措施,以確保只有簽名信息庫(kù)中的用戶(hù)可以添加記錄(或編輯記錄)。簡(jiǎn)單的安全性將允許您打印用戶(hù)名而不是空值。
          • 您沒(méi)有處理錯(cuò)誤或特殊條件。
          • 您沒(méi)有使用 ADF 的驗(yàn)證功能。例如,確保輸入文本框在用戶(hù)輸入新交易時(shí)不為空就比較有意義。
          • 添加一個(gè)選擇以允許用戶(hù)從交易列表刪除存款或支出,這樣比較有趣。

          但是您必須適可而止!

          感謝并總結(jié)

           

              我們衷心感謝 JDeveloper 團(tuán)隊(duì)就本文中有關(guān) JDeveloper 功能的語(yǔ)句精確性進(jìn)行了檢查。Oracle 文檔詳細(xì)列出了許多此處未提及的 JDeveloper 特性。

              正如我們?cè)诤?jiǎn)介中所述,在您已經(jīng)熟悉了某種特定開(kāi)發(fā)方法后很難再轉(zhuǎn)而使用另一種技術(shù)。本文中,我們使用了 Spring JDBC 模板進(jìn)行數(shù)據(jù)建模、利用 Spring MVC 和 Spring Web Flow 進(jìn)行導(dǎo)航,以及將 Eclipse 用作開(kāi)發(fā)環(huán)境。回想起來(lái),開(kāi)始我們是希望了解如何在新環(huán)境中做我們已經(jīng)知曉的事情,而選件(如輔助 Bean)則助了我們一臂之力。最初我們沒(méi)有打算嘗試 TopLink,甚至尋求另一種方法來(lái)使用 ADF 控件。值得高興的是,我們閱讀了 Oracle 參考,這些參考使我們對(duì)于嘗試 ADF 提供的其他功能充滿(mǎn)了信心。

              對(duì)于應(yīng)用程序開(kāi)發(fā)框架而言,ADF 無(wú)疑是一個(gè)卓越的工具、一個(gè)不錯(cuò)的助手。我們力圖通過(guò) ADF 和 JDeveloper 探索出若干其他方法,包括

          • 使我們現(xiàn)有的基于 Spring 的后端服務(wù)能夠用作可從 ADF Faces 接口調(diào)用的 Web 服務(wù)。Oracle ACE Lucas Jellema 撰寫(xiě)的網(wǎng)志給予了我們嘗試這種想法的靈感。
          • 使用 Oracle XML Publisher 作為構(gòu)建報(bào)表頁(yè)面的另一種方法
          • 將 BPEL 插件用于 JDeveloper,以根據(jù)業(yè)務(wù)流程中人為干預(yù)的需要進(jìn)行建模。據(jù)說(shuō),BPEL 之于流程管理正如 SQL 之于數(shù)據(jù)管理。

          Oracle 提供的開(kāi)發(fā)工具系列可以很好地滿(mǎn)足我們的需求。

          提示與技巧

          1. 一不做,二不休。文中數(shù)次提及的其當(dāng)之無(wú)愧的一個(gè)事實(shí)是:JDeveloper 和 ADF 是功能強(qiáng)大的端到端解決方案。它們具有挑戰(zhàn)開(kāi)發(fā)環(huán)境(如 .net)的實(shí)力。例如,我們最初計(jì)劃不使用 TopLink 將示例應(yīng)用程序放在一起,并認(rèn)為在應(yīng)用程序中編寫(xiě)基于 Spring 的數(shù)據(jù)訪問(wèn)很輕松。閱讀 ADF 教程激發(fā)了我們對(duì) TopLink 的好奇,因此我們決定嘗試使用它,并在開(kāi)始時(shí)只是認(rèn)為這是無(wú)害的。在為交易添加第一個(gè)列表表單花費(fèi)了大約 90 秒后,我們的態(tài)度發(fā)生了根本性轉(zhuǎn)變。最初,mergeEntity 函數(shù)似乎只是由 TopLink 創(chuàng)建的另一個(gè)產(chǎn)物。在添加了編輯頁(yè)面之后,我們了解了其價(jià)值,以及可對(duì) Faces 組件進(jìn)行無(wú)縫訪問(wèn)的 ADF 控件的價(jià)值。JDeveloper 提供了集成的開(kāi)發(fā)環(huán)境。ADF 不僅是一組 UI 組件,還是一個(gè)完善的前端、后端框架,可提供能夠顯著提高工作效率的工具。

          2. JDeveloper 與 Eclipse 或 Websphere Application Developer 在創(chuàng)建程序包、復(fù)制和移動(dòng)文件方面存在著區(qū)別。對(duì)于圖像和其他非 Java 文件,我們發(fā)現(xiàn)復(fù)制和移動(dòng)文件最簡(jiǎn)單的方法是在 Windows Explorer 中進(jìn)行操作,然后在 Applications 窗口中進(jìn)行刷新。使用 File 中的 Import 選項(xiàng)時(shí),請(qǐng)確保編輯 CopyTo 行以將完整的文件夾(程序包)名包括在內(nèi)。重命名文件和移動(dòng)文件還會(huì)對(duì)配置文件和屬性值造成重大破壞。我們一般使用 Property Editor 中的 ... 選項(xiàng)來(lái)設(shè)置圖像和其他文件的屬性值。編輯配置文件需要敏銳的眼光和一定的耐心。我們可能犯的最嚴(yán)重錯(cuò)誤就是在 faces 配置文件中將 campusAccounts 更改為 campusaccounts。頁(yè)面之間不會(huì)出現(xiàn)轉(zhuǎn)換,從而浪費(fèi)了大量時(shí)間。誠(chéng)然,使用 JDeveloper 時(shí)保持程序包一致的確令人煩躁。

          3. 下載 SRDemo 非常簡(jiǎn)單,如果您剛好安裝了 JDeveloper。在 Help 菜單中,選擇 Check for Updates,然后選擇 Official Oracle Extensions。選取 ADF SRDemo,并按向?qū)瓿上鄳?yīng)操作。要運(yùn)行它,請(qǐng)轉(zhuǎn)至 SRDemo 應(yīng)用程序并選擇 index.jspx 和綠色箭頭。一旦下載了演示程序,您就可以訪問(wèn)其全部文件,包括幾乎所有應(yīng)用程序都需要的幫助類(lèi)(如 JSFUtils 和 UserSystemState)。您需要為 SRDemo 提供數(shù)據(jù)庫(kù)模式。

          4. 您不必離開(kāi) JDeveloper 就可查看數(shù)據(jù)庫(kù)表的值。從 Connections 選項(xiàng)卡中,選擇您的 Connection 和模式,然后打開(kāi)一個(gè)表。表值將顯示在 Data 選項(xiàng)卡(可能位于窗口底部)中。

              Tom Moore 是威斯康星大學(xué)伊奧克萊爾分校的高級(jí)顧問(wèn),專(zhuān)攻知識(shí)與技術(shù)服務(wù)。Tom 持有威斯康星大學(xué)密爾沃基分校的計(jì)算機(jī)科學(xué)碩士學(xué)位,熱衷于 Java 和開(kāi)放源代碼產(chǎn)品(如 Struts 和 Spring)。在他將注意力轉(zhuǎn)向 Oracle 開(kāi)發(fā)工具和框架之前,已是威斯康星大學(xué)伊奧克萊爾分校計(jì)算機(jī)科學(xué)系的老成員。
            posted on 2007-08-18 10:29 JavaPoint 閱讀(1718) 評(píng)論(1)  編輯  收藏 所屬分類(lèi): Java

            評(píng)論:
            # re: 了解 Oracle ADF:入門(mén)示例 2016-08-05 17:11 | 鄭州
            主站蜘蛛池模板: 都昌县| 商丘市| 十堰市| 洱源县| 南开区| 北碚区| 江北区| 新宾| 三门县| 福贡县| 建宁县| 白朗县| 依兰县| 西乡县| 龙川县| 临潭县| 延寿县| 家居| 齐齐哈尔市| 阳曲县| 佳木斯市| 普安县| 个旧市| 永顺县| 石景山区| 如皋市| 札达县| 磐安县| 沾化县| 洪湖市| 古浪县| 临武县| 谷城县| 蒲城县| 安达市| 合江县| 内丘县| 凯里市| 清原| 定襄县| 南丰县|