ajax如何從伺服器端返回xml資料

來源:互聯網
上載者:User

原始的Ajax:直接使用XmlHttpRequest

如上所述,Ajax的核心是JavaScript對象XmlHttpRequest。下面的樣本文章評價系統將帶您熟悉Ajax的底層基本知識:http://tearesolutions.com/ajax-demo/raw-ajax.html。註:如果您已經在本地WebLogic容器中安裝了ajax-demo.war,可以導航到http://localhost:7001/ajax-demo/raw-ajax.html,

瀏覽應用程式,參與投票,並親眼看它如何運轉。熟悉了該應用程式之後,繼續閱讀,進一步瞭解其工作原理細節。
首先,您擁有一些簡單的錨點標記,它串連到一個JavaScriptcastVote(rank)函數。

function castVote(rank) {
var url = "/ajax-demo/static-article-ranking.html";
var callback = processAjaxResponse;
executeXhr(callback, url);
}

該函數為您想要與之通訊的伺服器資源建立一個URL並調用內建函式executeXhr,提供一個回調JavaScript函數,一旦伺服器響應可用,該函數就被執行。由於我希望它運行在一個簡單的Apache環境中,“cast vote URL”只是一個簡單的HTML頁面。在實際情況中,被調用的URL將記錄票數並動態地呈現包含投票總數的響應。
下一步是發出一個XmlHttpRequest請求:

function executeXhr(callback, url) {
// branch for native XMLHttpRequest object
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = callback;
req.open("GET", url, true);
req.send(null);
} // branch for IE/Windows ActiveX version
else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange = callback;
req.open("GET", url, true);
req.send();
}
}
}


如您所見,執行一個XmlHttpRequest並不簡單,但非常直觀。和平常一樣,在JavaScript領域,大部分的工作量都花在確保瀏覽器安全色方面。在這種情況下,首先要確定XmlHttpRequest是否可用。如果不能用,很可能要使用Internet Explorer,這樣就要使用所提供的ActiveX實現。

executeXhr()方法中最關鍵的部分是這兩行:

req.onreadystatechange = callback;
req.open("GET", url, true);

第一行定義了JavaScript回呼函數,您希望一旦響應就緒它就自動執行,而req.open()方法中所指定的“true”標誌說明您想要非同步執行該請求。
一旦伺服器處理完XmlHttpRequest並返回給瀏覽器,使用req.onreadystatechange指派所設定的回調方法將被自動調用。

function processAjaxResponse() {
// only if req shows "loaded"
if (req.readyState == 4) {
// only if "OK"
if (req.status == 200) {
502 502'votes').innerHTML = req.responseText;
} else {
alert("There was a problem retrieving the XML data:
" +
req.statusText);
}
}
}

該代碼相當簡潔,並且使用了幾個幻數,這使得難以一下子看出發生了什麼。為了弄清楚這一點,下面的表格列舉了常用的XmlHttpRequest對象屬性。

屬性


描述

onreadystatechange


每次狀態改變所觸發事件的事件處理常式

readyState


對象狀態值:

* 0 = 未初始化(uninitialized)
* 1 = 正在載入(loading)
* 2 = 載入完畢(loaded)
* 3 = 互動(interactive)
* 4 = 完成(complete)

responseText


從伺服器處理序返回的資料的字串形式

responseXML


從伺服器處理序返回的DOM相容的文檔資料對象

status


從伺服器返回的數字代碼,比如404(未找到)或200(就緒)

statusText


伴隨狀態代碼的字串資訊

現在processVoteResponse()函數開始顯示出其意義了。它首先檢查XmlHttpRequest的整體狀態以保證它已經完成(readyStatus == 4),然後根據伺服器的設定詢問請求狀態。如果一切正常(status == 200),就使用innerHTML 屬性重寫DOM的“votes”節點的內容。

既然您親眼看到了XmlHttpRequest對象是如何工作的,就讓我們利用一個旨在簡化JavaScript與Java應用程式之間的非同步通訊的架構來對具體的細節進行抽象。

Ajax: DWR方式

按照與文章評價系統相同的流程,我們將使用Direct Web Remoting(DWR)架構實現同樣的功能。

假定文章和投票結果儲存在一個資料庫中,使用某種對象/關係映射技術來完成抽取工作。為了部署起來儘可能地簡單,我們不會使用資料庫進行持久性儲存。此外,為使應用程式儘可能通用,也不使用Web架構。相反,應用程式將從一個靜態HTML檔案開始,可以認為它由伺服器動態地呈現。除了這些簡化措施,應用程式還應該使用Spring Framework關聯一切,以便輕鬆看出如何在一個“真實的”應用程式中使用DWR。

現在應該下載應用程式範例並熟悉它。該應用程式被壓縮為標準的WAR檔案,因此您可以把它放置到任何一個Web容器中——無需進行配置。部署完畢之後,就可以導航到http://localhost:7001/ajax_demo/dwr-ajax.html來運行程式。

可以查看HTML 原始碼,瞭解它如何工作。給人印象最深的是,代碼如此簡單——所有與伺服器的互動都隱藏在JavaScript對象ajaxSampleSvc的後面。更加令人驚訝的是,ajaxSampleSvc服務不是由手工編寫而是完全自動產生的!讓我們繼續,看看這是如何做到的。

引入DWR

如同在“原始的Ajax”一節所示範的那樣,直接使用XmlHttpRequest建立非同步請求非常麻煩。不僅JavaScript代碼冗長,而且必須考慮伺服器端為定位Ajax請求到適當的服務所需做的工作,並將結果封送到瀏覽器。

