鳳凰涅磐,浴火重生!

          超越他人的期望,才能讓人感動!

          My Links

          Blog Stats

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          DOJO + JSON

          曾幾何時ajax已經遍布大江南北,然而單純的js難于閱讀和debug,dojo的出現,無疑部分地解決了這個問題,加上ide的支持,更是如虎添翼了!引用一篇IBM的文章,看看dojo的應用吧。

          以下是引用內容:

          使用 Dojo 工具包和 JSON-RPC 構建企業 SOA Ajax 客戶端

          developerWorks
          文檔選項
          將此頁作為電子郵件發送

          將此頁作為電子郵件發送

          將此頁作為電子郵件發送

          將此頁作為電子郵件發送

          樣例代碼


          拓展 Tomcat 應用

          下載 IBM 開源 J2EE 應用服務器 WAS CE 新版本 V1.1


          級別: 中級

          Roland Barcia (barcia@us.ibm.com), IT 咨詢專家, IBM WebSphere 軟件服務部

          2006 年 8 月 21 日

          了解如何使用 Dojo 工具包為 Java? Platform Extended Edition (Java EE) 應用程序構建企業 SOA 客戶端,以及如何使用 JavaScript Object Notation–RPC (JSON-RPC) 來調用服務器端 Java 對象。

          引言

          異步 JavaScript 和 XML (Ajax) 是使用本機瀏覽器技術構建富 Web 應用程序的新方法。對于編寫需要某些類型的“活動”用戶界面的復雜應用程序的開發人員,JavaScript 在這方面已經做得很好。不過,JavaScript 難于編碼、調試、移植和維護。使用 Ajax 工具包有助于最大程度地減少使用 JavaScript 和 Ajax 帶來的許多常見問題。優秀的 Ajax 工具包提供了一組可重用的小部件、用于擴展和創建小部件的框架、事件系統、JavaScript 實用工具和增強的異步服務器調用支持。在本文中,我們將討論如何使用 Dojo 工具包為 Java EE 應用程序構建企業 SOA 客戶端。我們還將使用 JSON (JavaScript Object Notation)–RPC 來調用服務器端 Java 對象。

          在本文中,我們還將向您提供以下內容的簡要說明:Ajax、Dojo、JSON 和 JSON-RPC,以及一些設計 Ajax 應用程序的設計原則和您可以下載并親自嘗試運行的簡短示例。





          回頁首


          Ajax 概述

          有許多關于 Ajax 的論文、文章和書籍。我不打算對 Ajax 進行深入介紹。有關詳細信息,請查閱參考資料

          Ajax 可作為使用本機瀏覽器組件構建網站的體系結構樣式。Ajax 的關鍵部分有:

          • JavaScript,它可以編排頁面元素,從而獲得最佳 Ajax 用戶體驗。
          • Cascading Style Sheets (CSS),它可以定義頁面元素的可視樣式。
          • 文檔對象模型(Document Object Model,DOM),它將網頁結構作為一組可以使用 JavaScript 操作的可編程對象提供。
          • XMLHttpRequest,它支持以后臺活動的形式從 Web 資源檢索數據。

          XMLHttpRequest 對象是關鍵部分。

          XMLHttpRequest 對象

          XMLHttpRequest 對象是 Ajax 用于進行異步請求的機制。圖 1 說明了該流程:


          圖 1. XMLHttpRequest 對象進行異步請求的流程圖
          XMLHttpRequest 對象進行異步請求的流程圖。

          XMLHttpRequest 對象是瀏覽器中提供的 JavaScript 對象。(Microsoft? 和 Mozilla 瀏覽器各有自已的版本)。該流程如下所示:

          1. 頁面調用某個 JavaScript。
          2. JavaScript 函數創建 XMLHttpRequest 對象。這包括設置要調用的 URL 和 HTTP 請求參數。
          3. JavaScript 函數注冊回調處理程序。HTTP 響應調用此回調處理程序。
          4. JavaScript 函數調用 XMLHttpRequest 對象上的 send 方法,該方法接著將 HTTP 請求發送到服務器。
          5. XMLHttpRequest 對象立即將控制返回到 JavaScript 方法。此時,用戶可以繼續使用該頁面。
          6. 稍后,HTTP 服務器通過調用回調處理程序返回 HTTP 響應。
          7. 回調處理程序可以訪問 HTML DOM 對象。它可以動態更新頁面元素,而無需中斷用戶(除非您碰巧更新用戶正在使用的 DOM 對象)。

          通過異步更新頁面的 DOM,還可以在本地進行異步請求。





          回頁首


          Dojo 工具包概述

          Dojo 使您能夠方便地構建動態站點。它提供一個豐富的小部件庫,您可以使用它組成頁面。您可以使用基于 Dojo 方面的事件系統將事件附加到組件,以創建豐富的交互體驗。此外,您可以使用幾個 Dojo 庫進行異步服務器請求、添加動畫效果和瀏覽存儲實用工具等等。

          Dojo 小部件

          Dojo 提供了您可以用于構建頁面的一組豐富的小部件。您可以使用多個方法創建 Dojo 小部件。Dojo 的眾多優點之一是它允許您使用標準的 HTML 標記。然后,可以將這些標記用于小部件。這樣,HTML 開發人員就可以方便地使用 Dojo,如清單 1 所示:


          清單 1. 在 HTML 標記中使用 Dojo
          <div dojoType="FloatingPane" class="stockPane" title="Stock Form" id="pane" 
                                           constrainToContainer="true" displayMaximizeAction="true">
                 <h2>Stock Service</h2>
                 Enter symbol: <input dojoType="ValidationTextBox" required="true"
                                                    id="stockInput">
                 <p />
                 <button dojoType="Button2" widgetId="stockButton">
                         Get Stock Data
                 </button>
                 <div id="resultArea" />
          </div>
          

          您可以使用 div 標記來定義小部件的位置,而在頁面加載或對事件進行響應時 Dojo 可以在這些地方放置小部件。您還可以使用更具體的標記,如 <dojo:widget>,并向其中添加 Dojo 小部件屬性。在清單 1 中,我們將 dojoType 屬性添加到 button 標記。在設置了標記之后,您需要在一些 JavaScript 內部加載小部件,如清單 2 所示。您可以將標記嵌入到頁面內部,但是我們建議將其放置在單獨的 JS 文件中。在本文的稍后部分中,我們將闡明一些 MVC 設計原則。


          清單 2. 在 HTML 標記中使用 Dojo
          //require statements
          dojo.require("dojo.widget.*" );
          dojo.require("dojo.event.*");
          dojo.require("dojo.widget.Button2");
          dojo.require("dojo.widget.FloatingPane" );
          
          //all dojo.require above this line
          dojo.hostenv.writeIncludes(); 
          dojo.require();	
          	

          您可以在 JavaScript 中創建、訪問、修改和刪除小部件,從而實現動態行為。在我們的示例中,您將看到在 JavaScript 中訪問小部件的示例。

          Dojo 事件系統

          Dojo 事件系統使用面向方面的技術將事件附加到小部件。這可以將小部件與實際的事件處理分離。Dojo 不是將硬代碼 JavaScript 事件添加到 html 標記上,而是提供允許您將事件附加到小部件的 API,如清單 3 所示。


          清單 3. 使用 Dojo 將事件處理程序附加到小部件
          function submitStock()
          	{
          		...
          	}
          function init()
          	{
          		var stockButton = dojo.widget.byId('stockButton');
          		dojo.event.connect(stockButton, 'onClick', 'submitStock');
          	}
          dojo.addOnLoad(init);
          	

          通過使用 connect 方法,您可將 JavaScript 方法連接到小部件。您還可以在 div 節點上附加 dojoAttachEvent,如下所示。某些 HTML 標記沒有定義事件,所以這是一個方便的擴展。


          清單 4. 使用 Dojo 將事件附加到 HTML 標記
          <div dojoAttachPoint="divNode"
              dojoAttachEvent="onClick; onMouseOver: onFoo;">
          	

          Dojo 事件系統還允許多個高級功能,如:

          • 聲明在現有的事件處理程序之前或之后插入事件處理程序的建議。
          • 允許小部件在瀏覽器中訂閱或發布主題。
          • 添加事件回調。
          • 可用于表示事件的 event 規范化對象。

          有關詳細信息,請參見 http://dojo.jot.com/EventExamples

          Dojo 異步服務器請求

          Dojo 通過抽象特定于瀏覽器的詳細信息,提供了對服務器進行異步請求的簡單方法。Dojo 允許您創建數據結構來隱藏詳細信息,如清單 5 所示。


          清單 5. 使用 Dojo 進行異步請求
          var bindArgs = {
              url:        "/DojoJ2EE/MyURI",
              mimetype:   "text/javascript",
              error:      function(type, errObj){
                  // handle error here 
              },
              load:      function(type, data, evt){
                  // handle successful response here
              }
          };
          // dispatch the request
          var requestObj = dojo.io.bind(bindArgs);
          	

          此外,Dojo 使用 JSON-RPC 標準支持 RPC。在接下來的部分中,我們將看一看 Dojo 對 JSON 的支持。

          附加的 Dojo 功能

          Dojo 是一個具有許多功能的豐富庫,包括:

          • 處理 html、字符串、樣式、dom、正則表達式和若干其他實用工具的通用庫。
          • 包括字典、ArraryLists、隊列、SortedList、設置和堆棧的數據結構。
          • 用于添加動畫效果、驗證、拖放和若干其他功能的可視化 Web 實用工具。
          • 數學和加密庫。
          • 存儲組件。
          • XML 解析

          有關詳細信息,請參見 http://manual.dojotoolkit.org/index.html





          回頁首


          JSON 概述

          JSON 是 JavaScript 的對象文字符號的子集,它是在 JavaScript 中表示數據結構的常用方法。JSON 是一種完全與語言無關的文本格式,但使用編程人員熟悉的與 C 語言家族(包括 C、C++、C#、Java、JavaScript、Perl、Python 和許多其他語言)類似的約定。這些屬性使 JSON 成為 Ajax 客戶端的理想數據交換語言。

          JSON 構建在兩種結構的基礎上:

          1. 名稱/值對的集合。在不同的語言中,它被實現為對象、記錄、結構、字典、哈希表、有鍵列表或者關聯數組。
          2. 值的有序列表。在大多數語言中,它被實現為數組、向量、列表或序列。

          JSON 對象的示例如下:

          var myJSONObject = {"id": 4, "name": "Roland Barcia", "pets": ["dog","cat","fish"]};
          	

          在示例中,我們對值對進行了命名。括號中的任何內容都是一個列表。在不同的編程語言中都有一組豐富的實現。有關詳細信息,請參見 http://json.org/

          JSON-RPC

          JSON-RPC 是一種輕量級遠程過程調用協議,在此協議中,JSON 可以連續請求和響應。向遠程服務發送請求可以調用遠程方法。該請求是具有三個屬性的單個對象:

          • method - 包含要調用的方法名稱的字符串。
          • params - 作為參數傳遞到方法的對象數組。
          • id - 請求 ID。它可以屬于任何類型。它用于將響應與其應答的請求相匹配。

          當方法調用完成時,服務必須對響應進行應答。此響應是具有三個屬性的單個對象:

          • result - 被調用方法返回的對象。它必須為 null,以避免在調用該方法時發生錯誤。
          • error - error 對象(如果在調用方法時發生錯誤)。它必須為 null(如果不存在任何錯誤)。
          • id - 它必須是與響應的請求相同的 ID。

          通知是沒有響應的特殊請求。它與帶有一個異常的請求對象具有相同的屬性:

          • id - 必須為 null

          JSON 與 XML

          XML 是一種用于面向服務的體系結構 (SOA) 和數據傳輸的常見傳輸。當然,目前許多服務以 SOAP 格式存在。不過,何時將其用于數據傳輸在 Ajax 社區中存在分岐。JSON 有以下幾個優點:

          • 瀏覽器解析 JSON 的速度比 XML 快。
          • JSON 構造是友好的編程語言,并容易轉換為后端編程語言(如 Java)。
          • JSON 相當穩定。JSON 的附加內容將成為超集。

          XML 有以下優點:

          • 調用將 XML 用作傳輸的現有服務。
          • 使用 XSLT 可以動態轉換 XML。這是企業服務總線 (ESB) 方案中的理想功能。

          用于 Dojo 的 JSON-RPC

          Dojo 為調用 JSON-RPC 請求提供了抽象層。用于 Dojo 的 JSON-RPC 引入了標準方法描述(Standard Method Description,SMD)的概念。SMD 文件是 JSON-RPC 服務的描述。它允許您以中立方式描述 JSON 調用。清單 6 提供了此類 JSON 調用的示例:


          清單 6. Dojo 中的 SON 調用
          {"SMDVersion":".1",
           "objectName":"StockService",
           "serviceType":"JSON-RPC",
           "serviceURL":"/DojoJ2EE/JSON-RPC",
           "methods":[
          		{"name":"getStockData",
          		"parameters":[
          			{"name":"symbol",
          			"type":"STRING"}
          		 ]
              }
            ]
           }
          	

          您可以使用 Dojo API 調用服務:

          var StockService = new dojo.rpc.JsonService("/path/to/StockService.smd"); StockService.getStockData("IBM",stockResultCallback);

          這將通過網絡發送此結構:

          {"id": 2, "method": "getStockData", "params": ["IBM"]}

          JSON-RPC Java ORB

          JSON-RPC 為遠程過程調用定義標準格式,但是不存在對后端技術的標準映射。JSON-RPC Java Orb 提供了這樣一種機制:注冊 Java 對象,并將它們公開為 JSON-PRC 服務。它還在 JavaScript 中提供客戶端 API,以調用服務。

          如果您選擇使用 Dojo,則可以編寫自已的綁定代碼。用于 Java 的 JSON API 可以提供幫助。有關詳細信息,請參見 (http://developer.berlios.de/projects/jsontools/)。在我們的示例中,我們將使用 JSON-RPC Java ORB 進行異步請求,以利用服務器端綁定代碼。

          JSON-RPC Java Orb 允許您在一種 Servlet 范圍(請求、會話、應用程序)內注冊 Java 對象。然后,它可以使用 JSON-RPC 請求來調用 Java 對象。為此,可以將對象類型放在 JSON 對象之前。由于 Dojo API 不執行此操作,所以用于 JSON-RPC 的 Dojo 客戶端 API 與用于 Java 的 JSON-RPC 不兼容。

          清單 7 提供了如何向 HttpSession 注冊 Java 對象的示例:


          清單 7. 注冊 Java 對象的 HttpSession
          HttpSession session = sessionEvent.getSession();
          JSONRPCBridge json_bridge = null;
          json_bridge = (JSONRPCBridge) session.getAttribute("JSONRPCBridge");
          if(json_bridge == null) {
          		json_bridge = new JSONRPCBridge();
          		session.setAttribute("JSONRPCBridge", json_bridge);
          }
          json_bridge.registerObject
          ("StockService",StockServiceImpl.getStockService());

          您可以在 Servlet 或 HttpListener 中執行此操作。然后將 JavaScript 客戶端寫入到 Java 服務,如清單 8 所示。


          清單 8. 連接 Java 服務的 JSONRpcClient
          jsonrpc = new JSONRpcClient("/DojoJ2EE/JSON-RPC");
          var stockButton = dojo.byId('stockInput');
          jsonrpc.StockService.getStockData(stockResultCallBack,stockButton.value);
          	

          此請求會發送以下有效負載:

          {"id": 2, "method": "StockService.getStockData", "params": ["IBM"]}

          響應與以下所示類似:

          {"result":{"javaClass":"com.ibm.issw.json.service.StockData","price":100, "companyName":"International Business Machine","symbol":"IBM"},"id":2}

          用于 Java 客戶端的 JSON-RPC 將處理此響應,并向您提供一個靜態接口。

          為了支持請求,您需要注冊特殊的 Servlet。稍后,我將向您介紹如何執行此操作。

          JSON-RPC Java ORB 的一個缺點是只有單個 URL,這導致使用 Java EE 安全來保護 URL 非常困難。作為一種變通方法,您可以在 HTTP 會話層注冊服務,并根據安全需要添加它們。





          回頁首


          為企業應用程序構建企業客戶端

          在此部分中,我將討論一些設計原則,然后詳細講解一個示例。您可以下載完整的 WAR 文件,并親自嘗試該應用程序。

          模型-視圖-控制器

          在 Java EE 領域中,模型-視圖-控制器 (MVC) 已經變得非常成熟,這歸功于 Struts 和 JavaServer Faces 之類的框架。使用 Ajax 可以進行正確的 MVC 設計,這對成功的 Web 應用程序至關重要。此外,SOA 允許直接從 Ajax 應用程序調用服務。這樣做有幾個優點,如 WebSphere 期刊文章 "AJAX Requests – Data or Markup?" 中所述。

          圖 2 提供了 Ajax 客戶端和 Java EE 應用程序之間理想生態系統的簡要概述。


          圖 2. Ajax 客戶端和 Java EE 應用程序之間的理想生態系統
          Ajax 客戶端和 Java EE 應用程序之間的理想生態系統。

          在服務器端,業務和門戶功能現在被公開為某一類型的服務接口。在服務的形式下,應遵循正確的服務器端最佳實踐。服務器應用程序應公開過程粒度服務。JavaServer Faces 之類的框架現在負責執行初始呈現;不過,對于客戶端 Ajax 工具包,這是可選的。

          在瀏覽器上,分離關注的內容非常重要。圖 3 突出顯示了 Java 服務器文件結構:


          圖 3. Java 服務器文件結構
          Java 服務器文件結構。

          您可以選擇每頁有一個 JavaScript 控制器。不過,對于復雜的門戶頁,您可以將相關事件分組成小型的控制器集。

          控制器文件應:

          1. 向小部件加載網絡請求處理程序,如圖 4 所示:

            圖 4. 將請求處理程序附加到小部件
            將請求處理程序附加到小部件。

          2. 實現請求處理程序。請求處理程序不應有太多的邏輯。它們應委派給服務 Facade,以便與后端交互。
          3. 實現回調處理程序方法。回調應將呈現委派給獨立 JS 文件。此外,它們應將存儲中間狀態的工作委派給獨立 Java 服務器文件。對于無狀態交互,可以直接將結果傳遞到 rendering.js 文件。

          圖 5 說明了組件之間的流:


          圖 5. 從客戶端到請求處理程序,再到回調處理程序的信息流
          從客戶端到請求處理程序,再到回調處理程序的信息流。

          呈現文件包含呈現組件的邏輯或基于事件結果的用戶界面。

          Business Facades 應包含代理服務器請求的方法。DataCopy 應維護需要本地保存在瀏覽器中的本地視圖對象。

          為 Dojo 設置 Java EE 應用程序

          對于 Dojo,您必須添加 JavaScript 文件作為 Web 應用程序的一部分。您可以將 dojo 文件夾復制到 Web 應用程序文件夾,如圖 6 所示:


          圖 6. 添加使用 Dojo 所必需的 JavaScript 文件
          添加使用 Dojo 所必需的 JavaScript 文件。

          為 JSON-RPC Java Orb 設置 Java EE 應用程序

          為了在應用程序中使用 JSON-RPC Java Orb,您需要在 Web 應用程序的 lib 目錄中添加 json-rpc-1.0.jar。還需要將單個 jsonrpc.js 文件添加到 Web 內容文件夾中,如圖 7 所示:


          圖 7. 添加使用 JSON-RPC Java Orb 所必需的 JavaScript 文件
          添加使用 JSON-RPC Java Orb 所必需的 JavaScript 文件。

          為了使 Java EE 應用程序能夠接收用于 Java 請求的 JSON-RPC,您必須添加 JSONRPCServlet,如清單 9 所示:


          清單 9. 使用 JSONRPCServlet 所需的代碼
          <servlet>
          	<servlet-name>
          		com.metaparadigm.jsonrpc.JSONRPCServlet
          	</servlet-name>
          	<servlet-class>
          		com.metaparadigm.jsonrpc.JSONRPCServlet
          	</servlet-class>
          </servlet>
          
          <servlet-mapping>
          	<servlet-name>
          		com.metaparadigm.jsonrpc.JSONRPCServlet
          	</servlet-name>
          	<url-pattern>/JSON-RPC</url-pattern>
          </servlet-mapping>
          	

          對于 SOA

          Ajax 使 SOA 客戶端更完美。在我們的示例中,我們使用了一個簡單的 Java 服務。

          Java 服務

          圖 8 是基于 Java 的服務模型:


          圖 8. 基于 Java 的服務模型
          基于 Java 的服務模型。

          我們使用了一個簡單的硬編碼實現,如清單 10 所示:


          清單 10. 簡單的硬編碼 Java 服務
          public StockData getStockData(String symbol) throws StockException {
          	if(symbol.equals("IBM"))
          	{
          		StockData stockData = new StockData();
          		stockData.setCompanyName("International Business Machine");
          		stockData.setSymbol(symbol);
          		stockData.setPrice(100.00);
          		return stockData;
          	}
          	else
          	{
          		throw new StockException("Symbol: " + symbol + " not found!");
          	}	
          }
          	

          使用 JSON-RPC 公開 Java 服務

          為了公開 Java 應用程序,我使用了被稱為 ExportServices 的 HttpSessionListener,以便為用戶注冊服務,如清單 11 所示:


          清單 11. ExportServices,即公開 Java 服務的 HttpSessionListener
          import javax.servlet.http.HttpSession;
          import javax.servlet.http.HttpSessionEvent;
          import javax.servlet.http.HttpSessionListener;
          	
          import com.ibm.issw.json.service.StockServiceImpl;
          import com.metaparadigm.jsonrpc.JSONRPCBridge;
          	
          public class ExportServices implements HttpSessionListener {
          	
          	public void sessionCreated(HttpSessionEvent sessionEvent) {
          			
          		HttpSession session = sessionEvent.getSession();
          		JSONRPCBridge json_bridge = null;
          		json_bridge = (JSONRPCBridge) session.getAttribute("JSONRPCBridge");
          			if(json_bridge == null) {
          				json_bridge = new JSONRPCBridge();
          				session.setAttribute("JSONRPCBridge", json_bridge);
          			}
          		json_bridge.registerObject
          			("StockService",StockServiceImpl.getStockService());
          	}
          	
          	public void sessionDestroyed(HttpSessionEvent arg0) {
          			
          	}
          	
          }
          	

          您需要將偵聽器添加到應用程序中(通過將其添加到 web.xml),如清單 12 所示:


          清單 12. 添加到 web.xml 的 ExportServices 偵聽器
          <listener>
          	<listener-class>ExportServices</listener-class>
          </listener>
          	

          客戶端開發過程

          設置了基礎結構并公開了服務之后,現在我們可以構建 Web 客戶端了。通過 Dojo,我們利用小部件構建網頁并利用事件模型。圖 9 說明了建議的開發過程:


          圖 9. 開發過程示例
          開發過程示例。

          我將使用此過程演示該示例。

          從小部件構建 UI

          首先構建 UI。請參見清單 13,了解示例 UI。

          創建 UI:

          1. 加載腳本:
            1. dojo
            2. jsonrpc
            3. StockClientController
            4. resultRenderer
          2. 構建頁面,并結合使用 div 和 HTML 標記以創建 Dojo 小部件。

            清單 13. HTML UI
            <html>
            <head>
            <title>Stock Form</title>
            
            <script type="text/javascript" src="../dojoAjax/dojo.js"></script>
            <script type="text/javascript" src="../jsonrpc.js"></script>
            <script type="text/javascript" src="../view/resultRender.js"></script>
            <script type="text/javascript"
            	src="../controller/StockClientController.js"></script>
            <link REL=StyleSheet href="../StockApp.css" TYPE="text/css" ></link>
            </head>
            <body>
            
            <div class="layout" dojoType="LayoutContainer">
            <div dojoType="ContentPane" class="stockContent" layoutAlign="bottom"
             id="docpane" isContainer="true" executeScripts="true">
            <div dojoType="FloatingPane" class="stockPane" title="Stock Form" 
            id="pane" constrainToContainer="true" displayMaximizeAction="true">
            			<h2>Stock Service</h2>
            Enter symbol: <input dojoType="ValidationTextBox" required="true"
            			id="stockInput">
            			<p />
            			<button dojoType="Button2" widgetId="stockButton">
            Get Stock Data
            </button>
            			<div id="resultArea" />
            		</div>
            	</div>
            </div>
            </body>
            </html>
            	

          3. StockClientController.js 非常關鍵。在腳本的開頭,使用 dojo.require 方法加載所需的小部件,然后初始化 Dojo 環境,如清單 14 所示。

            清單 14. 初始化 Dojo 環境的 StockClientController
            //require statements
            dojo.require("dojo.widget.*" );
            dojo.require("dojo.event.*");
            dojo.require("dojo.widget.Button2");
            dojo.require("dojo.widget.FloatingPane" );
            	
            //all dojo.require above this line
            dojo.hostenv.writeIncludes(); 
            dojo.require();	
            	

          操作前后需要考慮的事項

          在 Ajax 中,需要考慮的一件事是,在觸發事件之前,不要顯示某些用戶界面。不過,一種做法是放置 div 標記作為占位符。然后,可以使用 DOM 或 Dojo API 訪問此區域,并添加動態 UI 元素。在我們的應用程序中,我添加了一個簡單的 div,以獲得以下結果:

          <div id="resultArea" />

          附加樣式表

          接下來,使用 CSS 添加樣式。CSS 是設置 Ajax 應用程序格式的標準方法。使用 CSS,您可以將樣式定義應用于多個 div 標記,方法是將標記的 class 屬性設置為該樣式的名稱。這允許您重用樣式定義。清單 15 顯示了我使用的樣式表:


          清單 15. 在 UI 中使用的樣式表
          @CHARSET "ISO-8859-1";
          
          .layout
          {
          	width: 100%;
          	height: 80%;
          }
          	
          .stockContent
          {
          	width: 100%; 
          	height: 90%;
          	background-color: #F0F0F0 ; 
          	padding: 10px;
          }
          	
          .stockPane
          {
          	width: 40%; 
          	height: 250px;
          }
          	
          .exceptionMsg
          {
          	color: #FF0000;
          }
          	

          服務視圖

          接下來,一個好的想法是確保 UI 開發人員在 JavaScript 中擁有一個服務視圖。Dojo 使用 SMD 來做到這一點,如前面所述。用于 Java 的 JSON-RPC 為我們提供了直接從 JavaScript 調用 Java 服務的能力,如清單 16 所示:


          清單 16. 直接調用 Java 服務的 JavaScript
          <script type="text/javascript" src="../jsonrpc.js"></script>
          jsonrpc.StockService.getStockData(stockResultCallBack,stockButton.value);
          	

          構建請求事件處理程序

          接著,在控制器 JS 文件中,我們需要創建事件處理程序和回調處理程序。回調處理程序應是其他工作的 Facade。在我們的示例中,事件處理程序將異步調用我們的服務,并將回調傳遞到相應的方法。XMLHttpRequest 對象的此抽象由 JSON-RPC-Java 提供。在接收到響應時,回調委派給呈現,如清單 17 所示:


          清單 17. 控制器文件中的回調和事件處理程序
          function stockResultCallBack(result,exception) {
          	try {
          		renderStockResult(result,exception);
          	} catch(e) {
          		alert(e);
              } 	    
          }
          
          function submitStock()
          	{
             	try {
          		jsonrpc = new JSONRpcClient("/DojoJ2EE/JSON-RPC");
          		var stockButton = dojo.byId('stockInput');
          		jsonrpc.StockService.
          			getStockData(stockResultCallBack,stockButton.value);
          	} 
          	catch(e) {
          		alert(e);
          	}
          }
          	

          在加載時加載初始 UI 和網絡請求事件

          下面,我們在頁面初始化時使用 Dojo 這種有力的工具,將小部件連接到請求處理程序。請參見清單 18 中的 init 方法。dojo.addOnLoad() 方法允許您使用同一面向方面的技術,將 init 方法附加到頁面加載事件。


          清單 18. init() 方法
          function init()
          	{
          	var stockButton = dojo.widget.byId('stockButton');
          	dojo.event.connect(stockButton, 'onClick', 'submitStock');
          	}
          dojo.addOnLoad(init);
          	

          呈現響應

          最后一步是添加動態呈現響應代碼。我將它放置在獨立呈現器 JS 文件中。您可以使用各種方法來呈現響應。在我們的示例中,我們將結合使用 DOM API 和 Dojo 實用工具來構建簡單的表。在這里,我們可以使用 Dojo 的小部件之一,但是我希望對清單 19 中的函數 renderStockResult 使用自已的代碼,以便突出顯示一些 Dojo 實用工具和數據結構。

          要創建呈現響應代碼,請執行下列操作:

          1. renderStockResult 函數中,使用 dojo.byId() 方法訪問 resultArea 對象。
          2. 檢查任何異常;如果 renderStockResult 含有傳遞給它的異常,它會將該異常傳遞到錯誤處理程序并返回。
          3. 使用 Dictionary(類似于 Java HashMap)和 ArrayList Dojo 結構來存放 result 數據。
          4. 將結構化數據傳遞到通用表創建者方法。

          清單 19. 呈現響應方法
          dojo.require("dojo.collections.*");
          dojo.require("dojo.fx.*");
          
          function renderStockResult(result,exception)
          {
          	var resultArea = dojo.byId('resultArea');
          	if(exception)
          	{
          		handleStockError(resultArea,exception);
          		return;
          	}
          	
          	var symbolHeader = "Symbol:";
          	var priceHeader = "Price:";
          	var companyNameHeader = "Company Name:";
          	
          	var headers = new dojo.collections.ArrayList();
          	headers.add(symbolHeader);
          	headers.add(priceHeader);
          	headers.add(companyNameHeader);
          	
          	var column = new dojo.collections.Dictionary();
          	
          	column.add(symbolHeader,result.symbol);
          	column.add(priceHeader,result.price);
          	column.add(companyNameHeader,result.companyName);
          	
          	var data = new dojo.collections.ArrayList();
          	
          	data.add(column);
          	
          	createTableWithVerticleHeading(resultArea,headers,data);
          		
          }
          	

          設置了數據結構之后,調用具體的 createTableWithVerticleHeading 方法。實際上,此類實用工具將會被外部化。在下面顯示的方法中,我們將使用 Dojo Iterator 對象來遍歷這些數據結構并創建表。我要在下面指出的另一個方法是 dojo.fx.html.fadeShow(table, 200),您可以使用該方法將淡入效果添加到結果的打印中。這只是某些動畫的一瞬。在清單 20 中,Dojo 代碼為粗體。


          清單 20. 表創建方法
          function createTableWithVerticleHeading(root,headers,data)
          {
          	
          	var oldResult = dojo.byId('resultTable');
          	if(oldResult)
          	{
          		root.removeChild(oldResult);
          	}
          	var exceptionMsg = dojo.byId('stockExceptionMsg');
          	if(exceptionMsg)
          	{
          		resultArea.removeChild(exceptionMsg);
          	}
          	var table = document.createElement("table");
          	dojo.fx.html.fadeShow(table, 200);
          	table.setAttribute("id","resultTable");
          	
          	root.appendChild(table);
          	var headerIter = headers.getIterator();
          	
          	
          	while(!headerIter.atEnd())
          	{
          		var row = document.createElement("tr");
          		table.appendChild(row);
          		var element = document.createElement("th");
          		element.setAttribute("align","left");
          		row.appendChild(element);
          		var header = headerIter.get();
          		var dataElement = document.createTextNode(header);
          		element.appendChild(dataElement);
          		var dataIter = data.getIterator();
          		while(!dataIter.atEnd())
          		{
          			var resultItem = dataIter.get();
          			var item = resultItem.item(header);
          			var elementItem = document.createElement("td");
          			elementItem.setAttribute("align","left");
          			row.appendChild(elementItem);
          			var dataText = document.createTextNode(item);
          			elementItem.appendChild(dataText);
          		} 	
          	}
          }
          	

          最后,我們將添加簡單的錯誤處理方法,以打印錯誤消息,如清單 21 所示。請記住,通過在元素上設置類屬性,然后委派給 CSS 文件,可添加粗體文本。


          清單 21. 錯誤處理方法
          function handleStockError(resultArea,exception)
          {
          	var oldResult = dojo.byId('resultTable');
          	if(oldResult)
          	{
          		resultArea.removeChild(oldResult);
          	}
          	var exceptionMsg = dojo.byId('stockExceptionMsg');
          	if(exceptionMsg)
          	{
          		resultArea.removeChild(exceptionMsg);
          	}
          	var error = document.createElement("h4");
          	error.setAttribute("class","exceptionMsg");
          	error.setAttribute("id","stockExceptionMsg");
          	var errorText = document.createTextNode(exception.message);
          	resultArea.appendChild(error);
          	error.appendChild(errorText);
          	
          	return;
          }
          

          測試應用程序

          您可以下載應用程序的最終 WAR 文件。可將其安裝在任何應用服務器(如 WebSphere Application Server)上。部署了應用程序后,您可以打開 HTML 頁,以查看浮點形式,如圖 10 所示:


          圖 10. HTML 中的浮點形式
          HTML 中的浮點形式

          可以自由移動該形式。您可能注意到,我已將浮點綁定到外部容器,如圖 11 所示:


          圖 11. 綁定到外部容器的浮點
          綁定到外部容器的浮點。

          輸入 IBM 以調用 Java EE 應用程序。結果應類似于圖 12 所示的形式:


          圖 12. 將 IBM 輸入到應用程序的結果
          將 IBM 輸入到應用程序的結果。

          接下來,輸入一些其他數據,以測試錯誤處理程序,如圖 13 所示。


          圖 13. 測試錯誤處理程序
          測試錯誤處理程序。

          Dojo 還提供了單元測試套件以自動執行單元測試。





          回頁首


          結束語

          在本文中,我向您介紹了如何使用 Dojo 工具包、JSON 和 JSON-RPC 為 Java EE 應用程序構建 Ajax 客戶端。我概述了每項技術,并介紹了一些設計原則。最后,我提供了一個示例應用程序。Ajax 應用程序將很快成為 SOA 客戶端。通過使用 Dojo 之類的工具包,您可以方便地構建這些網頁。


          引用:http://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/0606_barcia/0606_barcia.html

          posted on 2007-03-06 16:54 whirlyzhq 閱讀(2172) 評論(0)  編輯  收藏 所屬分類: framework


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 大渡口区| 保康县| 老河口市| 梅河口市| 垦利县| 新绛县| 治县。| 榕江县| 军事| 凤城市| 永城市| 韶山市| 马尔康县| 唐海县| 宜城市| 兰考县| 武功县| 林周县| 鲁甸县| 团风县| 上饶县| 建平县| 无锡市| 台中县| 建水县| 洛隆县| 原阳县| 宝坻区| 焉耆| 玉溪市| 界首市| 崇礼县| 奉节县| 乌拉特前旗| 南康市| 名山县| 华池县| 桐乡市| 南雄市| 梓潼县| 宝兴县|