看看如何在Struts應用中施展AJAX魔法

來源:互聯網
上載者:User
ajax

AJAX是最近在web開發流程中一次革命,它允許在一個普通的web瀏覽器中配置大量的動態效果。多年前Struts 都已經是Java-Web開發中的一個事實上的標準,在大量的應用中都已經使用了它。本文將告訴你,如何在你已經存在Struts應用中結合豐富的AJAX沒Ы湧凇?

本文將介紹在JSP頁面中包含一些JavaScript這樣一個簡單而有效方法來結合AJAX和Struts。在此我們介紹如何重新使用已經存在的Struts actions,但此技術同樣可用於你選擇的其他Java-Web 架構。本方法同樣可平移到Struts或者JSF的下一個版本。

著作權聲明:任何獲得授權的網站,轉載時請務必保留以下作者資訊和連結

作者:Paul Browne;pawenwen(作者的blog:http://blog.matrix.org.cn/page/pawenwen)

關鍵字:Struts;AJAX

什麼是AJAX?

AJAX是“非同步JavaScript和XML”的縮寫。這是一項技術,而不是一個如Struts一樣的架構。為什麼在AJAX周圍會有這麼多的關注呢?這是因為AJAX使web頁面看起來並不像一個平面的文檔,而更像使用者所期望的如案頭應用的動態GUI應用程式。AJAX技術能在很多的瀏覽器上使用(包括IE和Netscape/Mozilla)。它已經為Microsoft(用於Outlook的web用戶端)和Google(使用者Google Maps和Gmail)所使用。

未使用AJAX之前

目前大多數的Struts應用都是標準的“如同一個平面文檔的web頁面”的結構。如果你想模仿一些傳統型應用程式(比如那些使用Java Swing,Visual Basic,或者Delphi建立的應用程式),那麼你有兩個選擇:你可以發送所有的可能作為頁面的一部分被請求的資訊,使用大量的JavaScript來操作其動態顯示(一個很慢並且非企業級Java的方法);或者你可以不改變形式地提交到後台伺服器(一種有效方法) 。AJAX提高給你了融合前面的最佳解決方案:動態頁面,但是大多數的應用是在你的web伺服器的Java程式來處理的。

AJAX 101

AJAX和現有的動態HTML技術非常相似,並在其上增加了一個發送到“後台”伺服器的請求來擷取需要的新的或者更新的資訊。AJAX的機制在其他地方已經有詳細的說明――請查看本文後的Resources來擷取更多。但是你至少需要知道:

1. XMLHttpRequest (如果你使用的是IE瀏覽器的話,則是Microsoft.XMLHTTP的ActiveX的對象)。這些對象,你可以在web頁面中使用JavaScript調用。他們允許你作為背景調用方式來請求web伺服器的內容(例如,在表單提交後,螢幕並不像平時一樣顯示“空白”)。

2. XMLHttpRequest 和Microsoft.XMLHTTP 返回的內容可以作為XML或者文本來處理。JavaScript(在你頁面上的)可以使用請求的新內容來更新頁面。

3. 整個處理過程可以由普通的JavaScript事件來觸發:onclick,onchange,onblur,等。

在你的Struts應用中使用AJAX

你閱讀了本文,然後你會對使用AJAX來建立動態web頁面感興趣,並且想知道如何將它加入到你的Struts應用中。這隻是選擇之一。那麼你會如何選擇呢?

· 等待,知道Struts的下一個版本融合了AJAX技術。如果Struts開發人員準備開發一個新的應用,這或許會是一個好的選擇。再後面,可能會是要求JSF也這樣做――對其本身並不一件壞事,但是對於已經存在的系統這將會帶來最根本的改變。

· 你也可以直接採用新的方法,比如Direct Web Remoting (DWR) 和Ruby on Rails,這些都是專為建立AJAX應用的。如果你考慮不使用Struts來開發web的話,那麼這些都是很又用的架構,並且值得一試。但是,這也同時意味著你必須要重寫你的應用。

· 在你已經存在的Struts應用中增加AJAX。既然AJAX只是一項技術而並非架構,那麼它就很容易融入到Struts中。作為現有的系統,其穩定性(如,保持現有的庫檔案)是相當重要的。所以這個方法被推薦,並且我們將在後面詳細介紹。

我們選擇在Struts應用中增加AJAX的優勢是:

1. 它並不需要任何新的庫檔案或者伺服器代碼;只需要使用現有的Struts庫檔案和action。

2. 解決方案中所有部分――JavaScript,XML,Java和Struts――早已為廣泛所知。

3. 此應用可以一塊一塊地移植到AJAX;我們可以確定哪些部分對使用者有益,並首先將它們更新到動態AJAX顯示。

實現方案

我們如何真正的貫徹我們的選擇呢?我們首先應該注意一個“標準的”(沒有AJAX)Struts應用是如何工作的。在此應用中,一個一般的事件流程如下:

1. 使用點擊超連結或者表單的提交按鈕,使用者發送請求。

2. web伺服器運行處理請求的Struts Action來產生一個web頁面。

3. 瀏覽器顯示web頁面。

4. 當使用者點擊儲存的時候,資訊由Struts架構中一個ActionForm類來轉換並發送到伺服器。

5. 然後,Struts架構調用Struts Action來出來請求(如,儲存資料到資料庫中)。

6. 頁面再一次回傳,處理流程繼續。

現有的Struts應用

一個示範事件流程的簡單Struts應用可以在以下地址下載: struts-non-ajax.zip。此基於Struts的應用,是基於使用者的輸入顯示或者隱藏藍色和綠色的表格。圖1顯示了載入初始頁面的畫面。圖2顯示了使用者輸入值並點擊了提交後的畫面。雖然簡單,但它已經足以表示一個Struts的工作流程。

圖 1. 沒有AJAX的例子:啟動顯示畫面

圖 2. 沒有AJAX的例子:輸入值並點擊了提交

伺服器端的代碼是:一個Struts Action使用struts-config.xml 中定義的值轉寄到(相同的)JSP。這個例子代碼中一些需要注意的地方是:

·struts-config.xml檔案將所有的請求重新導向到http://localhost:8080/struts-non-ajax/(或者和你自己的伺服器相同)的index.jsp。

· index.jsp 包含了一個兩個文字框的Struts form(showBlue和showGreen)。該頁面同樣包含了標籤,但是如同兩個文字框被初始化為空白,標籤之間的內容並不顯示。

· 使用者輸入值(true或者false)並點擊提交按鈕,處理控制(經過Struts架構,讀取struts-config.xml)提交到SampleAction類中。

·SampleAction記錄下值,然後轉寄到index.jsp。一個成熟的Struts應用可能會處理更多的事情,不如儲存或者查詢資料庫等。

· index.jsp 現在重新處理請求;如果ShowBlue或者ShowGreen的值是true,這些表格就顯示出來。

該應用並沒有任何“錯誤”。類似的Struts項目好多年都是這樣做的。但是,我們如何在不添加複雜的JavaScript或者頻繁的表單提交的前提下,為此應用增加動態元素呢?

我們的第一個Struts AJAX應用

觀察下下面的圖3和圖4。第一眼看上去,它們和前面的例子沒有說明區別。它們的不同之處在於,頁面載入後(圖3)然後文字框中的值改變了,表單自動認可而不顯示空白的,然後在圖4中顯示結果。普通的提交按鈕仍然在,你也可以選擇使用它。

圖 3. 頁面載入後的AJAX例子

圖 4. AJAX調用後的AJAX例子

添加AJAX是出奇的容易。伺服器端的代碼和前面的例子是一樣的: 一個Struts的ActionForm來後去資料,一個Struts的Action來執行需要的任務(例如,儲存資料庫)然後轉寄到適當的JSP頁面來顯示結果。

繼續

如果你希望就此停止閱讀(跳過這個例子的工作說明),但是這裡的是和你需要轉換你的Struts應用到一個Struts-AJAX應用同樣的風格:

1. 在你的web頁面中引入一個Ajax.js (該檔案是struts-ajax.zip 例檔案中的一部分)。Ajax.js 包含了所有需要發送和接收AJAX調用的JavaScript方法。

2. 確保你希望在AJAX調用中更新的web頁面的部分包含在標籤中,並且給每個標籤一個id。

3. 當一些事件觸發的時候就更新頁面(例如,文字框的the onchange()方法),調用retrieveURL()方法,通過URL傳遞到需要執行伺服器端處理的Struts Action。

4. 為了頁面的顯示/更新,最簡單的方法是Struts Action轉寄回同樣的頁面。在本例中,showGreen/showBlue 文字框中的onchange()方法來觸發AJAX調用。

JavaScript方法retrieveURL()調用伺服器的Struts(通過URL),擷取JSP響應,然後更新顯示頁面中的 標籤中的部分。就是這麼簡單!

AJAX解決方案的細節

我們將例子變為AJAX-Struts應用的時候,需要三個變化:

1. 增加一個JavaScript方法來完成到伺服器的“背後的”AJAX調用。

2. 增加JavaScript代碼來接收伺服器的響應並更新頁面。

3. 在JSP頁面增加標籤標籤,這個標籤中內容將在AJAX調用中更新。

我們將詳細的說明上面的每一步。

發送AJAX請求到伺服器

有兩個方法(在下面列出)用於發送請求到伺服器。

· retrieveURL()方法獲得伺服器的URL和Struts form。URL用於使用AJAX,form的值用於傳遞到伺服器。

· getFormAsString()方法用於將retrieveURL()中form命名的值組裝成查詢字串,並發送到伺服器。

使用方法很簡單,使用onclick()/onChange()事件來觸發retrieveURL()更新顯示。

在這兩個方法中有一些有趣的東西。

在retrieveURL()方法中,req.onreadystatechange = processStateChange (注意,沒有括弧)這一行來告訴瀏覽器在伺服器響應到達的時候調用processStateChange()方法(該方法將在後面介紹)。retrieveURL()方法中(現在已經是AJAX的標準了)同樣決定是使用IE瀏覽器(ActiveX)還是使用Netscape/Mozilla (XmlHttpRequest) 來實現跨瀏覽器安全色。

getFormAsString()方法將HTML form轉換成字串串連在URL後面(這樣就允許我們發送HTTP GET請求)。這個字串是經過轉換的(比如,空格轉換成%20等),並且是一個Struts能將其組裝成ActionForm的格式(並不需要Struts清楚的明白這個是來之AJAX的請求)。注意,在本例中我們使用HTTP GET,使用HTTP POST的方法也是類似的。

function retrieveURL(url,nameOfFormToPost) {

//將url轉換成字串

url=url+getFormAsString(nameOfFormToPost);

//調用AJAX

if (window.XMLHttpRequest) {

// 非IE瀏覽器

req = new XMLHttpRequest();

req.onreadystatechange = processStateChange;

try {

req.open("GET", url, true);

} catch (e) {

alert("Server Communication Problem\n"+e);

}

req.send(null);

} else if (window.ActiveXObject) {

// IE

req = new ActiveXObject("Microsoft.XMLHTTP");

if (req) {

req.onreadystatechange=processStateChange;

req.open("GET", url, true);

req.send();

}

}

}

getFormAsString() 是一個“私人” 方法,在retrieveURL()中使用。

function getFormAsString(formName){

//設定返回字串

returnString ="";

//取得表單的值

formElements=document.forms[formName].elements;

//迴圈數組,組裝url

//像'/strutsaction.do&name=value'這樣的格式

for(var i=formElements.length-1;i>=0; --i ){

//轉化每一個值

returnString+="&"

+escape(formElements[i].name)+"="

+escape(formElements[i].value);

}

//返回字串

return returnString;

}

根據AJAX的響應更新web頁面

到現在為止,我們學習過了使用JavaScript來完成AJAX調用(前面列出),Struts Action,ActionForm以及JSP(基本沒有變化,只是增加了標籤)。為了完善我們對Struts-AJAX項目的瞭解,我們需要瞭解三個用於根據伺服器返回的結果而更新頁面的JavaScript方法。

· processStateChange(): 該方法在AJAX調用前設定。它在伺服器響應到達後由XMLHttpRequest/Microsoft.XMLHTTP 對象調用。

·splitTextIntoSpan(): 根據響應,迴圈取出數組中的元素組裝成NewContent。

·replaceExistingWithNewHtml(): 根據span元素數組,迴圈搜尋,將裡面的元素調換掉頁面中和它的'someName'相同的中的內容。注意,我們使用的是req.responseText 方法來獲得返回的內容(它允許我們操作任何文本的響應)。與此相對於的是req.responseXml (它的作用更大,但是要求伺服器返回是XHTML或者XML)。

function processStateChange() {

if (req.readyState == 4) { // 完成

if (req.status == 200) { // 響應正常

//將響應的文本分割成Span元素

spanElements =

splitTextIntoSpan(req.responseText);

//使用這些Span元素更新頁面

replaceExistingWithNewHtml(spanElements);

} else {

alert("Problem with server response:\n "

+ req.statusText);

}

}

}

replaceExistingWithNewHtml() 是為processStateChange()使用的“私人”方法。

function replaceExistingWithNewHtml

(newTextElements){

//迴圈newTextElements

for(var i=newTextElements.length-1;i>=0;--i){

//判斷是否以 if(newTextElements[i].

indexOf("-1){

//獲得span的名字- 設定在第一和第二個引號之間

//確認span元素是以下的格式

//NewContent

startNamePos=newTextElements[i].

indexOf('"')+1;

endNamePos=newTextElements[i].

indexOf('"',startNamePos);

name=newTextElements[i].

substring(startNamePos,endNamePos);

//獲得內容-在第一個>標記後的所有內容

startContentPos=newTextElements[i].

indexOf('>')+1;

content=newTextElements[i].

substring(startContentPos);

//現在更新現有的Document中的元素,

// 確保文檔存在該元素

if(document.getElementById(name)){

document.getElementById(name).

innerHTML = content;

}

}

}

splitTextIntoSpan() 是為processStateChange() 使用的“私人”方法。

function splitTextIntoSpan(textToSplit){

//分割文檔

returnElements=textToSplit.

split("")

//處理每個元素

for(var i=returnElements.length-1;i>=0;--i){

//刪除掉第一個span後面的元素

spanPos = returnElements[i].

indexOf("

//如果找到匹配的,獲得span前的內容

if(spanPos>0){

subString=returnElements[i].

substring(spanPos);

returnElements[i]=subString;

}

}

return returnElements;

}

新的控制流程

添加以下的JavaScript代碼到我們的應用中,以下的步驟將在伺服器和瀏覽器中執行。

1. 如同一個普通Struts應用裝載頁面。

2. 使用者改變文字框的值,觸發一個onChange() 事件,調用retrieveURL() 方法。

3. 該JavaScript方法通過發送Struts明白的表單變數(後台)請求到伺服器的Struts Action。

4. 該JavaScript方法同樣設定了第二個JavaScript方法的名字,此方法將到伺服器響應完畢後調用。本例子中,設定為processStateChange() 方法。

5. 如我們所預期的,伺服器響應完畢,調用processStateChange() 方法。

6. JavaScript在(新的)伺服器響應中迴圈取出所有元素。將頁面上存在與獲得元素名字相同的 中的元素替換掉。

在你的應用中設計AJAX

以上描述的JavaScript方法能在大多數的應用中使用,包括比我們的例子複雜得多的。但是,在使用之前,你需要注意以下幾點:

· 避免複製代碼,最好在初始化請求(如,顯示完整的頁面)和AJAX(更新部分頁面)請求中使用相同的Struts Action和JSP。

·在公用的Action(控制器)中,決定JSP頁面(所有的JSP頁面或者其中的一部分)中的一個地區需要傳送到瀏覽器。通過在web伺服器的session或者ActionForm中設定標記來讓JSP頁面知道哪些部分需要提交。

· 在JSP中,使用Struts 或者JSTL標籤來決定提交的HTML地區。

使用AJAX的本例子,可以在以下下載: struts-Ajax.zip

結語

AJAX技術允許我們在建立和使用web應用的時候完全的改變。本文介紹了一個簡單的技術,在現有的Struts應用中增加Struts的處理。它允許我們利用我們已有的東西,不僅僅是代碼,還包括了開發的技能。作為一個好的產品,它同樣允許我們寫出更清晰,更具移植性的Java Struts應用。

資源

·作者的blog:http://blog.matrix.org.cn/page/pawenwen

· Sample code for this article

· Definition of AJAX

· "Using AJAX to Catch JavaScript Errors" (XML.com文章)

· "Developing AJAX Applications the Easy Way" (java.net文章)

· "An Introduction to AJAX" (dev2dev文章)

·"AJAX on Rails" (ONLamp.com文章)

· DWR: Direct Web Remoting Project

· Struts Framework Project

·JSF: Java Server Faces Project

Paul Browne 作為企業級Java顧問為FirstPartners.net 工作已有7年了。



相關文章

聯繫我們

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