了解如何使用 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 的关键部分有:
XMLHttpRequest 对象是关键部分。
XMLHttpRequest 对象是 Ajax 用于进行异步请求的机制。图 1 说明了该流程:
XMLHttpRequest 对象是浏览器中提供的 JavaScript. 对象。(Microsoft™ 和 Mozilla 浏览器各有自已的版本)。该流程如下所示:
通过异步更新页面的 DOM,还可以在本地进行异步请求。
Dojo 使您能够方便地构建动态站点。它提供一个丰富的小部件库,您可以使用它组成页面。您可以使用基于 Dojo 方面的事件系统将事件附加到组件,以创建丰富的交互体验。此外,您可以使用几个 Dojo 库进行异步服务器请求、添加动画效果和浏览存储实用工具等等。
Dojo 提供了您可以用于构建页面的一组丰富的小部件。您可以使用多个方法创建 Dojo 小部件。Dojo 的众多优点之一是它允许您使用标准的 HTML 标记。然后,可以将这些标记用于小部件。这样,HTML 开发人员就可以方便地使用 Dojo,如清单 1 所示:
|
您可以使用 div 标记来定义小部件的位置,而在页面加载或对事件进行响应时 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 不是将硬代码 JavaScript. 事件添加到 html 标记上,而是提供允许您将事件附加到小部件的 API,如清单 3 所示。
function submitStock()
{
...
}
function init()
{
var stockButton = dojo.widget.byId('stockButton');
dojo.event.connect(stockButton, 'onClick', 'submitStock');
}
dojo.addOnLoad(init);
|
通过使用 connect 方法,您可将 JavaScript. 方法连接到小部件。您还可以在 div 节点上附加 dojoAttachEvent,如下所示。某些 HTML 标记没有定义事件,所以这是一个方便的扩展。
|
Dojo 事件系统还允许多个高级功能,如:
有关详细信息,请参见 http://dojo.jot.com/EventExamples。
Dojo 通过抽象特定于浏览器的详细信息,提供了对服务器进行异步请求的简单方法。Dojo 允许您创建数据结构来隐藏详细信息,如清单 5 所示。
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 是一个具有许多功能的丰富库,包括:
有关详细信息,请参见 http://manual.dojotoolkit.org/index.html。
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 可以连续请求和响应。向远程服务发送请求可以调用远程方法。该请求是具有三个属性的单个对象:
当方法调用完成时,服务必须对响应进行应答。此响应是具有三个属性的单个对象:
通知是没有响应的特殊请求。它与带有一个异常的请求对象具有相同的属性:
XML 是一种用于面向服务的体系结构 (SOA) 和数据传输的常见传输。当然,目前许多服务以 SOAP 格式存在。不过,何时将其用于数据传输在 Ajax 社区中存在分岐。JSON 有以下几个优点:
XML 有以下优点:
Dojo 为调用 JSON-RPC 请求提供了抽象层。用于 Dojo 的 JSON-RPC 引入了标准方法描述(Standard Method Description,SMD)的概念。SMD 文件是 JSON-RPC 服务的描述。它允许您以中立方式描述 JSON 调用。清单 6 提供了此类 JSON 调用的示例:
{"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 为远程过程调用定义标准格式,但是不存在对后端技术的标准映射。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 对象的示例:
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 所示。
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 应用程序之间理想生态系统的简要概述。
在服务器端,业务和门户功能现在被公开为某一类型的服务接口。在服务的形式下,应遵循正确的服务器端最佳实践。服务器应用程序应公开过程粒度服务。JavaServer Faces 之类的框架现在负责执行初始呈现;不过,对于客户端 Ajax 工具包,这是可选的。
在浏览器上,分离关注的内容非常重要。图 3 突出显示了 Java 服务器文件结构:
您可以选择每页有一个 JavaScript. 控制器。不过,对于复杂的门户页,您可以将相关事件分组成小型的控制器集。
控制器文件应:
图 5 说明了组件之间的流:
呈现文件包含呈现组件的逻辑或基于事件结果的用户界面。
Business Facades 应包含代理服务器请求的方法。DataCopy 应维护需要本地保存在浏览器中的本地视图对象。
对于 Dojo,您必须添加 JavaScript. 文件作为 Web 应用程序的一部分。您可以将 dojo 文件夹复制到 Web 应用程序文件夹,如图 6 所示:
为 JSON-RPC Java Orb 设置 Java EE 应用程序
为了在应用程序中使用 JSON-RPC Java Orb,您需要在 Web 应用程序的 lib 目录中添加 json-rpc-1.0.jar。还需要将单个 jsonrpc.js 文件添加到 Web 内容文件夹中,如图 7 所示:
为了使 Java EE 应用程序能够接收用于 Java 请求的 JSON-RPC,您必须添加 JSONRPCServlet,如清单 9 所示:
|
Ajax 使 SOA 客户端更完美。在我们的示例中,我们使用了一个简单的 Java 服务。
图 8 是基于 Java 的服务模型:
我们使用了一个简单的硬编码实现,如清单 10 所示:
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 所示:
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 所示:
|
设置了基础结构并公开了服务之后,现在我们可以构建 Web 客户端了。通过 Dojo,我们利用小部件构建网页并利用事件模型。图 9 说明了建议的开发过程:
我将使用此过程演示该示例。
从小部件构建 UI
首先构建 UI。请参见清单 13,了解示例 UI。
创建 UI:
|
//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,以获得以下结果:
附加样式表
接下来,使用 CSS 添加样式。CSS 是设置 Ajax 应用程序格式的标准方法。使用 CSS,您可以将样式定义应用于多个 div 标记,方法是将标记的 class 属性设置为该样式的名称。这允许您重用样式定义。清单 15 显示了我使用的样式表:
@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 所示:
|
构建请求事件处理程序
接着,在控制器 JS 文件中,我们需要创建事件处理程序和回调处理程序。回调处理程序应是其他工作的 Facade。在我们的示例中,事件处理程序将异步调用我们的服务,并将回调传递到相应的方法。XMLHttpRequest 对象的此抽象由 JSON-RPC-Java 提供。在接收到响应时,回调委派给呈现,如清单 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 方法附加到页面加载事件。
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 实用工具和数据结构。
要创建呈现响应代码,请执行下列操作:
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 代码为粗体。
function createTableWithVerticleHeading(root,headers,data)
{
var ldResult = 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 文件,可添加粗体文本。
function handleStockError(resultArea,exception)
{
var ldResult = 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 所示:
可以自由移动该形式。您可能注意到,我已将浮点绑定到外部容器,如图 11 所示:
输入 IBM 以调用 Java EE 应用程序。结果应类似于图 12 所示的形式:
接下来,输入一些其他数据,以测试错误处理程序,如图 13 所示。
Dojo 还提供了单元测试套件以自动执行单元测试。
在本文中,我向您介绍了如何使用 Dojo 工具包、JSON 和 JSON-RPC 为 Java EE 应用程序构建 Ajax 客户端。我概述了每项技术,并介绍了一些设计原则。最后,我提供了一个示例应用程序。Ajax 应用程序将很快成为 SOA 客户端。通过使用 Dojo 之类的工具包,您可以方便地构建这些网页。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/14789789/viewspace-434482/ ,如需转载,请注明出处,否则将追究法律责任。