設計DWR的目的是要處理將Web頁面安裝到後端服務上所需的所有資訊管道。它是一個Java架構,可以很輕鬆地將它插入到Web應用程式中,以便JavaScript代碼可以調用伺服器上的服務。它甚至直接與Spring Framework整合,從而允許使用者直接向Web客戶機公開bean。

DWR真正的巧妙之處是,在使用者配置了要向客戶機公開的服務之後,它使用反射來產生JavaScript對象,以便Web頁面能夠使用這些對象來訪問該服務。然後Web頁面只需接合到產生的JavaScript對象,就像它們是直接使用服務一樣;DWR無縫地處理所有有關Ajax和請求定位的瑣碎細節。

讓我們仔細分析一下範例程式碼,弄清它是如何工作的。

應用程式細節:DWR分析

關於應用程式,首先要注意的是,它是一個標準的Java應用程式,使用分層架構(Layered Architecture)設計模式。使用DWR通過JavaScript公開一些服務並不影響您的設計。

下面是一個簡單的Java服務,我們將使用DWR架構直接將其向JavaScript代碼公開:

package com.tearesolutions.service;

public interface AjaxSampleSvc {
Article castVote(int rank);
}

這是一個被簡化到幾乎不可能的程度的例子,其中只有一篇文章可以投票。該服務由Spring管理,它使用的bean名是ajaxSampleSvc,它的持久性需求則依賴於ArticleDao。詳情請參見applicationContext.xml。

為了把該服務公開為JavaScript對象,需要配置DWR,添加dwr.xml檔案到WEB-INF目錄下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 0.4//EN"
"http://www.getahead.ltd.uk/dwr/dwr.dtd">

<dwr>
<allow>
<create creator="spring" javascript="ajaxSampleSvc">
<param name="beanName" value="ajaxSampleSvc" />
</create>
<convert converter="bean" match="com.tearesolutions.model.Article"/>
<exclude method="toString"/>
<exclude method="setArticleDao"/>
</allow>
</dwr>

dwr.xml檔案告訴DWR哪些服務是要直接向JavaScript代碼公開的。注意,已經要求公開Spring bean ajaxSampleSvc。DWR將自動找到由應用程式設定的SpringApplicationContext。為此,必須使用標準的servlet 過濾器ContextLoaderListener來初始化Spring ApplicationContext。
DWR被設定為一個servlet,所以把它的定義添加到web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD
Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<display-name>Ajax Examples</display-name>

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<servlet>
<servlet-name>ajax_sample</servlet-name>
<servlet-class>com.tearesolutions.web.AjaxSampleServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<description>Direct Web Remoter Servlet</description>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>ajax_sample</servlet-name>
<url-pattern>/ajax_sample</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>

做完這些之後,可以載入http://localhost:7001/ajax-demo/dwr,看看哪些服務可用。結果如下:

圖3. 可用的服務
單擊ajaxSampleSvc連結,查看有關如何在HTML頁面內直接使用服務的樣本實現。其中包含的兩個JavaScript檔案完成了大部分的功能:

<script type='text/javascript'
src='/ajax-demo/dwr/interface/ajaxSampleSvc.js'></script>
<script type='text/javascript'
src='/ajax-demo/dwr/engine.js'></script>

ajaxSampleSvc.js是動態產生的:

function ajaxSampleSvc() { }

ajaxSampleSvc.castVote = function(callback, p0)
{
DWREngine._execute(callback, '/ajax-demo/dwr',
'ajaxSampleSvc', 'castVote', p0);
}

現在可以使用JavaScript對象ajaxSampleSvc替換所有的XmlHttpRequest代碼,從而重構raw-ajax.html檔案。可以在dwr-ajax.html檔案中看到改動的結果;下面是新的JavaScript函數:

function castVote(rank) {
ajaxSampleSvc.castVote(processResponse, rank);
}
function processResponse(data) {
var voteText = "

Thanks for Voting!
"
+ "

Current ranking: " + data.voteAverage + " out of 5
"
+ "

Number of votes placed: " + data.numberOfVotes + "
";
502 502'votes').innerHTML = voteText;
}

驚人地簡單,不是嗎?由ajaxSampleSvc對象返回的Article域對象序列化為一個JavaScript對象,允許在它上面調用諸如numberOfVotes()和voteAverage()之類的方法。在動態產生並插入到DIV元素“votes”中的HTML代碼內使用這些資料。

下一步工作

在後續文章中,我將繼續有關Ajax的話題,涉及下面這些方面:

* Ajax最佳實務

像許多技術一樣,Ajax是一把雙刃劍。對於一些用例,其應用程式其實沒有必要使用Ajax,使用了反而有損可用性。我將介紹一些不適合使用的模式,突出說明Ajax的一些消極方面,並展示一些有助於緩和這些消極方面的機制。例如,對Netflix電影瀏覽器來說,Ajax是合適的解決方案嗎?或者,如何提示使用者確實出了一些問題,而再次單擊按鈕也無濟於事?

* 管理跨請求的狀態

在使用Ajax時,最初的文檔DOM會發生一些變化,並且有大量的頁面狀態資訊儲存在用戶端變數中。當使用者跟蹤一個連結到應用程式中的另一個頁面時,狀態就丟失了。當使用者按照慣例單擊Back按鈕時,呈現給他們的是緩衝中的初始頁面。這會使使用者感到非常迷惑!

* 調試技巧

使用JavaScript在用戶端執行更多的工作時,如果事情不按預期方式進行,就需要一些調試工具來協助弄清出現了什麼問題。



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.