AJAX
1、概述
2、XMLHttpRequest 对象
3、AJAX 异步实现步骤
4、使用 Ajax 计算 BMI
5、AJAX 联合 json 使用
6、FormData 对象
概述
1、AJAX 是用来做局部刷新的。局部刷新使用的核心对象是异步对象(XMLHttpRequest)。这个异步对象是存在浏览器内存中的 ,使用 javascript 语法创建和使用 XMLHttpRequest 对象。AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分页面内容的新方法。
2、ajax:Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
Asynchronous:异步。
JavaScript:javascript脚本,在浏览器中执行。
xml:一种数据格式
3、ajax 是一种做局部刷新的新方法,不是一种语言。ajax 包含的技术主要有 javascript、dom、css、xml等等。核心是 javascript 和 xml :
javascript:负责创建异步对象, 发送请求, 更新页面的 dom 对象。 ajax 请求需要服务器端的数据。
xml:网络中的传输的数据格式。
全局刷新和局部刷新
- 全局刷新
整个浏览器被新的数据覆盖。 在网络中传输大量的数据。 浏览器需要加载,渲染页面。
1、必须由浏览器亲自向服务端发送请求协议包。
2、这个行为导致服务端直接将【响应包】发送到浏览器内存中。
3、这个行为导致浏览器内存中原有内容被覆盖掉。
4、这个行为导致浏览器在展示数据时候,只有响应数据可以展示。 - 局部刷新
在浏览器器的内部,发起请求,获取数据,改变页面中的部分内容。其余的页面无需加载和渲染。 网络中数据传输量少, 给用户的感受好。(浏览器在展示数据时,此时在窗口既可以看到本次的响应数据,同时又可以看到浏览器内存中原有数据。)
1、不能由浏览器发送请求给服务端。
2、浏览器委托浏览器内存中一个脚本对象代替浏览器发送请求。
3、这个行为导致导致服务端直接将【响应包】发送脚本对象内存中。
4、这个行为导致脚本对象内容被覆盖掉,但是此时浏览器内存中绝大部分内容没有收 到任何影响。
5、这个行为导致浏览器在展示数据时候,同时展示原有数据和响应数据。
异步请求对象
- 概述
1、在局部刷新,需要创建一个对象,代替浏览器发起请求的行为,这个对象存在内存中。 代替浏览器发起请求并接收响应数据。这个对象叫做异步请求对象。
2、全局刷新是同步行为,局部刷新是异步行为(浏览器数据没有全部更新)。这个异步对象用于在后台与服务器交换数据,XMLHttpRequest 就是我们说的异步对象。 - XMLHttpRequest 对象的作用
1、在不重新加载页面的情况下更新网页。
2、在页面已加载后向服务器请求数据。
3、在页面已加载后从服务器接收数据。
所有现代浏览器 (IE7+、Firefox、Chrome、Safari 以及 Opera) 都内建了 XMLHttpRequest 对象。通过一行简单的 JavaScript 代码,我们就可以创建 XMLHttpRequest 对象。
var xmlhttp = new XMLHttpRequest();
AJAX 中的核心对象就是 XMLHttpRequest。
XMLHttpRequest 对象
常用属性
属性 | 说明 |
---|---|
onprogress | 分成上传和下载两种情况,下载的 progress 事件属于 XMLHttpRequest 对象;上传的 progress 事件属于 XMLHttpRequest.upload 对象。可以设置文件上传或者下载的进度处理事件 |
ontimeout | HTTP请求超时事件触发器 |
onreadystatechange | 状态改变事件触发器,每个状态改变都会触发这个事件触发器 |
readyState | 数值,代表 XMLHttpRequest 的5个状态 |
responseText | 服务器的响应,字符串 |
responseXML | 服务器的响应,XML DOM 对象 |
status | 服务器返回的 HTTP 状态码 |
timeout | 设置 HTTP 请求的时限,单位为 ms,超过时限自动停止 HTTP 请求 |
abort() | 停止当前请求 |
getResponseHeader(header) | 返回指定响应头的字符串值 |
常用方法
方法 | 说明 |
---|---|
abort() | 停止当前请求 |
getAllResponseHeaders() | 将 HTTP 请求的所有响应头作为键/值对返回 |
getResponseHeader(header) | 返回指定响应头的字符串值 |
open(method, URL, asynFlag, userName, passWord) | 建立对服务器的请求,method 参数是 HTTP 请求方法,URL参数可以是相对或绝对 URL。该方法还有3个可选参数。asynFlag:是否非同步标记,userName:用户名,passWord:密码 |
setResquestHeader(header, value) | 把指定请求报头设置为所提供的值,此方法必须在 open() 方法和 send() 之间调用。如果多次对同一个请求头赋值,只会生成一个合并了多个值的请求头。 |
send(content) | 向服务器发送请求(空字符串必须是 null) |
AJAX 异步实现步骤
1、创建异步对象
var xmlHttp = new XMLHttpRequest();
2、给异步对象绑定事件(onreadystatechange)
(1)、当异步对象发起请求,获取了数据都会触发这个事件。这个事件需要指定一个函数, 在函数中处理状态的变化。
(2)、当请求被发送到服务器时,我们需要执行一些基于响应的任务。每当 readyState 改变时,就会触发 onreadystatechange 事件。此事件可以指定一个处理函数 function。
(3)、通过判断 XMLHttpReqeust 对象的状态,获取服务端返回的数据。 语法:
xmlHttp.onreadystatechange = function() {
if( xmlHttp.readyState == 4 && xmlHttp.status == 200) {
//处理服务器返回数据
}
}
3、初始化异步请求对象
(1)、初始化请求参数,方法:open(method,url,async)
xmlHttp.open(请求方式get|post, "服务器端的访问地址", 同步|异步请求(默认是true,异步请求))
(2)、参数说明:
method:请求的类型(GET 或 POST)(使用 post 时必须加上这段,会自动附加请求报头
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
)
url:服务器的 servlet 地址
async:true(异步)或 false(同步)(默认true)
异步:使用异步对象发起请求后,不用等待数据处理完毕,就可以执行其它的操作(send 之后的代码可以在数据处理前执行)。
同步:异步对象必须处理完成请求,从服务器端获取数据后,才能执行 send 之后的代码。任意时刻只能执行一个异步请求。(某一个时刻,浏览器只能委托一个异步请求对象发送请求,必须等待请求处理完成。浏览器委托异步请求对象工作期间,浏览器处于等待状态。不能执行其他命令。不推荐使用。)
(3)、例如:
xmlHttp.open(“get”,”http:192.168.1.20:8080/myweb/query?name=zs&pwd=123”,true);
4、使用异步对象发送请求
xmlHttp.send()
5、接收服务器响应的数据
(1)、如需获得来自服务器的响应,使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性。
responseText:获得字符串形式的响应数据。
responseXML:获得 XML 形式的响应数据。
(2)、使用例子:xmlHttp.responseText
访问地址: 使用get方式传递参数
http://localhost:8080/course_myajax/bmiPrint?name=李四&w=82&h=1.8
- 例子
xmlHttp.onreadystatechange= function(){
处理请求的状态变化。
if(xmlHttp.readyState == 4 && xmlHttp.status== 200 ) {
//可以处理服务器端的数据,更新当前页面
var data = xmlHttp.responseText;
document.getElementById("name").innerText= data;
}
}
XMLHttpRequest 三个重要属性
下面是 XMLHttpRequest 对象的三个重要的属性。
- onreadystatechange 属性
一个 js 函数名 或 直接定义函数,每当 readyState 属性改变时,就会调用该函数。 - readyState 属性
存有 XMLHttpRequest 的状态。从0到4发生变化。
0:(请求未初始化)创建异步请求对象。var xmlHttp = new XMLHttpRequest();
1:(服务器连接已建立)初始化异步请求对象。xmlHttp.open(请求方式,请求地址,true);
2:(请求已接收)异步对象发送请求。xmlHttp.send();
3:(请求处理中)异步对象接收应答数据,从服务端返回数据。XMLHttpRequest 内部处理(注意3是异步对象内部使用, 获取了原始的数据。)。
4:(请求已完成,且响应已就绪)异步请求对象已经将数据解析完毕。此时开发人员才能处理数据(更新当前页面)。 - status 属性:
表示网络请求的状况的(200、404、500),这里需要的是当 status==200 时,表示网络请求是成功的。
回调
当请求的状态变化时,异步对象会自动调用 onreadystatechange 事件对应的函数。
使用 Ajax 计算 BMI
- web.xml:
<servlet>
<servlet-name>BmiServlet</servlet-name>
<servlet-class>com.aaa.ajax.BmiServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BmiServlet</servlet-name>
<url-pattern>/bmi</url-pattern>
</servlet-mapping>
- BmiServlet.java
package com.aaa.ajax;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class BmiServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String height = request.getParameter("height");
String weight = request.getParameter("weight");
float h = Float.parseFloat(height);
float w = Float.parseFloat(weight);
//计算bmi
float bmi = w / (h * h);
String msg;
if (bmi < 18.5){
msg = "您比较瘦";
} else if (bmi > 18.5 && bmi <= 23.9){
msg = "正常";
} else if (bmi > 23.9 && bmi <= 27) {
msg = "您偏于肥胖";
} else {
msg = "您属于肥胖";
}
msg = "您的BMI值是" + bmi + "," + msg;
//响应 ajax 需要的数据,使用 HttpservletResponse 输出数据
response.setContentType("text/html;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.println(msg);
pw.flush();
pw.close();
}
}
- index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<title>局部刷新</title>
<script type="text/javascript">
function doAjax(){
//1、创建异步对象
var xmlHttp = new XMLHttpRequest();
//2、给异步对象绑定事件
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState === 4 && xmlHttp.status === 200 ) {
//处理服务器端的数据,更新当前页面
var data = xmlHttp.responseText;
document.getElementById("mydata").innerText= data;
}
}
//3、初始化异步请求对象
//获取dom对象的value值
var height = document.getElementById("height").value;
var weight = document.getElementById("weight").value;
//拼接参数
var param = "height="+height+"&weight="+weight;
xmlHttp.open("get", "bmi?" + param, true)
//4、使用异步对象发送请求
xmlHttp.send();
}
</script>
</head>
<body>
<div>
<p>局部刷新计算BMI</p>
身高(m):<input type="text" id="height">
<br>
体重(kg):<input type="text" id="weight">
<br>
<input type="button" value="计算BMI" onclick="doAjax()">
<br>
<div id="mydata">等待加载BMI...</div>
</div>
</body>
</html>
- 运行
输入数据点击按钮:
实现局部刷新。
AJAX 联合 json 使用
ajax 发起请求-------servlet(返回的一个 json 格式的字符串:{name:"河北", jiancheng:"冀","shenghui":"石家庄"}
- json 分类:
1、json 对象,JSONObject,这种对象的格式(名称:值), 也可以看做是(key:value)格式。
2、json 数组, JSONArray,基本格式:
[{ name:"河北", jiancheng:"冀","shenghui":"石家庄"} , { name:"山西", jiancheng:"晋","shenghui":"太原"} ] - 为什么要使用 json
1、json格式好理解。
2、json格式数据在多种语言中,比较容易处理。 使用java, javascript读写json格式的数据比较容易。
3、json格式数据他占用的空间下,在网络中传输快, 用户的体验好。 - 处理 json 的工具库
gson(google);fastjson(阿里),jackson,json-lib。
在 js 中的,可以把 json 格式的字符串,转为 json 对象,json 中的 key,就是 json 对象的属性名。
代码示例
(这里使用 jackson)
- Province.java
public class Province {
private int id;
private String name;
private String jiancheng;
private String shenghui;
无参构造...
有参构造...
get、set...
}
- ProvinceDao.java
public class ProvinceDao {
public Province searchById(Integer proid) {
String url = "jdbc:mysql://localhost:3306/ajax?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true";
String username = "root";
String password = "123";
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "";
Province province = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
con = DriverManager.getConnection(url, username, password);
sql = "select name,jiancheng,shenghui from province where id = ?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1,proid);
rs = pstmt.executeQuery();
if(rs.next()){
province = new Province();
province.setName(rs.getString("name"));
province.setJiancheng(rs.getString("jiancheng"));
province.setShenghui(rs.getString("shenghui"));
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
try {
if (con != null){
con.close();
}
if (pstmt != null){
pstmt.close();
}
if (rs != null){
rs.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return province;
}
}
- SearchProServlet.java
public class SearchProServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String proid = request.getParameter("proid");
ProvinceDao provinceDao = new ProvinceDao();
String jsonData = "{}";
if (proid != null && !"".equals(proid.trim())){
Province province = provinceDao.searchById(Integer.parseInt(proid));
//将实体类转换为 json
ObjectMapper om = new ObjectMapper();
jsonData = om.writeValueAsString(province);
}
//响应 ajax 需要的数据,使用 HttpservletResponse 输出数据
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.println(jsonData);
pw.flush();
pw.close();
}
}
- index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<title>局部刷新</title>
<script type="text/javascript">
function search(){
//获取dom对象的value值
var proid = document.getElementById("proid").value;
//1、创建异步对象
var xmlHttp = new XMLHttpRequest();
//2、给异步对象绑定事件
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState == 4 && xmlHttp.status == 200 ) {
//处理服务器端的数据,更新当前页面
var data = xmlHttp.responseText;
//eval是执行括号中的代码,把 json 字符串转化为 json 对象
var jsonObj = eval("("+data+")");
//var jsonObj = JSON.parse(data);
document.getElementById("proname").value = jsonObj.name;
document.getElementById("projc").value = jsonObj.jiancheng;
document.getElementById("prosh").value = jsonObj.shenghui;
}
}
//3、初始化异步请求对象
xmlHttp.open("get", "search?proid=" + proid, true)
//4、使用异步对象发送请求
xmlHttp.send();
}
</script>
</head>
<body>
<div>
<table border="1">
<tr>
<td>省份编号:</td>
<td>
<input type="text" id="proid">
<input type="button" value="搜索" onclick="search()">
</td>
</tr>
<tr>
<td>省份名称:</td>
<td><input type="text" id="proname"></td>
</tr>
<tr>
<td>省份简称:</td>
<td><input type="text" id="projc"></td>
</tr>
<tr>
<td>省会</td>
<td><input type="text" id="prosh"></td>
</tr>
</table>
</div>
</body>
</html>
输入“1”点击搜索:
FormData 对象
1、使用 XMLHttpRequest 对象模拟 Form 表单提交数据给服务器时,无论是 "GET" 还是 "POST" 方法,都涉及了数据的拼接问题。
2、因为是字符串,如果数据项较多时,由于数据的键值必须和 Form 表单完全统一,否则服务器端无法处理,所以太容易出错了。
3、HTML5 新标准中提供了一个 FormData 对象,可以用来轻松模拟表单对象中的数据。
(总结:便于数据的拼接)
创建 FormData 对象
可以使用两种方法创建 FormData 对象。
- 方法一
一种是使用 new 关键字创建,页面上不需要 Form 表单,数据需要使用手工方式逐一附加,方法如下:
var formData = new FormData();
formData.append(key, value);
//key 是键,value 是对应的数据值
- 方法二
直接借助于页面上的 Form 表单,在使用 new 关键字实例化时,将 Form 表单对象直接作为参数,方法如下:
var oform = document.getElementById("myForm");
var formdata = new FormData(oform);
发送 FormData 数据
xmlHttp.send(FormData);
- send 括号中的值可选
在XHR请求中要发送的数据体,可以是以下几种:
1、可以为 Document, 在这种情况下,它在发送之前被序列化。
2、为 XMLHttpRequestBodyInit, 从 per the Fetch spec (规范中)可以是 Blob、BufferSource (en-US)、FormData、URLSearchParams 或者 USVString 对象。
3、null
4、如果没有指定值,则默认值为 null。
XMLHttpRequest.send();
XMLHttpRequest.send(ArrayBuffer data);
XMLHttpRequest.send(ArrayBufferView data);
XMLHttpRequest.send(Blob data);
XMLHttpRequest.send(Document data);
XMLHttpRequest.send(DOMString? data);
XMLHttpRequest.send(FormData data);
如果 send() 发送 DOM 对象,在发送之前,数据会先被串行化。如果发送二进制数据,最好是发送 ArrayBufferView 或 Blob 对象,这使得通过 Ajax 上传文件成为可能。
xhr.send("foo=bar&lorem=ipsum");
// xhr.send('string');
// xhr.send(new Blob());
// xhr.send(new Int8Array());
// xhr.send({ form: 'data' });
// xhr.send(document);
// xhr.send(null);
代码示例
将上面的 SearchProServlet 方法加上 post,这里使用 post 方式,将 index.jsp 中部分代码改成:
<script type="text/javascript">
function search(){
//获取dom对象的value值
var proid = document.getElementById("proid").value;
//使用 FormData 对象进行进行字符串拼接
var formData = new FormData();
formData.append("proid", proid);
//1、创建异步对象
var xmlHttp = new XMLHttpRequest();
//2、初始化异步请求对象
xmlHttp.open("post", "search", true)
//3、给异步对象绑定事件
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState === 4){
if(xmlHttp.status === 200) {
//处理服务器端的数据,更新当前页面
var data = xmlHttp.responseText;
//eval是执行括号中的代码,把 json 字符串转化为 json 对象
var jsonObj = eval("("+data+")");
//var jsonObj = JSON.parse(data);
document.getElementById("proname").value = jsonObj.name;
document.getElementById("projc").value = jsonObj.jiancheng;
document.getElementById("prosh").value = jsonObj.shenghui;
}
}
}
//这句必须有,使用 post 时会自动附加请求报头
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//4、使用异步对象发送请求(使用FormData)
xmlHttp.send(formData);
}
</script>
效果同上