Ajax(Asynchronous JavaScript and XML)
通过XMLHttp对象,开发人员可以在应用程序的任何地方初始化HTTP请求。这些请求以XML的格式返回(或者是其他的格式,如:json)。
微软的IE5.0引入了一个名为MSXML的ActiveX程序库,Firefox中也实现了XMLHttp功能。其创建了一个原生的JavaScript对象XMLHttpRequest,它模仿了微软的XMLHttp对象的行为。微软在IE7中也创建了自己的原生XMLHttpRequest对象。现在主流的浏览器都提供了对原生对象的支持,均称之为XHR(xmlHttpRequest)。
跨浏览器的创建XMLHttpRequest
//用于创建XMLHttpRequest对象
this.createXmlHttp = function() {
var xmlHttp = null;
//根据window.XMLHttpRequest对象是否存在使用不同的创建方式
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest(); //支持新版本的IE及其他大部分浏览器
} else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");//支持IE5、IE6浏览器
}
return xmlHttp;
}
使用XmlHttpRequest对象
创建完XHR对象后,就可以从JavaScript开始发出HTTP请求了。第一步是调用open()方法来初始化该对象。如下:
xmlHttp.open("POST", this._url, true);
*该方法的三个参数分别是:请求类型,即是get还是post,是字符串形式;URL,说明发关请求的目标;async,布尔值,用来说明请求是否是异步模式。为真是说明以异步模式发送该请求,JavaScript代码将继续执行而不再等响应了;这时就必须使用一个事件处理函数来监控请求的响应。
接着,需要定义一个onreadystatechange事件处理函数,XHR对象有一个名为readyState的属性,该属性在发送请求到接收到响应的期间会发生变化。readyState有五种可能的取值:
0,未初始化,对象已经创建,但还没有调用open()方法
1,载入中,open()方法已经调用,但请求还没有发送
2,已载入,请求已经发送
3,交互中,已经接收到部分响应
4,完成,所有数据都已经收到,连接已经关闭
每当readyState属性的值发生变化时,就将触发readystatechange事件,并调用onreadystatechange事件处理函数。
*注意:唯一可靠的readyState的值是4。有些浏览器忽略了1和2所表示的状态等,所以最好仅依赖于检查readState是否为4。
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
alert("Get response");
}
}
最后一步是调用send()方法,这将最终完成请求的的发送。该方法只接受一个参数,即表示请求主体的字符串(就是参数)。如果不包含主体(get请求就不包含),则必须传入null。
xmlHttp.send("name=" + encodeURIComponent(_node.id) + "&value=" + encodeURIComponent(_node.value));//发送包含用户输入信息的请求体
这样一个请求就发送完了,当然我可以去访问请求的响应信息,可以使用responseText或responseXML属性。
一个完整的例子:
//创建XmlHttpRequest对象
var xmlHttp=this.createXmlHttp();
//初始化
xmlHttp.open("POST", "jsp/servlet/action", true);
//设置响应监控函数
xmlHttp.onreadystatechange = showInfo;
//发送请求
xmlHttp.send(null);
showInfo = function() {
if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
alert(xmlHttp.responseText);
}
}
*注意:仅当找到文件并且没有错误发生时,才能够正常返回信息。如果文件没找到或是服务器端代码本身运行出错,则需要使用xmlHttp.status属性中包含的HTTP状态码来判断。
通常,应当总是确保响应的状态是200,这说明请求已经成功地完成了。即使服务器端错误,readyState属性的值仍然会设置为4,因此只检查它是不够的。
永远不要只依赖于statusText来判断是否出现错误。
访问响应的首部,使用getResponseHeader()方法,并传入需要获得的首部名称。就可以获得一个特定的首部。
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
通常只能从服务器接收XML数据(text/xml)或纯文本(text/plain),因为只有这两种内容类型使用javaScript处理最容易。
设置为同步时,不需要指定事件处理函数。对于想让用户交互等待的响应,或希望只接收很少的数据(如,小于1k)的应用场景是很有用的。对于通常的数据量或较大的数据量而言,最好还是使用异步调用。
服务器常用的状态码及其对应的含义如下:
200 服务器响应正常。
304 该资源在上次请求之后没有任何修改,这通常用于浏览器的缓存机制,使用GET请求时尤其需要注意。
400 无法找到请求的资源。
401 访问资源的权限不够。
403 没有权限访问资源。
404 需要访问的资源不存在。
405 需要访问的资源被禁止
407 访问的资源需要代理身份验证。
414 请求的URL太长。
500 服务器内部错误。
example:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script>
client:
var validateUserName=function(){
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("get","login.servlet?param=validateUserName&userName="+document.getElementById("userName").value,true); //准备提交
//服务器响应后用于接收响应的回调函数
xmlHttp.onreadystatechange=function(){
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
//alert(xmlHttp.responseText);
if(xmlHttp.responseText=="error"){
document.getElementById("userNameTip").innerHTML="用户名重名";
}else if(xmlHttp.responseText=="ok"){
document.getElementById("userNameTip").innerHTML="通过";
}
}
}
xmlHttp.send(null); //真正的发送
}
</script>
</head>
<body>
用户名:<input id="userName" type="text" name="userName" onblur="validateUserName()" /><span id="userNameTip"></span><br/>
密码:<input type="text" name="password" /><span id="passwordTip"></span><br/>
<input type="submit" value="登录" />
</body>
</html>
server:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String param=request.getParameter("param");
String userName=request.getParameter("userName");
response.setContentType("text/plain; charset=utf-8");
PrintWriter out=response.getWriter();
if("validateUserName".equals(param)){
System.out.println("userName:"+userName);
if("admin".equals(userName)){
out.print("error");
}else{
out.print("ok");
}
}
}
使用post方式传送数据,需要进行某些修改,其流程如下:
var xmlHttpRequest=new XMLHttpRequest();
xmlHttpRequest.onreadystatechange=callBack;
var url="server.jsp";
xmlHttpRequest.open("post",url,true);
xmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); //使用send(data)时,此处必写
var data="userName="+document.getElementById("add_userName").value+"&";
data+="password="+document.getElementById("add_password").value+"&";
data+="address="+document.getElementById("add_address").value;
console.log(data);
xmlHttpRequest.send(data);
由于get方式传送数据更快且更加方便,所以争议使用get方式进行异步数据传输。
XMLHttpRequest 对象方法
方法 描述
abort() 停止当前请求
getAllResponseHeaders() 作为字符串返问完整的headers
getResponseHeader(string header) 作为字符串返问单个的header标签
open(string method,string url,boolean async,string user,string password) 设置未决的请求的目标 URL, 方法, 和其他参数
method,设置http请求方法,如post、get等
url,请求的url地址
async,可选,指定此请求是否为异步方法,默认为true
user、password,可选,用户名密码
send(string data) 发送请求
method为post,需要指定此参数;method为get时,该参数为null
setRequestHeader(string header,string value) 设置header并和请求一起发送
header,要指定的http头名称
value,要指定的httpu头名称所对应的值
XMLHttpRequest 对象属性
属性 描述
onreadystatechange 状态改变的事件触发器
readyState 对象状态(integer):
0 = 未初始化
1 = 读取中
2 = 已读取
3 = 交互中
4 = 完成
responseText 服务器进程返回数据的文本版本
responseXML 服务器进程返回数据的兼容DOM的XML文档对象
status 服务器返回的状态码, 如:404 = "文件末找到" 、200 ="成功"
statusText 服务器返回的状态文本信息