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。