AJAX(Asynchronous Javascript And XML,异步Javascript和XML),是一种用于创建快速动态网页得技术。从名字上看,AJAX并不是一种全新得技术,而是整合了JavaScript和XML等现有技术。
AJAX通过在后台与服务器之间交换少量数据的方式,实现网页的异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的局部内容进行更新,例如:在网页中观看电影时,如果点击了左下角的“赞”图标,那么“赞”的数量就会从1234增加到1235(即局部内容进行了更新),而当前网页并不会被刷新。
而传统的网页(不使用AJAX)如果需要更新内容,就必须重新加载整个网页。试想如果点一下“赞”,网页就刷新、视频就得从头开始看,肯定很不方便得。
1.使用JavaScript实现AJAX
使用JavaScript来实现AJAX,主要是借助XMLHttpRequest对象向服务器发送请求,并获取返回结果。
(1)与服务器建立连接open(methodName , URL , isAsync)
methodName指定请求得方法名;URL指定请求地址;isAsync是一个boolean值,代表是否采用异步方式(默认true;若无特殊要求,此值一般都填true)。
(2) 发送HTTP请求send(content),content是可选项,用来指定请求参数,将请求参数作为请求得一部分一起发送给服务器。通常只在post方式下才使用content参数(get请求方式不携带请求体)。
(3)在HTTP请求头中设置key/value对setRequestHeader(header , value)
在HTTP请求头中设置key/value对时,若为get请求方式则不用设置;若为post方式,当请求头中包含文件上传元素时,设置为:
XMLHttpRequest.setRequestHeader("Content-Type" , "mulipart/form-data");
而当请求中不包含文件上传时,设置为:
XMLHttpRequest.setRequestHeader("Content-Type" , "application/x-www-form-urlencoderd")
2.XMLHttpRequest对象的常用属性
(1)readystate
readystate表示XMLHttpRequest对象发送的HTTP请求状态,共5种,如下:
状态值 简介
0 表示XMLHttpRequest对象没有初始化
1 表示XMLHttpRequest对象开始发送请求:已经执行了open()方法并完成了相关资源的准备
2 表示XMLHttpRequest对象已将请求发送完毕:已经执行了send()方法来发送请求,但是还没有收到响应
3 表示XMLHttpRequest对象开始读取响应信息:已经接收到HTTP响应的头部信息,但是还没有将响应体接受完毕
4 表示XMLHttpRequest对象将响应信息全部读取完毕
(2)status
status表示HTTP响应中的状态码,各状态吗的含义如下:
状态码 含义
200 服务器正常响应
400 无法找到请求的资源
403 没有访问权限
404 访问的资源不存在
500 服务器内部错误,很可能是服务器代码有错
可以发现,只有当状态码为200时才表示响应成功;否则,说明HTTP响应不正常。
(3)onreadystatechange
指定XMLHttpRequest对象的回调函数。每当readyState的属性值改变时,此回调函数就会被调用一次。
(4)responseText
从服务器返回的string格式的响应内容。
(5)responseXML
从服务器端返回的XML格式的数据,可以直接被当成DOM对象使用。
3.使用AJAX实现异步请求
使用JavaScript实现AJAX,分为post或get两种方式,但大体的步骤都相同,其内容如下:
(1)创建XMLHttpRequest对象,即创建一个异步调用对象。
(2)设置并编写回调函数。
(3)初始化XMLHttpRequest对象的参数值(若是post方式,还需要设置“请求头”)。
(4)发送HTTP请求。
(5)在回调函数中编写获取异步调用返回的数据。
(6)使用JavaScript或jQuery等实现局部刷新。
其实例如下:
很多手机软件、网站都会要求绑定手机号码,并且一个手机号码只能绑定一个账号。因此,在绑定手机号码之前,程序会先检验此号码是否已经被绑定:若已经被绑定,则提示“此号码已经被绑定,请尝试其他号码”;否则提示“绑定成功”。现在就用AJAX作为前端技术来实现此功能。
(1)采用post方式
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import entity.Address;
import entity.Student;
/**
* Servlet implementation class StudentServlet
*/
@WebServlet("/StudentServlet")
public class StudentServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public StudentServlet() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置发送到客户端响应的内容类型
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String mobile = request.getParameter("number");
//假设已经存在号码为12345678910这个电话号码
if("12345678910".equals(mobile)){
out.print("true");
}else{
out.print("false");
}
out.close();
}
}
-----------------------------------
<%@ page language="java" import="entity.Student" import="entity.Address" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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 src="${pageContext.request.contextPath}/js/jquery-3.2.1.js"></script>
<script>
function isExist(){
var $mobile = $("#mobile").val();
if($mobile==null||$mobile.length!=11){
$("#dog").html("请输入正确的号码");
}else{
//1.创建XMLHttpRequest对象
//注意 XMLHttpRequest对象前没有var,所以是一个全局变量
xmlHttpRequest = new XMLHttpRequest();
//2.设置回调函数(注意:回调函数的名字后面没有小括号"()"
xmlHttpRequest.onreadystatechange = callback;
//3.初始化XMLHttpRequest对象的参数值及请求头
var url = "${pageContext.request.contextPath}/StudentServlet";
xmlHttpRequest.open("post",url,true);
//POST方式需要设置“请求头”
xmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//4.发送HTTP请求
var data = "number="+$mobile;
xmlHttpRequest.send(data);
}
//AJAX回调函数
function callback(){
if(xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200){
//获取异步调用返回的数据
var data = xmlHttpRequest.responseText;
//使用JavaScript或jQuery等实现局部更新
if($.trim(data) == "true"){
$("#dog").html("此号码已经被绑定,请尝试其他号码");
}else{
$("#dog").html("绑定成功!!");
}
}
}
}
</script>
</head>
<body>
<input type="text" id="mobile">
<span style="color:red" id="dog"></span><br/>
<input type="button" value="绑定" οnclick="isExist()">
</body>
</html>
可以发现,服务器端是通过PrintWriter对象out,将结果以字符串的形式传递给客户端的;而客户端通过XMLHttpRequest对象的
responseText属性来获取该结果;此外,客户端中responseText属性的返回值是String类型,所以在服务端也应该传递String类型的结果。
(1)输入已存在的号码:12345678910
(2)输入暂不存在的号码,18078326104
(3)输入错误格式的号码:123456
2.采用get方式
如果将上例改为get方式的AJAX,则只需要做四处更改,具体内容如下。
(1) 将 XMLHttpRequest 对象的 open() 方法中的 method 参数值改为get;
(2) 给 XMLHttpReques t对象的 send() 方法中的 url 参数,加上需要传递的参数值(把url的值,从“请求地址”改为“请求地址?参数名1=参数值1&参数名2=参数值2&...”)
(3) 删除设置 XMLHttpRequest 对象头信息的代码
(4)将 XMLHttpRequest 对象的 send(data) 方法中的data,改为null。(将data的值,转移到了open() 方法的 ur l参数中)
由此发现,将post方式改为get方式后,把需要发送的参数从send() 方法转移到open方法中的 url 参数中,并且不需要再设置头信息。其他代码一样,不同的代码如下:
function isExist(){
var $mobile = $("#mobile").val();
if($mobile==null||$mobile.length!=11){
$("#dog").html("请输入正确的号码");
}else{
//1.创建XMLHttpRequest对象
//注意 XMLHttpRequest对象前没有var,所以是一个全局变量
xmlHttpRequest = new XMLHttpRequest();
//2.设置回调函数(注意:回调函数的名字后面没有小括号"()"
xmlHttpRequest.onreadystatechange = callback;
//3.初始化XMLHttpRequest对象的参数值及请求头
var data = "number="+$mobile;
var url = "${pageContext.request.contextPath}/StudentServlet";
xmlHttpRequest.open("get",url+"?"+data,true);
//POST方式需要设置“请求头”
//xmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//4.发送HTTP请求
xmlHttpRequest.send(null);
}
2.使用jQuery实现AJAX
除了使用JavaScript以为,还可以使用jQuery来实现AJAX,而且更加简洁、方便。jQuery方式的AJAX,主要是通过jQuery提供的
$.ajax()、$.get()、$.post()、$(selector).load()等方法来实现的。
(1)$.ajax()方法
其语法如下:
$.ajax({
url:请求路径,
type:请求方式,
data:请求数据,
.......
success:function(result,textStatus){
请求成功后执行的函数体
},
error:function(){
请求失败后执行的函数体
},
dataType:预期服务器返回的数据类型
});
基本格式:所有参数都写在$.ajax({...})中,不同参数之间用逗号隔开,每个参数以”参数名:参数值“的方式书写。
本质上就是将JavaScript 中 XMLHttpRequest的属性和方法,以参数化的形式集中管理,如下所示:
参数 简介
String url 发送请求的地址,默认是当前页地址
String type 请求方式(post 或 get),默认为get
number timeout 设置请求超时的时间(单位是毫秒)
String data 或 Object data 发送到服务器的数据。若是get方式的请求,data值将以地址重写的方式附加在url后;若是post 方式,data值将作为请求体的一部分
String dataType 预期服务器返回的数据类型,可用类型有XML、HTML、JSON、Text等。如果不指定,jQuery 会自动根据HTTP中的MIME信息返回 responseXML 或 responseText
function success(Object result , String textStatus) 请求成功后调用的函数,result:可选项,由服务器返回的数据
textStatus:可选项,描述请求类型
function error(XMLHttpRequest xhr , 请求失败后调用的函数,xhr:可选项,XMLHttpRequest 对象
String errorMessage , Exception e) errorMessage:可选项,错误信息,e:可选项,引用的异常对象
除了以上介绍的以外,还有cache , async , beforeSend , complete ,contentType 等其他参数,读者可以访问:
http://www.w3school.com.cn/jquery/ajax_ajax.asp进行学习。
现在用$.ajax()方法,来实现“检测手机号码是否绑定”的需求:
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import entity.Address;
import entity.Student;
/**
* Servlet implementation class StudentServlet
*/
@WebServlet("/StudentServlet")
public class StudentServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public StudentServlet() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置发送到客户端响应的内容类型
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String mobile = request.getParameter("number");
//假设已经存在号码为12345678910的电话号码
if("12345678910".equals(mobile)){
out.print("true");
}else{
out.print("false");
}
out.close();
}
}
-------------------------
<%@ page language="java" import="entity.Student" import="entity.Address" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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 src="${pageContext.request.contextPath}/js/jquery-3.2.1.js"></script>
<script>
function isExist(){
var $mobile = $("#mobile").val();
if($mobile == null||$mobile.length != 11){
$("#dog").html("请输入正确的号码!");
}else{
$.ajax({
url:"${pageContext.request.contextPath}/StudentServlet",
type:"get",
data:"number="+$mobile,
success:function(result){
if($.trim(result) == "true"){
$("#dog").html("该号码已经绑定,请尝试别的号码!");
}else{
$("#dog").html("绑定成功!");
}
},
error:function(){
$("#dog").html("检测失败");
}
});
}
}
</script>
</head>
<body>
<input type="text" id="mobile">
<span style="color:red" id="dog"></span><br/>
<input type="button" value="绑定" οnclick="isExist()">
</body>
</html>
(1)输入已存在的号码:12345678910
(2)输入暂不存在的号码,18078326104
(3)输入错误格式的号码:123456
2. $.get()方法
$.get(...)方法指定以get方式发送请求,与$.ajax({...})方法在语法上的区别:参数值必须按照一定的顺序书写;省略了参数名、type参数及error()参数;$.ajax({....})的各个参数是用大括号{ }括起来的,而$.get(...)没有大括号。
其语法(各参数顺序不可变)如下:
$.get(
请求路径,
请求参数,
function(result , textStatus , xhr){
请求成功后执行的函数体
},
预期服务器返回的数据类型
);
<script>
function isExist(){
var $mobile = $("#mobile").val();
if($mobile == null||$mobile.length != 11){
$("#dog").html("请输入正确的号码!");
}else{
$.get(
"${pageContext.request.contextPath}/StudentServlet",
"number="+$mobile, //也可以这样: {number:$mobile},
function(result){
if($.trim(result) == "true"){
$("#dog").html("该号码已经绑定,请尝试别的号码啊");
}else{
$("#dog").html("恭喜你,绑定号码成功");
}
}
);
}
}
</script>
即等价于:
$.ajax({
url:请求路径,
type:请求方式,
data:请求数据,
.......
success:function(result,textStatus){
请求成功后执行的函数体
},
error:function(){
请求失败后执行的函数体
},
dataType:预期服务器返回的数据类型
});
3. $.post()方法
$.post(
请求路径,
请求参数,
function(result , textStatus , xhr){
请求成功后执行的函数体
},
预期服务器返回的数据类型
);
由上述语法可见,只是将方法名$.get()变为$.post(),其他内容完全一致。
4.$(selector).load()方法
$(selector).load()方法是在$.get() 、$.post()方法的基础上进一步优化,不但会发送请求,还会将响应的数据放入指定的元素。其中$(selector)是指 jQuery 选择器指定的元素。
其语法如下:
$(selector).load(
请求路径,
请求数据,
function(result , textStatus , xhr){
请求成功后执行的函数体
},
预期服务器返回的数据类型
);
因为load()方法会直接将响应结果放入指定元素,所以通常可以省略load()中的 function()函数。
在此用 load() 方法,在实现一下“检测手机号码是否已绑定”
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import entity.Address;
import entity.Student;
/**
* Servlet implementation class StudentServlet
*/
@WebServlet("/StudentServlet")
public class StudentServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public StudentServlet() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置发送到客户端响应的内容类型
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String mobile = request.getParameter("number");
//假设已经存在号码为12345678910这个电话号码
if("12345678910".equals(mobile)){
out.print("该号码已经被绑定啦,试试别的号码吧 !");
}else{
out.print("绑定号码成功!");
}
out.close();
}
}
仔细观察,客户端用load()方法时,服务端直接将结果字符串返回。
-----------------------------------------------
<%@ page language="java" import="entity.Student" import="entity.Address" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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 src="${pageContext.request.contextPath}/js/jquery-3.2.1.js"></script>
<script>
function isExist(){
var $mobile = $("#mobile").val();
if($mobile == null||$mobile.length != 11){
$("#dog").html("请输入正确的号码!");
}else{
$("#dog").load(
"${pageContext.request.contextPath}/StudentServlet",
"number="+$mobile
);
}
}
</script>
</head>
<body>
<input type="text" id="mobile">
<span style="color:red" id="dog"></span><br/>
<input type="button" value="绑定" οnclick="isExist()">
</body>
</html>
输入一个已经存在的号码:12345678910
输入一个不存在的号码:18078326105
输入一个不符合的号码:123456