Ajax技术概述:
它是一种允许浏览器与服务器之间通信而无须刷新整个页面的局部交互技术。在Ajax中,数据在客户端与服务器之间独立传输,服务器不在返回整个页面。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息。
同步和异步:
同步请求:当浏览器发出去请求之后,只有当服务器端完成响应后回来,才能做其他事情。这个过程中,浏览器处于等待状态。什么都不能干只能一直等着,在那卡着)
异步请求:当浏览器发出去请求之后,等待服务器响应。在此期间,浏览器不阻塞。(客户端可以去做其他事情)
可以这样理解:异步请求就是浏览器开启一个新线程去发送请求到服务器端,而主线程不受影响,直到这个异步线程从服务器端响应回来,然后主线程就要对这个回来的响应进行处理。
我们看到的同步请求就是整个页面都会刷新一次。而异步请求是局部刷新。
原生Ajax代码编写步骤:
强烈建议按下面顺序来走:
- 创建XMLHttpRequest对象
- .注册回调函数(重要,不注册你是回不来的,接收不到响应)
- 连接请求提交地址
- 发送请求。
XMLHttpRequest对象:
专门用来发送异步请求的对象,当然,也可以发送同步请求。使网页与服务器进行通信用的就是它。
readyState属性:
在ajax执行过程中,服务器会通知客户端当前的通信状态。这依靠XMLHttpRequest对象的readState来实现
改变readystate属性是服务器对客户端连接操作的一种方式。每次该属性的改变都会触发onreadystatechange事件。
readyState其实就是告诉浏览器,你的ajax请求进行到哪一步了(请求的状态):
0:表示请求未初始化,即还未调用open方法
1:代表正在加载,open方法已被调用,但send方法还没调用。
2:表示加载完毕,send已被加载,请求已经开始。
3:代表已经在交互中,服务器端正在发送响应。
4:响应发送完毕。(重点关心的是这个)
readyState的值会因为浏览器不同而有所差异,但当请求结束时,每个浏览器都会把该属性的值同一设为4.
status属性(状态码):
1xx:代表临时的响应
2xx:代表服务端正常响应客户端(200一切正常,重点关心的是这个!)
3xx:代表服务器端资源没有发生改变
4xx:代表资源错误。(404没找到页面)(403禁止访问)
5xx:代表内部服务器端出错。
responseText和responseXML:
responseText:表示以文本的信息获取服务端响应。获取的就是字符串。(如果传递过来的是json字符串,当然就可以将其转换为JSON对象)重点知道这个
responseXML:当服务端以xml格式返回给客户端时,则使用此属性去接收。(获取的就是DOM对象)
一个实例:
前端JS代码如下:主要是实现用户注册时将用户名输入完毕利用ajax发请求(异步模式下,下述代码中同步模式可将open()方法的synch参数指定为false),查看是否用户名已被使用过。
window.onload = function(){
var ajaxFun = function(obj){
var synch = Boolean(obj.synch) && true;
var method = obj.method || "GET";
var data = obj.data || "";
var success = obj.success || function(data){};
//以下是ajax请求步骤
/*1 创建XMLHttpRequest对象 */
var xmlHttp = new XMLHttpRequest();
var url = obj.url;
if(method === "GET"){
//拼接参数键值对到url后
url += '?' + data;
}
/*2 注册回调函数 */ //这个函数将会被调用4次
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
success(xmlHttp.responseText)
}
}
/*3 建立请求提交地址(synch值若true则表示异步,false表示同步)*/
xmlHttp.open(method,url,synch);
/*4 发送请求 */
if(method == "GET"){
xmlHttp.send();
}
if(method == "POST"){
//POST请求方式需要加上这句话 设置请求头编码方式(而且这个设置必须在open方法之后 因为没有打开链接的话就不能设置请求头)
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlHttp.send(data);
}
}
var idInput = document.getElementById("id");
idInput.onblur = function(){
var value = idInput.value;
var obj = {
url: "registerAction",
synch: true, //异步请求
method: "POST",
data: this.method == "GET" ? value : "id=" + value,
success:function(data){
/*响应成功之后*/
var user = JSON.parse(data);
if(user.id == "ERROR"){
alert("用户名不可用");
}else{
alert("用户名可用");
}
}
}
ajaxFun(obj);
}
}
注意上述代码中:onreadystatechange事件是由服务器来触发的,而且每一次readyState值的改变都会触发该事件的回调函数。
后端Servlet代码:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// try {
/*
* 同步模式下浏览器就在这要等至少5秒了 只要同步模式下提交了,在整个页面上他除了等还是等什么都动不了。
* 如果它非要觉得卡 再点一次提交,这里执行两次,它还要等更久。。。。 卡死了!
* 所以异步请求局部刷新 用户体验感要比同步请求提升一个层级。
*/
// Thread.sleep(5000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
String id = req.getParameter("id");
String password = req.getParameter("password");
User user = new User(id, password);
user = this.userService.registry(user);
//制造json字符串
String userJson = gson.toJson(user);
//回传响应
resp.setContentType("application/json;charset=UTF-8");
resp.getWriter().write(userJson);
}
上述代码中gson是Gson的一个对象。Gson是由google公司提供的json转换工具。
结果测试:
可以看到用户还未输入密码是就已经交互过了。异步模式优点就是可以在未接收到响应前可以进行其他操作比如输入密码。如果是同步模式给你来个Thread.sleep(5000)那你这5秒内必须卡在那等着,鼠标都点不动。
还需注意的是POST请求时候必须指定请求的编码方式:
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
JSON格式:
1)对象格式:{"key1":“value1”,"key2":“value2”,"key3":“value3”...}
比如上述例子中的不使用Gson工具的话,造json字符串如下:
String jsonStr = "{\"" + user.getId()+ "\":\"" + user.getPassword() + "\"}";
2)数组/集合格式:[数据1,数据2,数据3...](对象格式与数组格式可以相互嵌套)
还是来测试一下眼见为实:
public class Test {
public static void main(String[] args) {
int[] array = {1,2,3,4};
System.out.println(RegisterServlet.gson.toJson(array));
List<User> userList = new ArrayList<User>();
userList.add(new User("1234567", "99999"));
userList.add(new User("3333", "0000"));
System.out.println(RegisterServlet.gson.toJson(userList));
}
}
结果如下:
在JS中为我们提供了一个对象就叫JSON,他可以实现json对象与json字符串之间的互转。
json字符串-------->json对象: JSON.parse(json字符串)
json对象-------->json字符串:JSON.stringify(json对象)