曾几何时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