一、瞭解Ajax
1.1 什麼是Ajax?
AJAX = 異步 JavaScript 和 XML(Asynchronous JavaScript and XML)。是一種用於創建快速動態網頁的技術。通過在後臺與服務器進行少量數據交換,AJAX 可以使網頁實現異步更新。這意味着可以在不重新加載整個網頁的情況下,對網頁的某部分進行更新。而傳統的網頁(不使用 AJAX)如果需要更新內容,必需重載整個頁面。
簡短地說,在不重載整個網頁的情況下,AJAX 通過後臺加載數據,並在網頁上進行顯示。
二、Ajax的工作原理
Ajax的原理簡單來說通過XmlHttpRequest對象來向服務器發異步請求,從服務器獲得數據,然後用javascript來操作DOM而更新頁面。這其中最關鍵的一步就是從服務器獲得請求數據。要清楚這個過程和原理,我們必須對 XMLHttpRequest有所瞭解。
XMLHttpRequest是ajax的核心機制,它是在IE5中首先引入的,是一種支持異步請求的技術。簡單的說,也就是javascript可以及時向服務器提出請求和處理響應,而不阻塞用戶。達到無刷新的效果。
AJAX是基於現有的Internet標準,並且聯合使用它們:
- XMLHttpRequest 對象 (異步的與服務器交換數據)
- JavaScript/DOM (信息顯示/交互)
- CSS (給數據定義樣式)
- XML (作爲轉換數據的格式)、JSON
三、Ajax get/post實例
3.1 Ajax開發步驟
- 建XMLHTTPRequest對象
- 設置onreadystatechange回調函數(回調函數中的參數data是用來跨域獲取數據的)
- open() 打開連接
- send() 發送請求
注意:回調函數中的data參數,在進行跨域的時候,我們需要獲取對應接口的數據並對數據進行相應的處理,那麼就可以通過接口所提供的回調函數通過傳參來獲取數據。
3.2 get實例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Ajax.Get</title>
</head>
<body>
<script type="text/javascript">
//1.創建異步XMLHttpRequest對象
function createXMLHttpRequest() {
var xmlHttp;
try {
xmlHttp = new XMLHttpRequest();
} catch (e) {
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}
var xhr = createXMLHttpRequest();
//2.設置回調函數
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var responseText = xhr.responseText;
var jsObject = eval("(" + responseText + ")");
console.log(jsObject.flag);
console.log(jsObject.msg);
}
};
//3.打開連接
xhr.open("get", "${pageContext.request.contextPath}/test?username=ziph&password=123456&id=" + Math.random(), true);
//4.發送參數
xhr.send();
</script>
</body>
</html>
3.3 post實例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Ajax.post</title>
</head>
<body>
<script type="text/javascript">
//1.創建異步XMLHttpRequest對象
function createXMLHttpRequest() {
var xmlHttp;
try {
xmlHttp = new XMLHttpRequest();
} catch (e) {
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
}
}
}
return xmlHttp;
}
var xhr = createXMLHttpRequest();
//2.設置回調函數
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var responseText = xhr.responseText;
var jsObject = eval("(" + responseText + ")");
console.log(jsObject.flag);
console.log(jsObject.msg);
}
}
//3.打開連接
xhr.open("post", "${pageContext.request.contextPath}/test", true);
//4.設置請求頭
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//5.發送參數
xhr.send("username=ziph&password=123456");
</script>
</body>
</html>
3.4 實例Servlet測試
package com.mylifes1110.java.servlet;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@WebServlet(name = "TestServlet", value = "/test")
public class TestServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("username : " + username + " , password : " + password);
boolean flag = true;
String msg = "賬戶可用";
if ("root".equals(username) || "zhangsan".equals(username)) {
flag = false;
msg = "賬戶已經被註冊";
} else {
msg = "賬戶可用";
flag = true;
}
Map<String, Object> map = new HashMap<>();
map.put("flag", flag);
map.put("msg", msg);
response.setContentType("text/html;charset=utf-8");
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writeValueAsString(map);
response.getWriter().write(jsonStr);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
四、分佈式解析Ajax步驟
這是之間簡單的羅列以下,講解步驟中會詳細講到!
屬性 | 描述 |
---|---|
onreadystatechange | 每次狀態改變所觸發事件的事件處理程序 |
responseText | 從服務器進程返回數據的字符串形式 |
responseXML | 從服務器進程返回的DOM兼容的文檔數據對象 |
status | 從服務器返回的數字代碼,比如常見的404(未找到)和200(已就緒) |
status Text | 伴隨狀態碼的字符串信息 |
readyState | 對象狀態值(XMLHttpRequest對象的處理狀態) |
4.1 創建XMLHttpRequest對象
XMLHttpRequest對象是AJAX的基礎。所有現代瀏覽器均支持 XMLHttpRequest 對象(IE5 和 IE6 使用 ActiveXObject)。XMLHttpRequest 用於在後臺與服務器交互數據。這意味着可以在不重新加載整個網頁的情況下,對網頁的某部分進行更新。
所有現代瀏覽器(IE7+、Firefox、Chrome、Safari 以及 Opera)均內建 XMLHttpRequest 對象。創建 XMLHttpRequest 對象的語法:
var xmlhttp = new XMLHttpRequest();
Internet Explorer 使用 ActiveX 對象:
var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
Internet Explorer 老版本則也是使用 ActiveX 對象:
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
所以,綜上所述,我們爲了應對所有的現代瀏覽器,包括 IE5 和 IE6,請檢查瀏覽器是否支持 XMLHttpRequest 對象。如果支持,則創建 XMLHttpRequest 對象。如果不支持,則創建 ActiveXObject (封裝方法):
function createXMLHttpRequest() {
var xmlHttp;
try {
xmlHttp = new XMLHttpRequest();
} catch (e) {
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}
4.2 onreadystatechange回調函數(監聽狀態)
當請求被髮送到服務器時,我們需要執行一些基於響應的任務。每當 readyState 改變時,就會觸發 onreadystatechange 事件。readyState 屬性存有 XMLHttpRequest 的狀態信息。
下面是 XMLHttpRequest 對象的三個重要的屬性:
屬性 | 描述 |
---|---|
onreadystatechange | 存儲函數(或函數名),每當 readyState 屬性改變時,就會調用該函數。 |
readyState | 存有 XMLHttpRequest 的狀態。從 0 到 4 發生變化。0: 請求未初始化、1: 服務器連接已建立、2: 請求已接收、3: 請求處理中、4: 請求已完成,且響應已就緒 |
status | 200:“OK”;404:未找到頁面 |
在 onreadystatechange 事件中,我們規定當服務器響應已做好被處理的準備時所執行的任務。
注意: onreadystatechange 事件被觸發 4 次, 五個狀態(0 - 4),對應着 readyState 的每個變化。
注意: 回調函數中的data參數,在進行跨域的時候,我們需要獲取對應接口的數據並對數據進行相應的處理,那麼就可以通過接口所提供的回調函數通過傳參來獲取數據。
當 readyState 等於 4 且狀態爲 200 時,表示響應已就緒:
xhr.onreadystatechange = function(data){
if (xhr.readyState == 4 && xhr.status == 200) {
//這裏寫響應成功後的代碼
var responseText = xhr.responseText;
var jsObject = eval("(" + responseText + ")");
console.log(jsObject.flag);
console.log(jsObject.msg);
}
};
readyState的狀態的詳細解釋
XMLHttpRequest對象的處理狀態
- 0(未初始化):對象已建立,但是尚未初始化(尚未調用open方法)
- 1(初始化):對象開始發送請求,對象已建立,尚未調用send方法
- 2(發送數據):對象的請求發送完成,send方法已調用,但是當前的狀態及http頭未知
- 3(數據傳輸):對象開始讀取服務器的響應,已接收部分數據,因爲響應及http頭不全,這時通過responseBody和responseText獲取部分數據會出現錯誤,
- 4(完成):對象讀取服務器響應完成,數據接收完畢,此時可以通過通過responseXml和responseText獲取完整的迴應數據
4.3 XMLHttpRequest請求
如需將請求發送到服務器,我們使用 XMLHttpRequest 對象的 open() 和 send() 方法:
xmlhttp.open("GET","servlet",true);
xmlhttp.send();
方法 | 描述 |
---|---|
open(method,url,async) | 規定請求的類型、URL 以及是否異步處理請求。method:請求的類型;GET 或 POSTurl:文件在服務器上的位置async:true(異步)或 false(同步) |
send(string) | 將請求發送到服務器。string:僅用於 POST 請求 |
method-請求方式
GET 還是 POST?
與 POST 相比,GET 更簡單也更快,並且在大部分情況下都能用。
然而,在以下情況中,請使用 POST 請求:
- 不使用緩存文件(更新服務器上的文件或數據庫)
- 向服務器發送大量數據(POST 沒有數據量限制)
- 發送包含未知字符的用戶輸入時,POST 比 GET 更穩定也更可靠
GET 請求
一個簡單的 GET 請求:
xmlhttp.open("GET","/servlet",true);
xmlhttp.send();
在上面的例子中,您可能得到的是緩存的結果。
爲了避免這種情況,請向 URL 添加一個唯一的 ID:
xmlhttp.open("GET","/xxx/xxx/xxx/servlet??id=" + Math.random(),true);
xmlhttp.send();
如果希望通過 GET 方法發送信息,請向 URL 添加信息:
xmlhttp.open("GET","/xxx/xxx/xxx/servlet?username=ziph&password=123456",true);
xmlhttp.send();
POST 請求
一個簡單 POST 請求
xmlhttp.open("POST","/xxx/xxx/xxx/servlet",true);
xmlhttp.send();
如果需要像 HTML 表單那樣 POST 數據,請使用 setRequestHeader() 來添加 HTTP 頭。然後在 send() 方法中規定您希望發送的數據:
xmlhttp.open("POST","/xxx/xxx/xxx/servlet",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded;charset=utf-8");
xmlhttp.send("username=ziph&password=123456");
方法 | 描述 |
---|---|
setRequestHeader(header,value) | 向請求添加 HTTP 頭。header: 規定頭的名稱 value: 規定頭的值 |
url - 服務器地址
open() 方法的 url 參數是服務器上資源的地址:
xmlhttp.open("GET","servlet",true);
異步 - True 或 False
AJAX 指的是異步 JavaScript 和 XML(Asynchronous JavaScript and XML)。
XMLHttpRequest 對象如果要用於 Ajax 的話,其 open() 方法的 async 參數必須設置爲 true:
xmlhttp.open("GET","/xxx/xxx/xxx/servlet",true);
對於 web 開發人員來說,發送異步請求是一個巨大的進步。很多在服務器執行的任務都相當費時。Ajax 出現之前,這可能會引起應用程序掛起或停止。
通過 Ajax,JavaScript 無需等待服務器的響應,而是:
- 在等待服務器響應時執行其他腳本
- 當響應就緒後對響應進行處理
Async=true
當使用 async=true 時,請規定在響應處於 onreadystatechange 事件中的就緒狀態時執行的函數:
xmlhttp.onreadystatechange = function(data)
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//成功後的執行代碼
}
}
xmlhttp.open("GET","/xxx/xxx/xxx/servlet",true);
xmlhttp.send();
Async=false
如需使用 async=false,請將 open() 方法中的第三個參數改爲 false:
我們不推薦使用 async=false,但是對於一些小型的請求,也是可以的。
請記住,JavaScript 會等到服務器響應就緒才繼續執行。如果服務器繁忙或緩慢,應用程序會掛起或停止。
**注意:**當您使用 async=false 時,請不要編寫 onreadystatechange 函數。把代碼放到 send() 語句後面即可:
xmlhttp.open("GET","/xxx/xxx/xxx/servlet",false);
xmlhttp.send();
//執行代碼
4.4 XMLHttpRequest響應
服務器響應
如需獲得來自服務器的響應,請使用 XMLHttpRequest 對象的 responseText 或 responseXML 屬性。
屬性 | 描述 |
---|---|
responseText | 獲得字符串形式的響應數據。 |
responseXML | 獲得 XML 形式的響應數據。 |
responseText 屬性
如果來自服務器的響應並非 XML,請使用 responseText 屬性。
responseText 屬性返回字符串形式的響應,因此可以這樣使用:
document.getElementById("myDiv").innerHTML = xmlhttp.responseText;
responseXML 屬性
如果來自服務器的響應是 XML,而且需要作爲 XML 對象進行解析,請使用 responseXML 屬性:
xmlDoc = xmlhttp.responseXML;
txt = "";
x = xmlDoc.getElementsByTagName("ARTIST");
for (i = 0;i < x.length;i++)
{
txt = txt + x[i].childNodes[0].nodeValue + "<br>";
}
document.getElementById("myDiv").innerHTML=txt;