1、什么是AJAX
AJAX是 “Asynchronous JavaScript and XML” 的簡稱,即異步的JavaScript和XML。
所謂異步,就是提交一個請求不必等待響應回來,可以直接去做其他事情。同步則是提交請求必須等待結果返回才能進行下一步操作。
同時,異步能夠局部刷新頁面,比如網站常見的輸入用戶名后的局部顯示該用戶名是否可用的信息,這種可以更好地提高用戶體驗。
接下來我們回顧一下AJAX的基本用法:
核心對象 XMLHttpRequest,它是瀏覽器內部的對象,可以用來發送HTTP請求和接收HTTP響應。它的實現根據瀏覽器可能有不同,一般創建需要進行條件判斷
if(window.ActiveObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} else if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
5
1
if(window.ActiveObject) {
2
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
3
} else if (window.XMLHttpRequest) {
4
xmlHttp = new XMLHttpRequest();
5
}
XMLHttpRequest的重要屬性
- readyState —— 返回當前請求狀態,用0-5表示
- status —— 返回當前服務器的狀態,用數字(狀態碼)表示,如200、500、404 etc.
- statusText —— 功能同status,不同點在於它以文本的形式進行表示
- onreadystatechange —— 事件觸發器,readyState/status發生變化會觸發該項
- responseText —— 接收服務器端返回的文本內容,以字符串形式存在
- responseXML —— 接收服務器響應,以XML存在,可以解析為一個DOM對象
XMLHttpRequest的重要方法
- open() --> e.g. open("GET", url, true)
- send() --> e.g. send(null)
下面是一個簡單例子
<script type="text/javascript">
var xmlHttp;
//創建XMLHttpRequest對象
function createXMLHttpRequest() {
if(window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHttp");
} else if(window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
}
function validate() {
//todo 編寫Ajax校驗,發送請求和處理,並且顯示信息
//創建createXMLRequest對象
createXMLHttpRequest();
//使用DOM,得到id值是username的域
var username = document.getElementById("username");
var url = "ValidateUsernameCtl?username=" + escape(username.value);
//向服務器端的ValidateUsernameCtl發送異步請求
xmlHttp.open("GET", url, true);
xmlHttp.onreadystatechange = callback;
xmlHttp.send(null);
}
function callback() {
if(xmlHttp.readyState == 4) {
if(xmlHttp.status == 200) {
//以responseXML屬性,接收服務器端返回的xml文件,使用DOM進行解析
var msg = xmlHttp.responseXML.getElementsByTagName("message")[0].firstChild.data;
var passed = xmlHttp.responseXML.getElementsByTagName("passed")[0].firstChild.data;
setMessage(msg, passed);
}
}
}
function setMessage(message, passed) {
var validateMessage = document.getElementById("usernamemsg");
var fontColor = "red";
if(passed == "true") {
fontColor = "green";
}
//對<div name="usernmaesg">的地方設置其間的代碼innerHTML為指定代碼
validateMessage.innerHTML = "<font color=" + fontColor + ">" + message + "</font>";
}
</script>
46
1
<script type="text/javascript">
2
var xmlHttp;
3
4
//創建XMLHttpRequest對象
5
function createXMLHttpRequest() {
6
if(window.ActiveXObject) {
7
xmlHttp = new ActiveXObject("Microsoft.XMLHttp");
8
} else if(window.XMLHttpRequest) {
9
xmlHttp = new XMLHttpRequest();
10
}
11
}
12
13
function validate() {
14
//todo 編寫Ajax校驗,發送請求和處理,並且顯示信息
15
//創建createXMLRequest對象
16
createXMLHttpRequest();
17
//使用DOM,得到id值是username的域
18
var username = document.getElementById("username");
19
var url = "ValidateUsernameCtl?username=" + escape(username.value);
20
//向服務器端的ValidateUsernameCtl發送異步請求
21
xmlHttp.open("GET", url, true);
22
xmlHttp.onreadystatechange = callback;
23
xmlHttp.send(null);
24
}
25
26
function callback() {
27
if(xmlHttp.readyState == 4) {
28
if(xmlHttp.status == 200) {
29
//以responseXML屬性,接收服務器端返回的xml文件,使用DOM進行解析
30
var msg = xmlHttp.responseXML.getElementsByTagName("message")[0].firstChild.data;
31
var passed = xmlHttp.responseXML.getElementsByTagName("passed")[0].firstChild.data;
32
setMessage(msg, passed);
33
}
34
}
35
}
36
37
function setMessage(message, passed) {
38
var validateMessage = document.getElementById("usernamemsg");
39
var fontColor = "red";
40
if(passed == "true") {
41
fontColor = "green";
42
}
43
//對<div name="usernmaesg">的地方設置其間的代碼innerHTML為指定代碼
44
validateMessage.innerHTML = "<font color=" + fontColor + ">" + message + "</font>";
45
}
46
</script>
2、JSON替代XML的優勢
在標題1中我們提到的AJAX中X實際上是XML,這里我們要換成JSON,為什么要采取JSON呢?
1)數據格式比較簡單,易於讀寫,格式都是壓縮的,占用帶寬小;
2)易於解析,客戶端JavaScript可以簡單的通過eval_r()進行JSON數據的讀取。
另外,JSON是趨勢,我們要跟着大勢走,順水推舟,不要沒事就去逆流而上。
3、SSH整合AJAX(JSON)的步驟
網上類似的博客幾乎都是相同的在不停轉載,這個跟我參考的那位網友的感覺是一樣,參考的帖子很少,於是自己也鼓搗了很久才解決。Struts2實際上有多種方式實現AJAX,可以參考博文《
Struts 2三種方式實現Ajax》,這里為了更好地結合JSON,采用了struts2-json插件的方式。
3.1 配置准備
3.1.1 添加jar包
- 添加struts2-json-plugin-x.x.x.x.jar,用來支持struts和ajax-json的集成
如果你是用的Maven方式,你可以直接添加依賴
<!--struts + ajax json //tips struts 整合 ajax json-->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>2.3.16.1</version>
</dependency>
6
1
<!--struts + ajax json //tips struts 整合 ajax json-->
2
<dependency>
3
<groupId>org.apache.struts</groupId>
4
<artifactId>struts2-json-plugin</artifactId>
5
<version>2.3.16.1</version>
6
</dependency>
- 添加org.json.jar,用來解析json
如果你是用的Maven方式,你可以直接添加依賴
<!--JSON-->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160810</version>
</dependency>
6
1
<!--JSON-->
2
<dependency>
3
<groupId>org.json</groupId>
4
<artifactId>json</artifactId>
5
<version>20160810</version>
6
</dependency>
3.1.2 配置struts.xml
<package name="ajax" namespace="/ajax" extends="json-default" >
<action name="ajaxAction" class="ajaxAction">
<!-- 返回類型為json-->
<result name="register" type="json">
<!--tips 參數root的含義-->
<param name="root">message</param>
</result>
</action>
</package>
9
1
<package name="ajax" namespace="/ajax" extends="json-default" >
2
<action name="ajaxAction" class="ajaxAction">
3
<!-- 返回類型為json-->
4
<result name="register" type="json">
5
<!--tips 參數root的含義-->
6
<param name="root">message</param>
7
</result>
8
</action>
9
</package>
重點注意的是:
- 這里不再繼承struts-default,而是json-default(這個文件在我們引入的struts-json插件包中就有配置)
- type需要修改為json
- <param name="root">message</param> 這里我們單獨來敘述
這里最難理解的大概就是這個<param name="root">message</param>了,下面來簡單說說到底是什么意思(參考鏈接:
JSON中result的root屬性):
所謂root的含義,是指返回的json數據為指定的對象(Action中作為屬性的那個類),例如我的源碼中AjaxAction中為Message message,將返回和Message對等的json對象。
如果沒有指定root屬性,則默認使用Action作為返回的json對象。
是否使用Action作為返回的json數據的根,區別如下:
例如有Action如下,含兩個屬性
String message、
UserInfo userInfo
:
public class JsonJqueryStruts2Action extends ActionSupport {
private String message; //使用json返回單個值
private UserInfo userInfo; //使用json返回對象
... ...
}
5
1
public class JsonJqueryStruts2Action extends ActionSupport {
2
private String message; //使用json返回單個值
3
private UserInfo userInfo; //使用json返回對象
4
... ...
5
}
result中使用了root參數(<param name="root">userInfo</param>)后返回的json數據:
{"userInfo":[
{"userId":"Patrick", "userName":"123456"}
]}
3
1
{"userInfo":[
2
{"userId":"Patrick", "userName":"123456"}
3
]}
result中沒有設置root參數返回Action中的json數據:
{"data":[
{"userInfo":[ {"userId":"Patrick", "userName":"123456"} ] },
{"message":"testMesssageData"}
]}
4
1
{"data":[
2
{"userInfo":[ {"userId":"Patrick", "userName":"123456"} ] },
3
{"message":"testMesssageData"}
4
]}
3.2 編寫Action
package com.zker.action;
import com.opensymphony.xwork2.ActionSupport;
import com.zker.common.util.Message;
import com.zker.common.util.SpringContextUtils;
import com.zker.dao.user.UserDao;
import org.json.JSONObject;
import java.io.IOException;
public class AjaxAction extends ActionSupport {
/**用來接受封裝的參數 LoginName 用戶名*/
String loginName;
/**封裝信息,為了測試JSON刻意做成簡單的類*/
Message message = new Message();
/**用來返回用於js接收*/
String result;
//tips 要有getter&setter,否則$post的param參數傳遞不過來
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public Message getMessage() {
return message;
}
public void setMessage(Message message) {
this.message = message;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
/**
* 利用Ajax實現注冊的用戶名重復性校驗
* @return
*/
public String ajaxRegister() throws IOException {
//tips 如何手動取出容器中的bean?答案如下
UserDao userDao = (UserDao)SpringContextUtils.context.getBean("userDao");
if (userDao.findAdminByLoginName(loginName) != null
|| userDao.findUserByLoginName(loginName) != null) {
message.setMsg("用戶名已存在");
message.setStatus(false);
} else {
message.setMsg("用戶名可以注冊");
message.setStatus(true);
}
/*
//JSON-String轉換 obj -> jsonStr
//當struts-login.xml中root為result時,此處才需要解開
this.result = JSONObject.wrap(message).toString();
*/
return "register";
}
}
71
1
package com.zker.action;
2
3
import com.opensymphony.xwork2.ActionSupport;
4
import com.zker.common.util.Message;
5
import com.zker.common.util.SpringContextUtils;
6
import com.zker.dao.user.UserDao;
7
import org.json.JSONObject;
8
9
import java.io.IOException;
10
11
12
public class AjaxAction extends ActionSupport {
13
/**用來接受封裝的參數 LoginName 用戶名*/
14
String loginName;
15
16
/**封裝信息,為了測試JSON刻意做成簡單的類*/
17
Message message = new Message();
18
19
/**用來返回用於js接收*/
20
String result;
21
22
//tips 要有getter&setter,否則$post的param參數傳遞不過來
23
public String getLoginName() {
24
return loginName;
25
}
26
27
public void setLoginName(String loginName) {
28
this.loginName = loginName;
29
}
30
31
public Message getMessage() {
32
return message;
33
}
34
35
public void setMessage(Message message) {
36
this.message = message;
37
}
38
39
public String getResult() {
40
return result;
41
}
42
43
public void setResult(String result) {
44
this.result = result;
45
}
46
47
/**
48
* 利用Ajax實現注冊的用戶名重復性校驗
49
* @return
50
*/
51
public String ajaxRegister() throws IOException {
52
//tips 如何手動取出容器中的bean?答案如下
53
UserDao userDao = (UserDao)SpringContextUtils.context.getBean("userDao");
54
if (userDao.findAdminByLoginName(loginName) != null
55
|| userDao.findUserByLoginName(loginName) != null) {
56
message.setMsg("用戶名已存在");
57
message.setStatus(false);
58
} else {
59
message.setMsg("用戶名可以注冊");
60
message.setStatus(true);
61
}
62
63
/*
64
//JSON-String轉換 obj -> jsonStr
65
//當struts-login.xml中root為result時,此處才需要解開
66
this.result = JSONObject.wrap(message).toString();
67
*/
68
69
return "register";
70
}
71
}
這里為了驗證AJAX+JSON,故意采取的建立一個Message類來傳遞信息,多此一舉只為學習,實際操作請注意。其他信息詳見代碼,這里不做具體展開。
3.3 編寫JS
<!--Ajax + JSON-->
$(document).ready( function() {
//使用 Ajax 的方式 判斷登錄
$("#loginName").blur( function() {
var url = "/ajax/ajaxAction!ajaxRegister";
var params = {loginName : $("#loginName").val()};
/*method1 <param name="root">result</param>
$.post(
url, //服務器要接受的url
params, //傳遞的參數
function validateLoginName(result){ //服務器返回后執行的函數 參數msg保存的是服務器發送到客戶端的數據
//alert("服務器端返回的data --> " + result);
var msgObj = eval("(" + result + ")"); //jsonStr -> jsObj(jsonObj)
var passed = msgObj.status;
setMessage(msgObj.msg, passed);
},
'json' //數據傳遞的類型 json
);
*/
/*method2 <param name="root">message</param> */
$.post(
url, //服務器要接受的url
params, //傳遞的參數
function validateLoginName(message){ //服務器返回后執行的函數 參數是服務器發送到客戶端的數據
var msg = message.msg;
var passed = message.status;
setMessage(msg, passed);
},
'json' //數據傳遞的類型 json
);
function setMessage(message, passed) {
var validateMessage = document.getElementById("loginNameMsg");
var fontColor = "red";
if(passed) {
fontColor = "green";
}
//對<div name="loginNameMsg">的地方設置其間的代碼innerHTML為指定代碼
validateMessage.innerHTML = "<font color=" + fontColor + ">"
+ " "
+ message + "</font>";
}
});
});
46
1
<!--Ajax + JSON-->
2
$(document).ready( function() {
3
//使用 Ajax 的方式 判斷登錄
4
$("#loginName").blur( function() {
5
var url = "/ajax/ajaxAction!ajaxRegister";
6
var params = {loginName : $("#loginName").val()};
7
8
/*method1 <param name="root">result</param>
9
$.post(
10
url, //服務器要接受的url
11
params, //傳遞的參數
12
function validateLoginName(result){ //服務器返回后執行的函數 參數msg保存的是服務器發送到客戶端的數據
13
//alert("服務器端返回的data --> " + result);
14
var msgObj = eval("(" + result + ")"); //jsonStr -> jsObj(jsonObj)
15
var passed = msgObj.status;
16
setMessage(msgObj.msg, passed);
17
},
18
'json' //數據傳遞的類型 json
19
);
20
*/
21
22
/*method2 <param name="root">message</param> */
23
$.post(
24
url, //服務器要接受的url
25
params, //傳遞的參數
26
function validateLoginName(message){ //服務器返回后執行的函數 參數是服務器發送到客戶端的數據
27
var msg = message.msg;
28
var passed = message.status;
29
setMessage(msg, passed);
30
},
31
'json' //數據傳遞的類型 json
32
);
33
34
function setMessage(message, passed) {
35
var validateMessage = document.getElementById("loginNameMsg");
36
var fontColor = "red";
37
if(passed) {
38
fontColor = "green";
39
}
40
//對<div name="loginNameMsg">的地方設置其間的代碼innerHTML為指定代碼
41
validateMessage.innerHTML = "<font color=" + fontColor + ">"
42
+ " "
43
+ message + "</font>";
44
}
45
});
46
});
<div id="loginNameMsg"></div>
<div class="login_sr">賬號:<s:textfield cssClass="login_inputYhm" name="sysUser.loginName" id="loginName" />
2
1
<div id="loginNameMsg"></div>
2
<div class="login_sr">賬號:<s:textfield cssClass="login_inputYhm" name="sysUser.loginName" id="loginName" />
這里值得一提的就是JQuery的$.post()方法,原型是ajax(),通過 HTTP 請求加載遠程數據,返回其創建的 XMLHttpRequest 對象。
至此,已經OK。