AJAX及使用E4X編寫Web服務指令碼

來源:互聯網
上載者:User
ajax|web|web服務|指令碼  

本文先簡單介紹一下可以用於 XML的 ECMAScript(ECMAScript for XML,E4X),它是一種對 JavaScript 的簡單擴充,這使得編寫 XML 指令碼非常的簡單。在本文中,作者示範了一種稱為非同步 JavaScript 及 XML(Asynchronous JavaScript and XML,AJAX)的 Web 編程模型,並且向您展示 JavaScript 的一些新 XML 擴充是如何使其更易於實現。

用於 XML 的 ECMAScript

您以前可能沒有遇到過這個術語 ECMAScript。它實際上是 JavaScript 的正式名稱。歐洲電腦製造商協會(European Computer Manufacturers Association,ECMA)是制定 JavaScript 標準的標準化組織(同時 C# 和CLR 標準也是該協會制定的)。ECMAScript 標準可以從 ECMA Web 網站免費獲得。

E4X 是 JavaScript 的擴充,它實際上就是在 JavaScript 中添加了對 XML 的直接支援。它同時也是一種 ECMA 標準(查看參考資料——ECMA-357)。那麼它對 XML 的直接支援是什麼呢?為什麼它具有很高的價值?如果您是一名 JavaScript 程式員,那麼您可能已經使用了諸如 Netscape LiveConnect 或者 Rhino (一種運行在 Java™ 下的可以免費獲得的 JavaScript 庫)之類的技術來在您的 JavaScript 中使用這些 Java 庫。這也就意味著您在 XML 庫的協助下已經可以建立、操作和使用 XML。同樣地,如果您使用了 Microsoft® Internet Explorer,那麼您已經通過 Microsoft MSXML2 庫獲得了 XML 的支援。這樣的話,如果您已經使用了那些庫檔案,那麼請做好進行重要變動的準備——E4X 會比它們更簡單和容易。

在我們查看樣本執行個體之前,對該實驗需要注意:此時 E4X 有兩種可用的實現方式。這兩種可用的方式都是來自Mozilla。一種是瀏覽器使用的 C JavaScript 引擎(它是用代碼來命名的 SpiderMonkey),並且在最新的 Mozilla 版本——我們使用 Mozilla 1.8a6 中是可用的。E4X 同樣在 Rhino 中也是可用的。Rhino 是 Java 內建的 JavaScript 解釋程式和編譯器,我們將展示其獨立使用及運行在 Axis 內部的情景。兩者都可以從 Mozilla 獲得。

在這些樣本執行個體中,我們首先從使用 Rhino 的命令列上的 E4X 開始,然後轉向在使用 Mozilla 的瀏覽器內部使用 E4X,同時示範 AJAX 模型。在第二篇文章中,我們將向您展示如何通過將 Rhino 嵌入到 Apache Axis Web 服務引擎中來使用伺服器內部的 E4X。但是在我們轉向 Web 服務之前,先向您展示 E4X 中的 XML 編程基礎。

一個簡單範例

我們首先從一個簡單的執行個體開始。我們首先對錶示作者的相關資訊的 XML 進行分析和操作。我們想得到的 XML 如下所示:

清單 1. 作者 XML 文檔

<people>

<person gender="male">

<name>Ant</name>

<hair>Shaggy</hair>

<eyes>Blue</eyes>

<height measure="metric">176</height>

</person>

<person gender="male">

<name>Paul</name>

<hair>Spiky</hair>

<eyes>Grey</eyes>

<height measure="metric">178</height>

</person>

</people>

如果我們以字串的形式得到了該 XML 文檔,那麼就可以通過以下簡單操作來“解析”該字串:

var x = new XML(peopleXMLString);

另外,我們也可以簡單地將該 XML“嵌入”到代碼中:

var x =

<people>

<person gender="male">

<name>Ant</name>

<hair>Shaggy</hair>

<eyes>Blue</eyes>

<height measure="metric">176</height>

</person>

<person gender="male">

<name>Paul</name>

<hair>Spiky</hair>

<eyes>Grey</eyes>

<height measure="metric">178</height>

</person>

</people>;

通過 Rhino 使用 E4X

如果您同我們的操作完全一樣,那麼現在就可以嘗試該操作。Rhino 1.6R1 最新的版本以及來自 Apache 的 XMLBeans 程式庫都支援 E4X。使用它們非常的簡單,只要擷取這些包,將它們解壓,然後將 js.jar 和 xbean.jar 添加到您的類路徑中,就可以啟動 JavaScript 處理常式了。

java -cp js.jar;xbean.jar

org.mozilla.javascript.tools.shell.Main

您現在可以嘗試以下執行個體。您可以將它們從該處剪下並複製,或者將它們包含在 examples1.js 檔案中,該檔案位於 zip 檔案(ws-ajax1code.zip)中,您可以通過點擊本文頂部或者底部的代碼表徵圖來下載該檔案。

您僅僅需要使用 JavaScript 的屬性就可以查看 XML 的任何部分。例如:

print(x.person[0].name);

Ant

print(x.person[1].hair);

Spiky

您注意到了嗎,到目前為止,我們還沒有使用諸如 DOM 或者 SAX 之類的 XML API。XML 只是變成了一種 JavaScript 能夠理解的本地類型。

使用以下代碼來列印兩個人的高度:

for each (var h in x..height) { print(h) };

176

178

文法非常有用。它返回所有的,任何深度的能夠匹配後面緊跟的標記名稱的子項目。因此 x..height 返回 height 標記的數值。

以下是另一個有用的文法:

print(x.person.(name=="Ant").hair);

Shaggy

這將使得在 XML 樹中可以很容易地進行查看操作。

一個更複雜的樣本執行個體

假定您想要將高度值從米制度量單位更改為英美製度量單位(也就是英國人常說的英尺和英寸單位)。

下面首先是厘米到英寸的轉換...

function metricToImperial(cms) {

var totalinches = Math.round(cms/2.54);

var inch = totalinches%12;

var ft = (totalinches-inch)/12;

var response = <height/>;

response.feet = ft;

response.inches = inch + 2; // we sounded a bit short

response.@measure = "imperial";

return response;

}

首先值得注意的一行是:

var response = <height/>;

該行允許您將 XML “嵌入”到 JavaScript 中。採用這種文法有兩個好處:第一,它確實會使 XML 的使用變得很容易。第二,這些代碼的意義非常清晰。

現在您可以向該元素中添加更多的子項目:

response.feet = ft;

這樣建立了 <height> 子項目,其標記名稱被設定為“feet”,並且將數值設定為變數 ft 的值。

您也可以用這種方式操作其屬性:

response.@measure = "imperial";

現在我們使用該功能來更新 XML:

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");

股票報價用戶端樣本

該指令碼程式屬於 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;

<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。

我們設定了兩個 HTTP 頭資訊——SOAPAction 和 Content-Type——然後使用 xmlhttp.send(xml.toString()) 將 SOAP 信封訊息發送出去。

如果該調用行為是非同步,那麼在調用從該響應建立的 XML 回呼函數之前,它需要等待,直到 readyState 為 4(全部完成)。

因此使用該操作的代碼如下所示:

   var url = document.getElementById("url").value;

   var callback = function(resp) {

alert(resp..*::getQuoteReturn);

}

   execService(url, envelope, callback);

在我們的範例中,我們使用非同步模型。典型的 網頁瀏覽器在與伺服器通話時並不阻塞,並且我們也不希望它那樣。舉例來說,如果我們阻塞了瀏覽器,那麼瀏覽器的視窗可能最終表現為“不響應”狀態,從而促使使用者結束它。

resp..*::getQuoteReturn 如果您是 E4X 新手,那麼需要再次理解該文法。.. 意味著從樹中搜尋命名的元素。*:: 意味著任意的命名空間,因此該數值將是在響應 SOAP 封裝的任意命名空間中被稱為 getQuoteReturn 元素的數值。

實際的樣本代碼 stockclient.html 同樣也顯示了該請求和響應 SOAP 封裝。測試該樣本——您應該看到如下內容:

圖 2. 顯示請求和響應 SOAP 封裝的 stockclient.html

 該 stockclient.html 看上去類似一個傳統的使用提交按鈕的 Web 頁面,儘管它事實上並不是(瀏覽器一直在查看該頁面,從未更改)。我們建立了該檔案,以便您能理解互動行為。但是,真正的 AJAX 版本的頁面要美觀很多。此 stockclientAjax.html 沒有按鈕。隨著您鍵入操作的進行,它會自動地更新股票價格。測試該樣本。



雖然該頁面沒有按鈕,但是只要您停止鍵入操作,它就能自動地做出請求(在做出請求之前,它需要等待 0.6 秒鐘,以便在您停止的時候它能夠“感應”到)。

產生來自 Rhino 的 Web 服務請求

 Rhino 並不支援 XMLHTTPRequest 對象,但是這個問題您不必擔心。因為 Rhino 運行在 Java 環境中,您可以使用 Java 功能來產生 Web 服務請求 。為示範該操作,我們編寫了一個 XMLHttpRequest 對象的簡單 Java 實現。Rhino 允許 Java 程式員發布 Java 語言來擴充它們的 JavaScript 環境。為了使用 Rhino shell 中的 XMLHttpRequest 對象,您只需確保 e4xutils.jar 在自己的類路徑中,然後您就可以使用 shell 命令,defineClass,將其添加到自己的環境中:

>set classpath=.\js.jar;.\xbean.jar;.\e4xutils.jar;.

>java org.mozilla.javascript.tools.shell.Main

Rhino 1.6 release 1 2004 11 30H

js> defineClass('xmlhttp.XMLHttpRequest');

下面有個很簡單的指令碼程式對其進行測試:

>test.js

defineClass("xmlhttp.XMLHttpRequest");

var xh = new XMLHttpRequest();

xh.open("GET",

"http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl",

false);

xh.send(null);

var wsdl = new XML(xh.responseText);

print(wsdl..*::address.@location);

>java org.mozilla.javascript.tools.shell.Main test.js

http://64.124.140.30:9090/soap

結果就是您現在可以使用您已經在 Mozilla 和 Rhino 中寫入(E4X+XMLHttpRequest)的相同的指令碼程式。

結束語

到目前為止,您已經看到了如何使用 E4X 和 Javascript 來初始化 Web 服務請求。

<

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.