AJAX 為 Asynchronous JavaScript and XML 的縮寫。基本上,AJAX 是 Web 應用程式操縱使用者與 Web 網頁之間互動的高效率方式;此方式減少每一次使用者互動所需進行的頁面重新整理及整頁重新載入。因而實現使用瀏覽器來呈現更好的表現方式 (類似於桌面應用程式或外掛 (plugin) 式 Web 應用程式的表現方式)。AJAX 互動係在背景以非同步方式操縱。在此過程中,使用者可以繼續使用頁面。Web 網頁中的 JavaScript 起始 AJAX 互動。當 AJAX 互動完成時,JavaScript 更新頁面的 HTML 來源。變更係立即進行,且不需要進行頁面重新整理。例如,AJAX 互動的用途為:使用伺服器端邏輯來驗證表單項目 (當使用者正在輸入表單項目時);從伺服器擷取詳細資料;動態更新頁面上的資料;以及提交頁面中的局部表單。 特別引人注目的事項在於,AJAX 應用程式不需要分開的外掛程式 (plug-in),並且係平台及瀏覽器中立的程式。即,較舊版瀏覽器也不支援 AJAX。所以,在撰寫用戶端指令檔過程中,必須謹慎考量到瀏覽器之間的差異。 您可考慮使用摘要瀏覽器差異的 JavaScript 程式庫,並且在某些情況下,使用替代互動技術來支援較舊版的瀏覽器。若需詳細資訊,請參閱「AJAX FAQ for the Java Developer」( http://weblogs.java.net/blog/gmurray71/ )。 ■ 何處適合使用 Java 技術? ============================== Java 技術與 AJAX 適當地一起運作。Java 技術處理伺服器端的 AJAX 互動。可以利用 servlet、JavaServer Pages (JSP) 技術、JavaServer Faces (JSF) 技術及 web 服務來處理 AJAX 互動。 處置 AJAX 要求的程式撰寫模型 (Programming Model) 所使用的 API 與傳統 Web 應用程式所使用的 API 相同。可以使用 JSF 技術來建立可重複使用的元件,這些可重複使用的元件產生用戶端 JavaScript 及相對應的伺服器端 AJAX 處理程式碼。接下來介紹使用 AJAX 及 servlet 的範例。 ■ Autocomplete (自動填寫) 範例 ==============================
請想像使用者可搜尋員工資訊的 Web 網頁。頁面包括使用者可輸入員工姓名的欄位。在這個範例中,項目欄位具有自動填寫功能。換言之,使用者可輸入員工姓名的某部分,並且 Web 應用程式列出以所輸入之字元開頭的員工名字或姓氏,藉以嘗試填寫該員工姓名。自動填寫功能省去使用者記得員工的全名,或省去在另一頁面上查看姓名。 在搜尋欄位中實作自動填寫,就是 AJAX 的用途之一。如果您要這樣做,必須在用戶端及伺服器上提供程式碼。 在用戶端上 首先,使用者指定瀏覽器所載入的頁面 URL。在這個範例中,假設頁面是 JSF 產生的 HTML 頁面、servlet 或 JSP 頁面。 頁面包括表單文字欄位,此欄位具有含 JavaScript 函式 doCompletion() 名稱的 onkeyup 屬性 (Attribute)。每次在表單文字欄位中按下按鍵時呼叫此函式。
<input type="text"
size="20"
autocomplete="off"
id="complete-field"
name="id"
onkeyup="doCompletion();">
假設使用者在表單文字欄位中輸入「M」字元。回應動作為,呼叫 doCompletion() 函式,接著此函式初始化 XMLHttpRequest 物件:
function initRequest(url) {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
isIE = true;
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
function doCompletion() {
if (completeField.value == "") {
clearTable();
} else {
var url = "autocomplete?action=complete&id=" +
escape(completeField.value);
var req = initRequest(url);
req.onreadystatechange = function() {
if (req.readyState == 4) {
if (req.status == 200) {
parseMessages(req.responseXML);
} else if (req.status == 204){
clearTable();
}
}
};
req.open("GET", url, true);
req.send(null);
}
}
目前,XMLHttpRequest 物件不屬於標準 JavaScript 部分 (正致力於其標準化),但是事實上是標準且是 AJAX 的心臟。此物件負責透過 HTTP 與伺服器端元件 (在此情況下是servlet) 互動。 當建立 XMLHttpRequest 物件時,請指定三個參數:URL、HTTP 方法 (GET 或 POST) 以及互動是否是非同步。在 XMLHttpRequest 範例中,參數是: URL autocomplete 以及來自 complete-field 的文字 (M 字元):
var url = "autocomplete?action=complete&id=" +
escape(completeField.value);
參數 GET 表明 HTTP 互動使用 GET 方法;以及參數 true 表明互動是非同步:
req.open("GET", url, true);
如果使用非同步呼叫,則必須設定回呼函式 (Callback Function)。當 XMLHttpRequest 上的 readyState 屬性 (property) 變更時,在 HTTP 互動期間的特定時間點,以非同步方式呼叫回呼函式。在這個範例中,回呼函式為 processRequest()。這是設定為函式的 XMLHttpRequest.onreadystatechange 屬性 (property)。請注意,當 readState 係「4」時呼叫 parseMessages 函式。 XMLHttpRequest.readyState 為「4」表示成功完成 HTTP 互動。 當呼叫 XMLHttpRequest.send() 時開始 HTTP 互動。 如果互動是非同步,則瀏覽器繼續處理頁面中的事件。 在伺服器上 XMLHttpRequest 提出對 URL autocomplete 的 HTTP GET 要求,這對應至名為 AutoComplete 的 servlet。 呼叫 AutoComplete servlet 的 doGet() 方法。doGet() 方法類似如下:
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
...
String targetId = request.getParameter("id");
Iterator it = employees.keySet().iterator();
while (it.hasNext()) {
EmployeeBean e = (EmployeeBean)employees.get(
(String)it.next());
if ((e.getFirstName().toLowerCase().startsWith(targetId) ||
e.getLastName().toLowerCase().startsWith(targetId))
&& !targetId.equals("")) {
sb.append("<employee>");
sb.append("<id>" + e.getId() + "</id>");
sb.append("<firstName>" + e.getFirstName() +
"</firstName>");
sb.append("<lastName>" + e.getLastName() +
"</lastName>");
sb.append("</employee>");
namesAdded = true;
}
}
if (namesAdded) {
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.getWriter().write("<employees>" +
sb.toString() + "</employees>");
} else {
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
}
您可以在這個 servlet 中發現到,對於撰寫 AJAX 處理的伺服器端程式碼,您確實不需要學習新知識。如果您想要交換 XML 文件,則必須將回應內容型別 (response content type) 設定為 text/xml設定為。您還可以運用 AJAX 來交換純文字或甚至交換用戶端上的回呼函式可評估或執行的 JavaScript 片段 (snippet)。 請注意,某些瀏覽器可快取結果,所以可能需要將 Cache-Control HTTP 標頭設定為 no-cache。在這個範例中,servlet 所產生的 XML 文件包含所有名字或姓氏以字元 M 開頭的員工。在下列範例中,將 XML 文件傳回至提出呼叫的 XMLHttpRequest 物件:
<employees>
<employee>
<id>3</id>
<firstName>George</firstName>
<lastName>Murphy</lastName>
</employee>
<employee>
<id>2</id>
<firstName>Greg</firstName>
<lastName>Murphy</lastName>
</employee>
<employee>
<id>11</id><firstName>Cindy</firstName>
<lastName>Murphy</lastName>
</employee>
<employee>
<id>4</id>
<firstName>George</firstName>
<lastName>Murray</lastName>
</employee>
<employee>
<id>1</id>
<firstName>Greg</firstName>
<lastName>Murray</lastName>
</employee>
</employees>
傳回至用戶端 提出起始呼叫的 XMLHttpRequest 物件在接收到回應時呼叫 parseMessages() 函式 (如需詳細資訊,請參閱之前在這個範例中的 XMLHttpRequest 初始化)。parseMessages() 函式類似如下:
function parseMessages(responseXML) {
clearTable();
var employees = responseXML.getElementsByTagName(
"employees")[0];
if (employees.childNodes.length > 0) {
completeTable.setAttribute("bordercolor", "black");
completeTable.setAttribute("border", "1");
} else {
clearTable();
}
for (loop = 0; loop < employees.childNodes.length; loop++) {
var employee = employees.childNodes[loop];
var firstName = employee.getElementsByTagName(
"firstName")[0];
var lastName = employee.getElementsByTagName(
"lastName")[0];
var employeeId = employee.getElementsByTagName(
"id")[0];
appendEmployee(
firstName.childNodes[0].nodeValue,
lastName.childNodes[0].nodeValue,
employeeId.childNodes[0].nodeValue);
}
}
parseMessages() 函式接收 AutoComplete servlet 作為參數所傳回之 XML 文件表示的物件。函式利用程式來全面研究 XML 文件,並且接著使用結果來更新 HTML 頁面的內容。達成此目的之方式為,將 XML 文件中姓名的 HTML 來源插入至 id 是「menu-popup」的 |