凤凰涅磐,浴火重生!

超越他人的期望,才能让人感动!

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 阅读(2164) 评论(0)  编辑  收藏 所属分类: framework


只有注册用户登录后才能发表评论。


网站导航: