Ajax介绍

Ajax主要作用:在不刷新网页的情况下,与后台数据进行交互,从而实现页面局部刷新的功能

  • Asynchronous JavaScript And Xml(异步的JavaScript和XML)
  • Ajax可以在不刷新页面的前提下,进行页面局部更新
  • Ajax不是新的技术,Ajax并不是W3C的标准
  • Ajax并不是一种标准,而是服务商提供的一种技术;大部分浏览器在浏览器内核中都提供了Ajax的核心实现;后来某位大牛对这些技术进行整合和命名,才有今天的Ajax

学习Ajax时,需要理解几点:

(1)以前遇到的请求都是和一个网页面联系在一起的,即前端发起一个请求就是和一个网页联系在一起,也可以理解为以前接触到的都是为了展示一个全新的页面而发起的一个请求,也可以理解为每发起一个新的请求,都会创建一个新的界面来展示一个新的界面来展示本次响应的内容;但Ajax不是这样的,Ajax的请求内容并不是为了展示一个新的界面,而是将本次请求的响应内容,局部刷新展示在已有界面上,本质是,已有页面发起一个没有和新的页面绑定的请求(这个请求和已有界面的局部刷新有关)

而这个功能的实现,浏览器中内嵌的ajax起到了重要作用

(2)一个可以接受请求,发出响应的servlet的任务仅仅是接受前台请求数据,处理后再返回给前台,具体响应后,前台怎么展示这些数据就和后台Servlet无关了

(3)目前可以这样理解:ajax是内嵌到浏览器中的一种技术,归浏览器解释;当浏览器解析到前端文件中的ajax部分的时候,浏览器会自动采用内置的ajax去解释

Ajax使用流程简介和准备工作

一.Ajax使用流程简介

  • 创建XmlHttpRequest对象
  • 发送Ajax请求(通过XmlHttpRequest对象发送请求)
  • 处理服务器响应(在web页面中,通过JavaScript对响应进行后续的处理,将其显示在页面中)

二.准备工作

创建Web工程ajax,并创建ContentServlet和index.html:

jqfunction6

index.html:

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>text ajax</title>
</head>
<body>
<!--当点击“加载”按钮,向服务器发送请求,将服务器返回的信息动态地写入到divContent这个div块中,即点加载后局部刷新和加载-->
<input id="btnLoad" type="button" value="加载">
<div id="divContent"></div>
</body>
</html>

ContentServlet.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebServlet(name = "ContentServlet", value = "/ContentServlet")
public class ContentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("<br>I'm server Content</br>");
//(1)用于应对Ajax请求的Servlet,该Servlet不进行任何页面的跳转,而是直接返回要响应给Ajax请求的信息(或者说是提供用户所需要的数据回显就可以了)
//(2)通常数据的格式会采用JSON,很少这样直接回显一个html(字符串)
}
}

目前的需求是:当点击”加载”按钮的时候,向服务器发送请求,将回显动态写入到divContent中;即局部刷新和加载

三.利用Ajax实现Ajax请求

1.创建XmlHttpRequest对象

  • XML HttpRequest用于在后台与服务器交换数据,是AJAX核心

  • XMLHttpRequest并不是W3C的标准,不同浏览器的创建方式不同

  • 创建XMLHttpRequest对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <script>
    document.getElementById("btnLoad").onclick = function(){
    //1.创建XMLHttpRequest对象
    var xmlhttp;
    if(window.XMLHttpRequest){ // 新版本浏览器支持这句话
    xmlhttp = new XMLHttpRequest(); // 创建一个新的XmlHttpRequest对象
    }else{ // 老版本浏览器
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    console.log(xmlhttp);
    }

    </script>

效果:

ajax1

2.发送Ajax请求

  • xmlhttp.open()用于创建请求

  • xmlhttp.send()用于发送请求

    1
    2
    3
    4
    5
    6
    <script>
    //创建请求
    xmlhttp.open("GET","http://localhost:8080/ajax/content","true");//包括请求的类型,请求的地址,ture为异步,false为同步
    //发送到服务器
    xmlhttp.send();
    </script>

    效果:

ajax2

查看content:

ajax3

查看response:

ajax4

当多次点击”加载”按钮时:

ajax5

3.处理服务器的响应

  • xmlhttp.onreadystatechange()事件用于监听AJAX的执行过程:这个方法用于捕捉Ajax的执行过程

  • xmlhttp.readyState属性说明XMLHttpRequest当前的状态:XmlhttpRequest对象中的一个重要属性,readState用于指示说明当前Ajax执行到哪一步了

  • readState值 说明
    readState=0 请求未初始化
    readState=1 服务器连接已建立
    readState=2 请求已被接受
    readState=3 请求正在处理
    readState=4 响应文本已被接受
  • xmlhttp.status属性服务器响应状态码,200:成功,404:未找到……

(1)核心事件是onreadystatechange,当ajax在发送过程中,各个状态发生变化的时候,就会触发这个事件;(注:onreadystatechange是XmlHttpRequest对象的事件)

(2)readState用以判断Ajax执行到哪一步,最重要的是为4的时候;(注意:status是XmlHttpRequest对象的属性)

(3)status:服务器处理的状态,200代表处理成功(注意:status是XmlHttpRequest对象的属性)

readState=4和status=200,就代表响应已经被接受,而且服务是处理成功了。(服务器处理不成功时,其也还是会有响应的,只是这个响应是一个出错的响应,比如当status=404的时候,对于响应出错的时候,后续应该采取其他策略

(4)使用了XmlHttpRequest对象的responseText属性,获取服务器响应的文本;(注意:responseText是XmlHttpRequest对象的属性)获取服务器响应的文本后,对这个文本进行后续处理就可以了;(这个文本一般是JSON形式的,JSON作为一种功能强大,前后端都能解释得表示方法很给力)

Ajax处理响应得标准范例:

1
2
3
4
5
6
7
8
9
10
<script>
xmlhttp.onreadstatechange=function(){//给onreqdestatechange绑定一个匿名函数
//响应被接受且服务器处理成功时才执行
if(xmlhttp.readyState=4&&xmlhttp.status=200)
//获取响应体得文本
var responseText = xmlhttp.responseText;//通过这个responseText获取响应文本
//对服务器结果进行处理
……
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>text ajax</title>
</head>
<body>
<!--当点击“加载”按钮,向服务器发送请求,将服务器返回的信息动态地写入到divContent这个div块中,即点加载后局部刷新和加载-->
<input id="btnLoad" type="button" value="加载">
<div id="divContent"></div>
<script>
document.getElementById("btnLoad").onclick = function() {
//1.创建XMLHttpRequest对象
var xmlhttp;
if (window.XMLHttpRequest) { // 新版本浏览器支持这句话
xmlhttp = new XMLHttpRequest(); // 创建一个新的XmlHttpRequest对象
} else { // 老版本浏览器
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
console.log(xmlhttp);//在控制台中输入xmlhttprequest对象

//2.发送Ajax请求
//xmlhttp.open("GET","http://localhost:8080/ajax/content","true");
//请求地址可以写成上面完整的http的形式,也可以采用下面的简写形式
xmlhttp.open("GET","/ajax/content",true);//通过XMLHttpRequest对象创建Ajax请求
xmlhttp.send();
//3.处理服务器响应
xmlhttp.onreadystatechange=function (){
if (xmlhttp.readyState == 4&&xmlhttp.status==200){//代表响应已经被接受,而且服务是处理成功
var t =xmlhttp.responseText;
alert(t);
//这个对响应文本的后续处理肯定会比较复杂,不会像下面这样简单赋值就OK了的
document.getElementById("divContent").innerHTML =t;
}
}
}
</script>
</body>
</html>

效果:

ajax6

ajax7

利用Ajax实现新闻列表

这个例子主要是展示在实际中,前后端交互的时候,传输的文本常常是JSON形式

News.java:定义构成函数等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class News {
private String title;
private String date;
private String source;
private String content;
public News(){

}

public News(String title, String date, String source, String content) {
this.title = title;
this.date = date;
this.source = source;
this.content = content;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getDate() {
return date;
}

public void setDate(String date) {
this.date = date;
}

public String getSource() {
return source;
}

public void setSource(String source) {
this.source = source;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}
}

NewListServlet类:

(1)后台处理后的数据向前台传的时候,需要转成JSON字符串;这需要引入fastjson的jar包

(2)这个Servlet并没有主动重定向或者转发至news.html中;而是在这里默默的等待,等待news,html的Ajax的XmlHttpServlet对象创建的Ajax请求,然后请求到这个Servlet中

(3)这个Servlet通过,response.getWriter().println(newsJsonStr);将JSON字符串回显到news.html中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import com.alibaba.fastjson.JSON;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@WebServlet(name = "NewsListServlet", value = "/news_list")
public class NewsListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<News> list = new ArrayList<News>();//创建集合对象list
list.add(new News("标题1","2022-1-1","TIOBE","内容1"));//在集合中增加内容
list.add(new News("标题2","2022-1-2","TIOBE","内容2"));
list.add(new News("标题3","2022-1-3","TIOBE","内容3"));
//在Servlet处理后,对外进行字符串序列化的时候,一律将其转化为JSON:通过JSON,可以对数据进行有效的描述
//然后在前端的html中,再通过javaScript自带的JSON处理方式,将从这儿发送过去的数据进行解析
//将集合对象list转成JSON需要,引入fastjson包,可以这样想回显是需要字符串的
String newsjsonstr = JSON.toJSONString(list);
System.out.println(newsjsonstr);
response.setContentType("text/html;charset=UTF-8");//json字符串中包含中文需要设置编码
response.getWriter().println(newsjsonstr);//回显从list集合对象序列化成json字符串


}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}
}

news.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div id="container"></div>
<script>
//创建XmlHttpRequest对象
var xmlhttp;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}else {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
//发送Ajax请求
xmlhttp.open("GET","/ajax/news_list",true);//创建Ajax请求
xmlhttp.send();//发送Ajax请求
//处理服务器响应(处理回显中的JSON字符串)
xmlhttp.onreadystatechange=function (){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
var json = xmlhttp.responseText;//从后台拿过来的数据,这个json是JSON字符串
var jsont = JSON.parse(json);//需要将JSON字符串转成JSON对象;JavaScript可以认为内置了JSON对象
console.log(json);
console.log(jsont);
var html = "";
for (var i =0;i<jsont.length;i++){
var news = jsont[i];
html = html + "<h1>"+news.title+"</h1>";//输出JSON对象调用其中的属性
html = html + "<h2>"+news.date+" "+news.source+" "+news.content + "</h2>";
html = html + "<hr/>";

}
document.getElementById("container").innerHTML=html;
}
}
</script>
</body>
</html>

效果:html中的ajax部分,会去请求访问Servlet,获取响应中的JSON字符串,在html中转变为JSON对象,按照需求来调用JSON对象中的属性

ajax8

Ajax同步和异步的简述

在ajax的第二步,发送ajax请求的时候,第三个参数,true:异步;false同步

1
2
3
4
5
<script>
//2.创建并发送Ajax请求
xmlhttp.open("GET","/ajax/news_list",true);//创建异步Ajax请求
xmlhttp.send();//发送请求
</script>

那么什么是异步,什么是同步呢?

分析:xmlhttp.send();在发送请求的过程中是需要时间的,网络传输将请求发送到服务器,服务器处理后再返回响应的过程肯定是需要一些时间的

true异步:在上面发送请求的过程中,程序的其他部分继续向下执行;

false同步:在上面发送请求的过程中,程序的其他部分不继续向下执行,而是等到响应成功后再继续执行;

注意:

(1)ajax绝大部分情况下使用异步处理,但说不定某些场景适合使用同步的方式

(2)同步是发送一个请求,需要等待返回,然后才能够发送下一个请求;异步是发送一个请求,不需要等待返回,随时可以再发送下一个请求;同步有等待响应的过程

(3)同步和异步的深入理解必须通过实际应用中逐深渐化理解

同步与异步的区别

同步:同步可以看作是一个单线程操作,只要客户端请求了,在服务器没有回显之前都是线程阻塞的状态,不会向下执行任何操作,同步传输是面向比特的传输,他的单位是帧

异步:异步肯定是多线程,在客户端请求时,可以执行其他线程,并且把这个线程存放在他的队列里面,有序的执行,异步传输是面向字符的传输,他的单位是字符

示例一:设置为false同步

1
2
3
4
5
<script>
xmlhttp.open("GET","/ajax/news_list",false);
xmlhttp.send();
console.log("请求发送完成");//为了方便观察效果,当响应返回时,在控制台输出一段话"请求发送完成"
</script>

在实际开发中,后台服务器响应需要一定的时间,为了使效果明显,方便肉眼观察,模拟后台实际消耗的时间,这里在servlet中写入休眠5秒

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import com.alibaba.fastjson.JSON;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@WebServlet(name = "NewsListServlet", value = "/news_list")
public class NewsListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Thread.sleep(5000);
}catch (InterruptedException e){
e.printStackTrace();
}
List<News> list = new ArrayList<News>();//创建集合对象list
list.add(new News("标题1","2022-1-1","TIOBE","内容1"));//在集合中增加内容
list.add(new News("标题2","2022-1-2","TIOBE","内容2"));
list.add(new News("标题3","2022-1-3","TIOBE","内容3"));
//在Servlet处理后,对外进行字符串序列化的时候,一律将其转化为JSON:通过JSON,可以对数据进行有效的描述
//然后在前端的html中,再通过javaScript自带的JSON处理方式,将从这儿发送过去的数据进行解析
//将集合对象list转成JSON需要,引入fastjson包,可以这样想回显是需要字符串的
String newsjsonstr = JSON.toJSONString(list);
System.out.println(newsjsonstr);
response.setContentType("text/html;charset=UTF-8");//json字符串中包含中文需要设置编码
response.getWriter().println(newsjsonstr);//回显从list集合对象序列化成json字符串


}

效果:发现,等后台响应后,html中的控制台才会输出预设的内容;但是,在浏览器界面没有显示出响应的结果,而是显示一个白板

ajax9

ajax10

一.为什么程序处于一直等待的状态;等待了差不多5秒后,才执行console.log(“请求发送完成”)

分析:在发送Ajax请求设置为false同步后,程序的其他部分不继续向下执行,而是等到服务器响应成功后再继续执行;send()方法会处于阻塞的状态,直到后台响应返回之后,才会向下执行,执行console.log()

ajax11

二.为什么浏览器界面没有回显出相应的内容?

分析:这里是由Ajax的机制决定的,一旦这儿设置成false同步;在xmlhttp.onreadystatechanse = function(){}这个事件会失效

ajax12

如果想在同步的情况下,继续在浏览器界面显示出响应内容:将xmlhttp.onreadystatechange = function(){}里面的内容复制到send()后面:也就是说xmlhttp.onreadystatechange = function(){}这个会不起作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
=<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div id="container"></div>
<script>
// 1.创建XmlHttpRequest对象
var xmlhttp;
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
}else{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// 2.发送Ajax请求
xmlhttp.open("GET","/ajax/news_list",false);
xmlhttp.send();
console.log("请求发送完成");
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
var t = xmlhttp.responseText; // 从后台拿过来的数据:这个JSON是个JSON字符串
var jsont = JSON.parse(t); // 需要将JSON字符串转成JSON对象;JavaScript可以认为内置了JSON对象
console.log(t);
console.log(jsont);
var html = "";
for(var i = 0;i< jsont.length;i++){
var news = jsont[i];
html = html+"<h1>"+news.title+"</h1>";
html = html + "<h2>"+news.date+" "+news.source+" "+news.content + "</h2>";
html = html + "<hr/>";
}
document.getElementById("container").innerHTML = html;
}

效果:将失效的代码删除吗,直接复制到send()方法后面,等待5秒后回显到浏览器上

ajax13

示例二:设置成true异步时:(核心内容)

异步:在网络发送请求的过程中不进行代码阻塞,继续向下执行,异步采用onreadstatechange进行对响应状态的监控,程序的其他部分同时进行

设置为异步案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div id="container"></div>
<script>
//创建XmlHttpRequest对象
var xmlhttp;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}else {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
//发送Ajax请求
xmlhttp.open("GET","/ajax/news_list",true);
xmlhttp.send();
console.log("请求发送完成");
//处理服务器响应
xmlhttp.onreadystatechange=function (){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
var json = xmlhttp.responseText;//从后台拿过来的数据,这个json是JSON字符串
var jsont = JSON.parse(json);//需要将JSON字符串转成JSON对象;JavaScript可以认为内置了JSON对象
console.log(json);
console.log(jsont);
var html = "";
for (var i =0;i<jsont.length;i++){
var news = jsont[i];
html = html + "<h1>"+news.title+"</h1>";
html = html + "<h2>"+news.date+" "+news.source+" "+news.content + "</h2>";
html = html + "<hr/>";

}
document.getElementById("container").innerHTML=html;
}
}
</script>
</body>
</html>

效果:可以看到,刷新界面后,控制台立即打印出”请求发送成功”,然后等待后台响应发送到html中回显;说明:当设置为异步后,请求发送后、响应回来前,程序会继续执行,只是xml.onreadystatechange = function(){}来实时监控响应的状态,程序可以通过此方法来按照不同的需求做出不同的程序

ajax14