一、概述
- 什么是 AJAX 请求
AJAX 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。 - AJAX 是一种浏览器通过 JavaScript 异步发起请求,局部更新页面的技术。
- AJAX 请求的局部更新,浏览器地址栏不会发生变化
- 局部更新不会舍弃原来页面的内容
二、JavaScript 原生 Ajax 请求
(一)原生 Ajax 请求的步骤
- 我们首先要创建 XMLHttpRequest 对象
- 调用 open 方法设置请求参数
- 在 send 方法前绑定 onreadystatechange
- 调用 send 方法发送请求
(二)XMLHttpRequest
- XMLHttpRequest 是 AJAX 的基础
- XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新
- 如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法:
方法 | 描述 |
---|---|
open(method,url,async) | 规定请求的类型、URL 以及是否异步处理请求。
|
send(string) | 将请求发送到服务器。 string:仅用于 POST 请求 |
- XMLHttpRequest 对象如果要用于 AJAX 的话,其 open() 方法的 async 参数必须设置为 true
(三)服务器响应
如需获得来自服务器的响应,请使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性。
属性 | 描述 |
---|---|
responseText | 获得字符串形式的响应数据。 |
responseXML | 获得 XML 形式的响应数据。 |
开发中我们一般使用responseText
(四)onreadystatechange 事件
- 当请求被发送到服务器时,我们需要执行一些基于响应的任务。
- 每当 readyState 改变时,就会触发 onreadystatechange 事件。
- readyState 属性存有 XMLHttpRequest 的状态信息。
- 下面是 XMLHttpRequest 对象的三个重要的属性:
属性 | 描述 |
---|---|
onreadystatechange | 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。 |
readyState | 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
|
status | 200: “OK” 404: 未找到页面 |
在 onreadystatechange 事件中,我们规定当服务器响应已做好被处理的准备时所执行的任务。
当 readyState 等于 4 且状态为 200 时,表示响应已就绪
(五)案例演示
ajax.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
// 在这里使用javaScript语言发起Ajax请求,访问服务器AjaxServlet中的javaScriptAjax()
function ajaxRequest() {
//1、我们首先要创建XMLHttpRequest
var xmlHttpRequest = new XMLHttpRequest();
//2、调用open方法设置请求参数
xmlHttpRequest.open("GET","http://localhost:8080/WebStudy/ajaxServlet?action=javaScriptAjax",true);
//3、在send方法前绑定onreadystatechange事件,处理请求完成、响应就绪后的操作。
xmlHttpRequest.onreadystatechange=function() {
//当xmlHttpRequest.readyState == 4,证明请求已完成,且响应已就绪
if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200) {
var jsonObj=JSON.parse(xmlHttpRequest.responseText);//responseText即服务器响应的JSON字符串
// 把响应的数据局部更新在页面上
document.getElementById("div01").innerHTML = "编号:" + jsonObj.id + " , 姓名:" + jsonObj.name;
}
}
//4、调用send方法发送请求
xmlHttpRequest.send();
}
</script>
</head>
<body>
<button onclick="ajaxRequest()">ajax请求</button>
<div id="div01"></div>
</body>
</html>
AjaxServlet:
import com.fox.bean.Person;
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class AjaxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决post请求中文乱码问题
// 一定要在获取请求参数之前调用才有效
req.setCharacterEncoding("UTF-8");
// 解决响应中文乱码
resp.setContentType("text/html; charset=UTF-8");
String action = req.getParameter("action");
try {
// 获取action业务鉴别字符串,获取相应的业务 方法反射对象
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
// 调用目标业务方法
method.invoke(this, req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void javaScriptAjax(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Ajax请求过来了");
Person person = new Person(1, "小明");
// json格式的字符串
Gson gson = new Gson();
String personJsonString = gson.toJson(person);
//服务器响应
response.getWriter().write(personJsonString);
//响应完成后,客户端怎么接收呢,这就要用到xmlHttpRequest中的responseText
}
}
web.xml:
<servlet>
<servlet-name>AjaxServlet</servlet-name>
<servlet-class>com.fox.servlet.AjaxServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AjaxServlet</servlet-name>
<url-pattern>/ajaxServlet</url-pattern>
</servlet-mapping>
这样就实现了页面的局部更新,而不是响应完成后跳转到新的页面
(六)异步请求
对于 web 开发人员来说,发送异步请求是一个巨大的进步。很多在服务器执行的任务都相当费时。AJAX 出现之前,这可能会引起应用程序挂起或停止。
但有了 AJAX,JavaScript 无需等待服务器的响应,而是:
- 在等待服务器响应时执行其他脚本
- 当响应就绪后才对响应进行处理
例如一个网页中有许多按钮,点击了按钮A,在服务器完成响应按钮A之前,无法点击其他按钮,这叫做同步;而点击了按钮A,无需等待A响应,依旧可以接着点击其他按钮,这叫做异步,能够提升用户的体验。
案例:
上例中的代码做以下改动:
function ajaxRequest() {
//1、我们首先要创建XMLHttpRequest
var xmlHttpRequest = new XMLHttpRequest();
//2、调用open方法设置请求参数
xmlHttpRequest.open("GET","http://localhost:8080/WebStudy/ajaxServlet?action=javaScriptAjax",true);
//3、在send方法前绑定onreadystatechange事件,处理请求完成、响应就绪后的操作。
xmlHttpRequest.onreadystatechange=function() {
if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200) {
var jsonObj=JSON.parse(xmlHttpRequest.responseText);//responseText即服务器响应的JSON字符串
// 把响应的数据局部更新在页面上
document.getElementById("div01").innerHTML = "编号:" + jsonObj.id + " , 姓名:" + jsonObj.name;
}
}
//4、调用send方法发送请求
xmlHttpRequest.send();
alert("我是最后一行的代码");
}
protected void javaScriptAjax(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Ajax请求过来了");
Person person = new Person(1, "小明");
//延时3秒
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// json格式的字符串
Gson gson = new Gson();
String personJsonString = gson.toJson(person);
//服务器响应
response.getWriter().write(personJsonString);
//响应完成后,客户端怎么接收呢,这就要用到xmlHttpRequest中的responseText
}
结果先执行完ajax.html所有脚本:
三秒后响应就绪,才局部更新:
结论:有了 AJAX,JavaScript 无需等待服务器的响应,而是在等待服务器响应时执行其他脚本,当响应就绪后才对响应进行处理
三、jQuery中 的 Ajax 请求
通过上面的代码我们发现。编写原生的 JavaScript 我们自己要写很多的代码。而且还要考虑浏览器兼容问题。所以使用起来非常的不方便。那我们工作之后怎么处理 Ajax 请求呢?我们前面学到的 jQuery 框架,它就有很好的 Ajax 解决方案。
JQuery 的 Ajax 请求一般涉及到五个方法:
- 四个 Ajax 请求方法:
- $.ajax 方法
- $.get 方法
- $.post 方法
- $.getJSON 方法
- 一个表单序列化方法:
- serialize()表单序列化方法
(一)$.ajax 方法
$.ajax方法参数:
- url 表示请求的地址
- type 表示请求的类型 GET 或 POST 请求
- data 表示发送给服务器的数据,格式有两种:
key1=value1&key2=value2
{key1: 'value1', key2: 'value2'}
- success 请求成功后响应的回调函数,传入返回后的数据,以及包含成功代码的字符串。
- dataType 响应的数据类型,常用的数据类型有:
- text 表示纯文本
- xml 表示 xml 数据
- json 表示 json 对象
案例:
ajax.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function () {
$("#ajaxBtn").click(function () {
$.ajax({
url:"http://localhost:8080/WebStudy/ajaxServlet",
data:"action=jQueryAjax",
//或者data:{action:"jQueryAjax"},
type:"GET",
success:function (msg) {//这个参数msg是由服务器返回,并根据dataType参数进行处理后的数据
//由于dataType是text,因此msg是text,我们要将其转换成json对象
var jsonObj=JSON.parse(msg);
$("#div01").html("编号:"+jsonObj.id+",姓名:"+jsonObj.name);
},
dataType:"text"
});
});
});
</script>
</head>
<body>
<button id="ajaxBtn">$.ajax请求</button>
<div id="div01"></div>
</body>
</html>
AjaxServlet:
import com.fox.bean.Person;
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class AjaxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决post请求中文乱码问题
// 一定要在获取请求参数之前调用才有效
req.setCharacterEncoding("UTF-8");
// 解决响应中文乱码
resp.setContentType("text/html; charset=UTF-8");
String action = req.getParameter("action");
try {
// 获取action业务鉴别字符串,获取相应的业务 方法反射对象
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
// 调用目标业务方法
method.invoke(this, req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void jQueryAjax(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Person person = new Person(1, "小明");
// json格式的字符串
Gson gson = new Gson();
String personJsonString = gson.toJson(person);
//服务器响应
response.getWriter().write(personJsonString);
}
}
web.xml:
<servlet>
<servlet-name>AjaxServlet</servlet-name>
<servlet-class>com.fox.servlet.AjaxServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AjaxServlet</servlet-name>
<url-pattern>/ajaxServlet</url-pattern>
</servlet-mapping>
从本例我们发现,如果dataType设置为text,那么还要多加一步:var jsonObj=JSON.parse(msg);
。因此我们可以直接将dataType设置为json,如下:
$.ajax({
url:"http://localhost:8080/WebStudy/ajaxServlet",
data:"action=jQueryAjax",
//或者data:{action:"jQueryAjax"},
type:"GET",
success:function (msg) {//这个参数msg是由服务器返回,并根据dataType参数进行处理后的数据
$("#div01").html("编号:"+msg.id+",姓名:"+msg.name);
},
dataType:"json"
});
(二)$.get 方法和$.post 方法
这是一个简单的 GET 请求功能和简单的 POST请求功能以取代复杂的 $.ajax 。请求成功时可调用回调函数。如果需要在出错时执行函数,请使用 $.ajax。
$.get 方法和$.post 方法参数:
- url 请求的 url 地址
- data 发送的数据
- callback 成功的回调函数
- type 返回的数据类型
其实就是比$.ajax少了一个请求类型参数,因为$.get方法和$.post 方法已经确定了请求类型是GET或POST
案例:
ajax.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function () {
$("#getBtn").click(function () {
$.get("http://localhost:8080/WebStudy/ajaxServlet","action=jQueryGet",function (msg) {
$("#div01").html("编号:"+msg.id+",姓名:"+msg.name);
},"json");
});
$("#postBtn").click(function () {
$.post("http://localhost:8080/WebStudy/ajaxServlet","action=jQueryPost",function (msg) {
$("#div01").html("编号:"+msg.id+",姓名:"+msg.name);
},"json");
});
});
</script>
</head>
<body>
<button id="getBtn">$.get请求</button>
<button id="postBtn">$.post请求</button>
<div id="div01"></div>
</body>
</html>
AjaxServlet:
import com.fox.bean.Person;
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class AjaxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决post请求中文乱码问题
// 一定要在获取请求参数之前调用才有效
req.setCharacterEncoding("UTF-8");
// 解决响应中文乱码
resp.setContentType("text/html; charset=UTF-8");
String action = req.getParameter("action");
try {
// 获取action业务鉴别字符串,获取相应的业务 方法反射对象
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
// 调用目标业务方法
method.invoke(this, req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void jQueryGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Person person = new Person(1, "小明");
// json格式的字符串
Gson gson = new Gson();
String personJsonString = gson.toJson(person);
//服务器响应
response.getWriter().write(personJsonString);
}
protected void jQueryPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Person person = new Person(2, "小红");
// json格式的字符串
Gson gson = new Gson();
String personJsonString = gson.toJson(person);
//服务器响应
response.getWriter().write(personJsonString);
}
}
(三)$.getJSON 方法
$.getJSON 方法参数:
- url 请求的 url 地址
- data 发送给服务器的数据
- callback 成功的回调函数
可以看出,又少了一个参数,因为请求类型已经确定为GET,dataType已经确定为json
案例:
ajax.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function () {
$("#getJSONBtn").click(function(){
$.getJSON("http://localhost:8080/WebStudy/ajaxServlet","action=jQueryGetJSON",function (msg) {
$("#div01").html("编号:" + msg.id + " , 姓名:" + msg.name);
});
});
});
</script>
</head>
<body>
<button id="getJSONBtn">$.getJSON请求</button>
<div id="div01"></div>
</body>
</html>
AjaxServlet:
import com.fox.bean.Person;
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class AjaxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决post请求中文乱码问题
// 一定要在获取请求参数之前调用才有效
req.setCharacterEncoding("UTF-8");
// 解决响应中文乱码
resp.setContentType("text/html; charset=UTF-8");
String action = req.getParameter("action");
try {
// 获取action业务鉴别字符串,获取相应的业务 方法反射对象
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
// 调用目标业务方法
method.invoke(this, req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void jQueryGetJSON(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Person person = new Person(1, "小明");
// json格式的字符串
Gson gson = new Gson();
String personJsonString = gson.toJson(person);
//服务器响应
response.getWriter().write(personJsonString);
}
}
(四)serialize()表单序列化方法
serialize()可以把表单中所有表单项的内容都获取到,并以字符串 name=value&name=value 的形式进行拼接。
案例:
ajax.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function () {
$("#submit").click(function(){
$.getJSON("http://localhost:8080/WebStudy/ajaxServlet","action=jQuerySerialize&"+$("#form01").serialize(),function (data) {
$("#div01").html("编号:" + data.id + " , 姓名:" + data.name);
});
});
});
</script>
</head>
<body>
<form id="form01" >
用户名:<input name="username" type="text" /><br/>
密码:<input name="password" type="password" /><br/>
下拉单选:<select name="single">
<option value="Single">Single</option>
<option value="Single2">Single2</option>
</select><br/>
下拉多选:
<select name="multiple" multiple="multiple">
<option selected="selected" value="Multiple">Multiple</option>
<option value="Multiple2">Multiple2</option>
<option selected="selected" value="Multiple3">Multiple3</option>
</select><br/>
复选:
<input type="checkbox" name="check" value="check1"/> check1
<input type="checkbox" name="check" value="check2" checked="checked"/> check2<br/>
单选:
<input type="radio" name="radio" value="radio1" checked="checked"/> radio1
<input type="radio" name="radio" value="radio2"/> radio2<br/>
</form>
<button id="submit">提交--serialize()</button>
<div id="div01"></div>
</body>
</html>
AjaxServlet:
import com.fox.bean.Person;
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class AjaxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决post请求中文乱码问题
// 一定要在获取请求参数之前调用才有效
req.setCharacterEncoding("UTF-8");
// 解决响应中文乱码
resp.setContentType("text/html; charset=UTF-8");
String action = req.getParameter("action");
try {
// 获取action业务鉴别字符串,获取相应的业务 方法反射对象
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
// 调用目标业务方法
method.invoke(this, req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void jQuerySerialize(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("用户名:" + request.getParameter("username"));
System.out.println("密码:" + request.getParameter("password"));
Person person = new Person(1, "小明");
// json格式的字符串
Gson gson = new Gson();
String personJsonString = gson.toJson(person);
//服务器响应
response.getWriter().write(personJsonString);
}
}
这样提交表单后就能将表单的所有内容以Ajax请求的方式发给服务器,不用跳转到新的页面。