ajax|web|web服務|指令碼
for each (var p in x.person) {
if (p.height.@measure=="metric")
p.height=metricToImperial(p.height);
}
print (x);
這裡是輸出內容:
<people>
<person gender="male">
<name>Ant</name>
<hair>Shaggy</hair>
<eyes>Blue</eyes>
<height measure="imperial">
<feet>5</feet>
<inches>11</inches>
</height>
</person>
<person gender="male">
<name>Paul</name>
<hair>Spiky</hair>
<eyes>Grey</eyes>
<height measure="imperial">
<feet>5</feet>
<inches>12</inches>
</height>
</person>
</people>
E4X 中的 XML 命名空間(Namespace)
如果您是一名 XML 高手,那麼此時您可能想知道如何使用該文法來管理 XML 命名空間。這裡有三種方式來實現該操作:
首先,您可以使用內嵌的 XML 文法:
var soapMsg = <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"/>;
print(soapMsg.namespace());
http://www.w3.org/2003/05/soap-envelope
第二個方法是在建立元素之前設定預設的 XML 命名空間:
default xml namespace = new Namespace("http://www.w3.org/2003/05/soap-envelope");
您可以將它設定為空白字串,以便對該預設的命名空間進行重新設定,例如:
default xml namespace = ""
最後一種方法是使用 :: 運算子
var f = new Namespace("http://fremantle.org");
soapMsg.Body.f::GetStockQuote="IBM";
print(soapMsg);
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<frem:GetStockQuote xmlns:frem="http://fremantle.org">
IBM
</frem:GetStockQuote>
</s:Body>
</s:Envelope>
XML 元素排序
E4X 所具有的一個明顯的優點是它完全支援 XML,包括排序功能。許多從 XML 文檔到相應程式設計語言對象的直接映射僅僅支援符合常規對象語義的 XML 語義子集——因此就失去了不僅能夠表示對象而且還表示文檔的功能。但是對本文來說,它是不合適的,只要簡單查看一下該規範就可以看出,E4X XML 對象具有的內建功能能夠對 XML 元素進行細緻準確的排序。
在 XML 中使用 Javascript 運算式
在轉向 Web 服務之前,我們向您介紹的最後一個內容——使用大括弧“{}”。以上我們介紹了“內嵌的”XML。E4X 也允許您重新進入 JavaScript 環境,並且可以包括了計算後的運算式值。例如:
var num = 36;
var p = <paul><age>{num}</age></paul>
print(p);
<paul>
<age>36</age>
</paul>
到目前為止,我們已經介紹了 E4X 的基礎知識,下面我們就可以使用這些基本知識進行以下操作。
使用 E4X 來調用 Web 服務
本節中,我們將描述如何在以下兩個環境中使用 E4X:
1. 使用 XMLHttpRequest 的 Mozilla 1.8
2. Java/Rhino
您可以很容易地在瀏覽器中使用 E4X 來調用 Web 服務。但是這裡存在問題!到目前為止,唯一的支援 E4X 的瀏覽器是 Mozilla 1.8 的專業版。不過我們並沒有將其作為一種可移植的跨瀏覽器的解決方案來推薦,以下的執行個體示範了 E4X 如何以一種簡單的方式來調用 Web 服務。在下一節中,我們將查看運行在 Rhino JavaScript 引擎中的另一種方法。
AJAX
該樣本執行個體顯示了向 SOAP 伺服器發送和接收 SOAP 訊息的瀏覽器。為了實現該操作,我們通過 XMLHttpRequest 對象來使用 E4X 。這個對象非常的有用,而且 Mozilla 和 Internet Explorer 瀏覽器都支援它,它允許運行在瀏覽器內部的指令碼語言在後台中產生 HTTP 請求。實際上,這就是為什麼 Google 的 GMail 能做到任何事情的原因。這種架構最近被命為 Asynchronous JavaScript+XML(AJAX)。
從根本上來說,AJAX 的目的是要通過一種比標準 HTML 和 HTTP 的“頁面”模型更為靈活的方式與伺服器進行互動,以此來提高 Web 頁面的響應能力和可用性。有關這方面一個很好的樣本是 Google Maps beta,它明顯地比以前的映射 Web 網站更具互動性。
令人鼓舞的是,根據新聞報道,結合了 E4X 的 AJAX 的效能更優!我們將向您展示瀏覽器應用的兩種版本。第一個版本示範了互動操作,而第二個版本隱藏了 Web 頁面上的按鈕和內部的工作過程,以此來展示互動性和非同步性。
瀏覽器的安全性
為了示範瀏覽器的安全性,我們使用了 xmethods.net 上可用的標準 Web 服務。但是,這裡還存在一個問題,因為一般來說,瀏覽器的安全性規則不允許指令碼程式或者 Java applet 程式建立網路連接,除非是與產生該頁面的伺服器建立網路連接。否則,您需要有一個監控頁面,它將您的按鍵動作“複製”到另外一個伺服器。
但是您可以避開這種操作。為實現該操作,您需要進行兩步。首先,您必須啟用 Mozilla 配置中的用於指令碼程式的升級特權。(假定您已經下載並安裝了 Mozilla 1.8 beta)。
在該瀏覽器的地址欄中輸入 about:config,然後將 signed.applets.codebase_principal_support 的值從 false 更新為 true。(出於安全性考慮,請記得在完成全部操作後設回原值。)
然後在指令碼程式中,您可以請求使用升級特權。當該指令碼語言運行時,將會提示使用者使用這些特權。程式碼為:
netscape.security.PrivilegeManager.enablePrivilege( "UniversalXPConnect UniversalBrowserAccess");
其它的選擇就是將服務和 Web 頁面部署到諸如 IBM® WebSphere® Application Server 或者 Tomcat 之類的 Web 應用程式伺服器中。例如,這種方式適用 Apache Axis 和 Axis 內建的預設股票報價機樣本執行個體。
股票報價用戶端樣本
該指令碼程式屬於 stockclient.html 的一部分。如果您從本文下載了 ws-ajax1code.zip 檔案,將其中的 zip 內容解壓,然後使用 Mozilla 開啟 stockclient.html,您將會看到如下內容:
圖 1. Mozilla 中的 stockclient.html
為了對其進行驗證,首先單擊 Update URL。該操作通過使用 XMLHttpRequest 對象從 http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl(或者您在 WSDL 框中鍵入的任意 URL)擷取 WSDL 檔案,然後使用 E4X 從那裡擷取連接埠地址 URL。現在單擊 Send,您將會看到 SOAP 請求被填寫了。一兩秒鐘之後,此 SOAP 響應應該同結果欄位一起被更新。我們查看一下這些代碼。
股票報價用戶端的指令碼程式
該指令碼程式帶著對 IBM 的股票價格的 request 調用指定的URL。如果您正在使用 Axis 伺服器,那麼我們建議使用股票行情自動收錄機符號 XXX,這是一種特殊的符號——部署的服務將總是返回一個固定的響應用於該收錄機,而不是產生 Web 請求來得到真正的股票價格——因此使用該符號進行測試會好些。
您必須完成的第一個操作就是定義您希望使用的 E4X:
<script type="text/javascript;e4x=1">
當您按下 Send 按鈕時,該指令碼程式顯示如下:
var s = new Namespace(
"s",
"http://schemas.xmlsoap.org/soap/envelope/");
var envelope = <s:Envelope xmlns:s={s}/>;
envelope.s::Body="";
var body = envelope.s::Body;
該操作對任何的 SOAP 請求都是通用的。它只是簡單地建立了一個 SOAP 信封,而沒有包括任何訊息體。該操作的一個等價實現方式如下所示:
var envelope =
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body/>
</s:Envelope>
但是,前面的代碼會容易些,而且也為您提供了指向主體元素的指標。
下一步是要建立訊息的主體:
var x = new Namespace("x","urn:xmltoday-delayed-quotes");
body.x::getQuote = <x:getQuote xmlns:x={x}/>;
最後,你必須添加正確的符號:
var symbol = document.getElementById("symbol").value;
var getQuote = body.x::getQuote;
getQuote.symbol=symbol;
現在您已經有了一個完全成形的 SOAP 請求訊息。如果您想要測試該訊息信封,那麼需要按照以下操作:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<x:getQuote xmlns:x="urn:xmethods-delayed-quotes">
<symbol>XXX</symbol>
</x:getQuote>
</s:Body>
</s:Envelope>
為了發送它,你必須使用 XMLHTTPRequest 對象。我們建立了一個簡單的輔助函數,以支援使用 XMLHttpRequest 對象來調用使用 E4X 的服務。此 execService 函數不僅支援非同步方式而且也支援同步方式。
function execService(url, xml, callback) {
var xmlhttp = new XMLHttpRequest();
var async=false;
if (arguments.length==3) async=true;
xmlhttp.open("POST", url, async);
xmlhttp.setRequestHeader("SOAPAction", "\"\"")
xmlhttp.setRequestHeader("Content-Type", "text/xml")
if (async) {
var f = function() {
if (xmlhttp.readyState==4) {
callback(new XML(xmlhttp.responseText));
}
}
xmlhttp.onreadystatechange = f;
}
xmlhttp.send(xml.toString());
if (!async) return new XML(xmlhttp.responseText);
}
下面我們來詳細地看看這些代碼。首先,這些代碼支援兩種調用方式。您可以使用其中一種:
XML execService(String url, XML envelope);或者void execService(String url, XML envelope, function callback);
在這種情況下,回呼函數應該是 void callback(XML x)。
於是您可以使用該函數直接調用 XML 服務,並且等待響應,或者您也可以傳送一個函數,使用 XML 響應訊息調用該函數。
該函數基於參數的數量來決定它是非同步還是同步(3 是非同步),然後簡單地使用 XMLHttpRequest 對象以 POST 請求方式來把 XML 訊息放到 HTTP 要求資訊,並把請求發送到指定的 URL。
- Ajax: 一個建立Web應用的新途徑
- Ajax的錯誤處理機制探討(2)
- Ajax的錯誤處理機制探討(1)
- 初次體驗.NET Ajax無重新整理技術
- Rails系統中的AJAX開發技術簡析(4)