曾幾何時ajax已經遍布大江南北,然而單純的js難于閱讀和debug,dojo的出現,無疑部分地解決了這個問題,加上ide的支持,更是如虎添翼了!引用一篇IBM的文章,看看dojo的應用吧。
以下是引用內容:
使用 Dojo 工具包和 JSON-RPC 構建企業 SOA Ajax 客戶端
|
|
級別: 中級
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 對象是瀏覽器中提供的 JavaScript 對象。(Microsoft? 和 Mozilla 瀏覽器各有自已的版本)。該流程如下所示:
- 頁面調用某個 JavaScript。
- JavaScript 函數創建 XMLHttpRequest 對象。這包括設置要調用的 URL 和 HTTP 請求參數。
- JavaScript 函數注冊回調處理程序。HTTP 響應調用此回調處理程序。
- JavaScript 函數調用
XMLHttpRequest
對象上的 send
方法,該方法接著將 HTTP 請求發送到服務器。
-
XMLHttpRequest
對象立即將控制返回到 JavaScript 方法。此時,用戶可以繼續使用該頁面。
- 稍后,HTTP 服務器通過調用回調處理程序返回 HTTP 響應。
- 回調處理程序可以訪問 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 構建在兩種結構的基礎上:
- 名稱/值對的集合。在不同的語言中,它被實現為對象、記錄、結構、字典、哈希表、有鍵列表或者關聯數組。
- 值的有序列表。在大多數語言中,它被實現為數組、向量、列表或序列。
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。
通知是沒有響應的特殊請求。它與帶有一個異常的請求對象具有相同的屬性:
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 應用程序之間的理想生態系統
在服務器端,業務和門戶功能現在被公開為某一類型的服務接口。在服務的形式下,應遵循正確的服務器端最佳實踐。服務器應用程序應公開過程粒度服務。JavaServer Faces 之類的框架現在負責執行初始呈現;不過,對于客戶端 Ajax 工具包,這是可選的。
在瀏覽器上,分離關注的內容非常重要。圖 3 突出顯示了 Java 服務器文件結構:
圖 3. Java 服務器文件結構
您可以選擇每頁有一個 JavaScript 控制器。不過,對于復雜的門戶頁,您可以將相關事件分組成小型的控制器集。
控制器文件應:
- 向小部件加載網絡請求處理程序,如圖 4 所示:
圖 4. 將請求處理程序附加到小部件

- 實現請求處理程序。請求處理程序不應有太多的邏輯。它們應委派給服務 Facade,以便與后端交互。
- 實現回調處理程序方法。回調應將呈現委派給獨立 JS 文件。此外,它們應將存儲中間狀態的工作委派給獨立 Java 服務器文件。對于無狀態交互,可以直接將結果傳遞到 rendering.js 文件。
圖 5 說明了組件之間的流:
圖 5. 從客戶端到請求處理程序,再到回調處理程序的信息流
呈現文件包含呈現組件的邏輯或基于事件結果的用戶界面。
Business Facades 應包含代理服務器請求的方法。DataCopy 應維護需要本地保存在瀏覽器中的本地視圖對象。
為 Dojo 設置 Java EE 應用程序
對于 Dojo,您必須添加 JavaScript 文件作為 Web 應用程序的一部分。您可以將 dojo 文件夾復制到 Web 應用程序文件夾,如圖 6 所示:
圖 6. 添加使用 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 文件
為了使 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 的服務模型
我們使用了一個簡單的硬編碼實現,如清單 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:
- 加載腳本:
- dojo
- jsonrpc
- StockClientController
- resultRenderer
- 構建頁面,并結合使用
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>
|
- 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 實用工具和數據結構。
要創建呈現響應代碼,請執行下列操作:
- 在
renderStockResult
函數中,使用 dojo.byId()
方法訪問 resultArea
對象。
- 檢查任何異常;如果
renderStockResult
含有傳遞給它的異常,它會將該異常傳遞到錯誤處理程序并返回。
- 使用
Dictionary
(類似于 Java HashMap
)和 ArrayList
Dojo 結構來存放 result
數據。
- 將結構化數據傳遞到通用表創建者方法。
清單 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 中的浮點形式
可以自由移動該形式。您可能注意到,我已將浮點綁定到外部容器,如圖 11 所示:
圖 11. 綁定到外部容器的浮點
輸入 IBM
以調用 Java EE 應用程序。結果應類似于圖 12 所示的形式:
圖 12. 將 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