1.Ajax
Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。
1.1.为什么会出现Ajax技术?
因为传统的网页技术,存在诸多不足,每次页面要进行刷新时,需要重新加载整个页面,这样会导致浏览器需要重新解析所有的页面数据,页面中原有的数据,不需要重新解析渲染的也会丢失,服务器,也需要构建整个页面的数据。这样增加了服务器,带宽,浏览器的压力,且用户体验比较差,因为数据的更新是无差别的,需要更新的或者不需要更新的,整个网页数据都会更新。这样可能导致用户的某些不需要更新的行为数据,没重置了,用户需要重新输入且用户不知道被刷新的原因。基于这点,需要根据需求,可选的改变网页上的数据.这种改变网页上的数据,是只改变网页上的部分数据,这样做,服务器需要构建的数据,相对少,传输的数据也少,浏览重新解析渲染的压力也小。这种方法就被称之为局部刷新。
1.2.Ajax技术的原理
为了弥补传统的不足,需要可选的改变网页部分数据,而改变网页的数据的依据需要从服务器获取,那么浏览器就需要与服务器交互。就是浏览器需要发送请求给服务器,但是浏览器没办法可选的修改网页数据,网页数据属于DOM元素,需要使用网页脚本语言进行修改。所以基于这点,开发者让浏览器厂商提供了发送请求的API,通过Javascript,利用浏览器向服务器发送请求,且接收服务器的响应数据,然后根据响应作为更新页面的依据。从而实现了页面局部刷新的效果,这种技术就是Ajax技术。由于,此时浏览器与服务器的交互是在后台的进行交互的,所以这种交互方式也被称之为异步交互。Ajax技术就是一种异步交互。其原理,本质上就是Javascript利用浏览器,在后台与服务交互数据,然后根据,利用Javascript的DOM的API,进行页面更新。
1.3.如何使用Ajax技术?
一般Ajax技术分为原生的Ajax技术或者第三方封装的Ajax技术。
原生的Ajax是指使用Javascript最原始的API与服务器进行交互。
原生Ajax:
XMLHttpRequest:是浏览器内置用于发送请求的对象,用于在后台与服务器交换数据。
注意:
-
所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象。
使用:new XMLHttpRequest();
-
老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 对象:
使用: new ActiveXObject("Microsoft.XMLHTTP");
以上说明XMLHttpRequest对象存在浏览器的兼容性问题.
核心方法:
方法 | 描述 |
---|---|
open(method,url,async) | 规定请求的类型、URL 以及是否异步处理请求。 method:请求的类型;GET 或 POST url:文件在服务器上的位置 async:true(异步)或 false(同步) |
send(string) | 将请求发送到服务器。string:仅用于 POST 请求 |
setRequestHeader(header,value) | 向请求添加 HTTP 头。 header: 规定头的名称 value: 规定头的值 |
事件:
onreadystatechange : 当浏览器与服务器的通信状态发生变化时就会触发该事件。
属性:
属性 | 描述 |
---|---|
onreadystatechange | 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。 |
readyState | 存有 XMLHttpRequest 的状态。 从 0 到 4 发生变化。 0: 请求未初始化 1: 服务器连接已建立 2: 请求已接收 3: 请求处理中 4: 请求已完成,且响应已就绪 |
status | 200: "OK" 404: 未找到页面 |
响应属性:
根据以下属性,可以从请求中获取服务器响应的数据
属性 | 描述 |
---|---|
responseText | 获得字符串形式的响应数据。 |
responseXML | 获得 XML 形式的响应数据。 |
注意:
ajax的响应数据只能是responseText或者responseXML,即Ajax的响应数据只能是字符串。
1.3.1.原生Ajax的使用
- 创建发送请求的对象
- 监听请求对象状态
- 根据状态解析响应数据
- 准备发送请求信息
- 发送请求
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>使用Ajax与服务器交互</title>
</head>
<body>
<div id="divId"></div>
<button id="btn" onclick="sendAjax()">按钮</button>
<script type="text/javascript">
//1. 创建请求对象
var reuqest = new XMLHttpRequest();
//发送ajax请求
function sendAjax() {
//2. 为对象添加监听事件
reuqest.onreadystatechange = function() {
console.log("状态发生了变化");
//接收响应数据
//当请求正常 且 响应完成时接收
console.log(reuqest.readyState);
//只有当请求响应完成 且请求正常时 才接收数据
if (reuqest.readyState == 4 && reuqest.status == 200) {
//获取响应中的字符串数据
var msg = reuqest.responseText;
console.log(msg);
document.getElementById("divId").innerText = msg;
}
}
var param = "name=张三&age=18"
//3. 准备发送请求 建立连接
//reuqest.open("get","ajax.do?"+param,true);
//reuqest.send(param);
reuqest.open("post", "ajax.do?" + param, true);
//4. 发送请求
reuqest.send(param);
}
</script>
</body>
</html>
package com.sxt.controller;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/ajax.do")
public class AjaxController extends HttpServlet {
private static final long serialVersionUID = -116354998836682953L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置编码避免汉字乱码
resp.setCharacterEncoding("UTF-8");
resp.setContentType("charset=UTF-8");
//接收ajax 参数
String name = req.getParameter("name");
String age = req.getParameter("age");
System.out.println(name+" "+age);
System.out.println("有人请求了!!");
//向ajax返回数据
PrintWriter writer = resp.getWriter();
//注意 使用print 不要使用println
writer.print("请求成功");
writer.flush();
}
}
1.3.2.jquery中的ajax
由于原生ajax的API使用相对繁琐,且对浏览器的兼容性相对较差。基于这个原因,jquery插件,对原生ajax的API进行了二次封装,降低了ajax使用的难度,简化了ajax开发的步骤。
在jquery中,ajax提供如下核心方法:
方法名 | 说明 |
---|---|
ajax(option) | 就是进行ajax请求,最接近原生ajax的方法 |
post(option) | 只支持post请求的ajax方法 |
get(option) | 只支持get请求的ajax方法 |
load(option) | 将ajax请求的数据加载到dom中 |
jquery中Ajax相关函数:
函数 | 描述 |
---|---|
jQuery.ajax() | 执行异步 HTTP (Ajax) 请求。 |
.ajaxComplete() | 当 Ajax 请求完成时注册要调用的处理程序。这是一个 Ajax 事件。与具体的ajax中complete一致 |
.ajaxError() | 当 Ajax 请求完成且出现错误时注册要调用的处理程序。这是一个 Ajax 事件。与具体的error一致 |
.ajaxSend() | 在 Ajax 请求发送之前显示一条消息。与具体的ajax请求中beforeSend一致 |
jQuery.ajaxSetup() | 设置将来的 Ajax 请求的默认值。进行全局设置,所有ajax的操作,都会遵循该设置 |
.ajaxStart() | 当首个 Ajax 请求完成开始时注册要调用的处理程序。这是一个 Ajax 事件。 |
.ajaxStop() | 当所有 Ajax 请求完成时注册要调用的处理程序。这是一个 Ajax 事件。 |
.ajaxSuccess() | 当 Ajax 请求成功完成时显示一条消息。 |
jQuery.get() | 使用 HTTP GET 请求从服务器加载数据。 |
jQuery.getJSON() | 使用 HTTP GET 请求从服务器加载 JSON 编码数据。 |
jQuery.getScript() | 使用 HTTP GET 请求从服务器加载 JavaScript 文件,然后执行该文件。 |
.load() | 从服务器加载数据,然后把返回到 HTML 放入匹配元素。 |
jQuery.param() | 创建数组或对象的序列化表示,适合在 URL 查询字符串或 Ajax 请求中使用。 |
jQuery.post() | 使用 HTTP POST 请求从服务器加载数据。 |
.serialize() | 将表单内容序列化为字符串。 |
.serializeArray() | 序列化表单元素,返回 JSON 数据结构数据。 |
option:ajax请求的相关参数
参数名 | 值类型 | 说明 |
---|---|---|
async | Boolean | 默认值: true。默认设置下,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为 false。 |
beforeSend | Function | 发送请求前可修改 XMLHttpRequest 对象的函数,如添加自定义 HTTP 头。 |
cache | Boolean | 默认值: true,dataType 为 script 和 jsonp 时默认为 false。设置为 false 将不缓存此页面。 |
complete | Function | 请求完成后回调函数 (请求成功或失败之后均调用)。 |
contentType | String | 默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。 |
context | Object | 这个对象用于设置 Ajax 相关回调函数的上下文。 |
data | String | 发送到服务器的数据。 |
dataFilter | Function | 给 Ajax 返回的原始数据的进行预处理的函数。提供 data 和 type 两个参数:data 是 Ajax 返回的原始数据,type 是调用 jQuery.ajax 时提供的 dataType 参数。函数返回的值将由 jQuery 进一步处理。 |
dataType | String | 预期服务器返回的数据类型. "xml": 返回 XML 文档 "html": 返回纯文本 HTML 信息 "script": 返回纯文本 JavaScript 代码。 "json": 返回 JSON 数据 。 "jsonp": JSONP 格式。 "text": 返回纯文本字符串 |
error | Function | 有以下三个参数:XMLHttpRequest 对象、错误信息、(可选)捕获的异常对象。当ajax发生错误时调用 |
global | Boolean | 是否触发全局 AJAX 事件。默认值: true。 |
success | Function | 请求成功后的回调函数。参数:由服务器返回,并根据 dataType 参数进行处理后的数据; |
timeout | Number | 设置请求超时时间(毫秒)。 |
type | String | 提交方式 GET POST DELETE PUT 等等 |
url | String | 默认值: 当前页地址。发送请求的地址。 |
API示例1:ajax基本请求参数
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jquery-ajax配置项API</title>
</head>
<body>
<button id="btn1">jquery最基本的ajax请求</button>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
//为按钮绑定事件
$("#btn1").click(function(){
//请求的配置项 请求的参数
var option = {
url:"ajax.do",//请求的URL地址
type:"get",//请求方法
data:{'name':'韩梅梅','age':18}, //请求参数
timeout:5000, //请求超时时间 单位毫秒 如果超出这个时间 则终止请求 触发error函数
error:function(req,msg,exception){//请求出现异常时调用的方法
console.log(req);
console.log(msg);
console.log(exception);
},
success:function(rs){//请求成功时调用的方法 响应码是 200
console.log("返回的数据是:"+rs);
},
complete:function(req,msg){//每次请求完成都会调用 不论成功还是失败
console.log("complete:"+req);
console.log("complete:"+msg);
}
};
//进行ajax请求
$.ajax(option);
});
</script>
</body>
</html>
AJax请求相关参数: 非常用参数
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jquery-ajax配置项API</title>
</head>
<body >
<button id="btn1">jquery最基本的ajax请求</button><br>
<button id="btn2">jquery最非常用属性介</button>
<img src="img/loading.gif" id="loading" style="width: 100px;height: 100px;display: none" />
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
//jquery ajax 非常用属性介绍
$("#btn2").click(function(){
var option = {
url:"ajax.do",
type:"get",
async:true,// 是否进行异步请求 默认是 true 如果需要同步请求 则为false
//如果ajax是异步请求,那么不管ajax相关代码是否执行完,ajax之后的代码都会执行
//如果ajax是同步请求,那么只有当ajax相关代码执行完,ajax之后的代码才会执行
//如果ajax相关数据 参与ajax之后的代码运算,建议使用同步请求
beforeSend:function(XHR){//进行ajax请求前调用的函数 此时 只属于当前ajax请求
//设置请求头
$("#loading").show();
},
context:document.body,// 指定ajax中的this 对象
dataType:"json",// ajax 期望的返回数据的格式类型 如果返回的数据 无法转化为期望格式类型,程序会报错 ,chrome看不到
dataFilter:function(data,type){//为ajax 返回的原始数据进行预处理的函数
//根据 type 的值 将data 原始数据进行预处理
//原始数据都默认普通字符串 将字符串转化为json对象
//data 内容 : 请求成功 普通字符串
console.log(data);
console.log(type);
var obj = new Object();
if(type == "json"){
obj.msg = data;
}
//此时打印的是js 对象
console.log(obj); //现在js 对象 根json 规范一样
//转化为json 对象
//将 js 对象转化为 json 对象
var jsonObj = $.parseJSON('{"msg":"请求成功"}');
//此时打印的json 对象
//console.log(jsonObj);
return JSON.stringify(jsonObj);
// 拼接成了 json 字符串 jquery 对这个字符串进行转化
//然后 转化后的结果 返回 success 方法 当做参数
},
success:function(rs){//请求成功时调用的方法 响应码是 200
//rs.msg ---- rs 是一个对象
console.log("返回的数据是:"+rs.msg);
//例如: success 里面做了多个dom的操作 根据数据生成dom
//而ajax 之后代码有相关关联的dom操作,则容易程序异常问题
$(this).attr("bgcolor","red");
},
complete:function(req,msg){//每次请求完成都会调用 不论成功还是失败
$("#loading").hide();
}
};
//进行ajax请求
$.ajax(option);
//进行dom 相关操作 获取 success 生成的dom
})
</script>
</body>
</html>
Ajax中的方法示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jquery ajax 中的方法介绍</title>
</head>
<body>
<form id="form1">
名称:<input name="name"/><br>
年龄:<input name="age" />
<input type="button" id="subBtn1" value="提交" />
</form>
<img src="img/loading.gif" id="loading" style="width: 100px;height: 100px;display: none" />
<button id="btn1" >获取表单数据</button>
<button id="btn2" >get发送ajax请求</button>
<button id="btn3" >post发送ajax请求</button>
<button id="btn4" >getJSON</button>
<button id="btn5" >load</button><br>
<h1>ajax2.html中</h1>
<div id="content"></div>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
//ajax 的全局设置
//只要进行了全局设置 所有的 ajax 请求都会触发相关设置的方法
/* $.ajaxSetup({
beforeSend:function(req){
// 在 前端后分离的项目中 此时可以在beforeSend中统一设置请求头
console.log("请求前");
},
dataFilter:function(data,type){
//统一进行数据拦截
//例如 : 如果数据不符合规范 则 进行某些业务处理
},
complete:function(req,rs){
console.log("请求完成");
}
}); */
//获取表单数据 便于 ajax 进行提交
$("#btn1").click(function(){
$(document).ajaxStart(function(){
console.log("ajax 开始请求");
});
$(document).ajaxStop(function(){
console.log("ajax 结束请求");
});
//获取表单中数据 序列化为表单格式的字符串
var data = $("#form1").serialize();
console.log(data);
data = $("#form1").serializeArray();
console.log(data);
$.ajax({
url:"ajax.do",
success:function(rs){
console.log(rs);
}
});
});
// ajax 中 get 和 post
//为了简化 ajax 开发 jquery 提供了 get 和 post 两个方法
//这两个方法
/*
url : 请求地址
param : 请求参数
function(rs){}: 请求成功后的回调函数
$.get(url,param,function(rs){});
$.post(url,param,function(rs){});
get 和 post 方法中的ajax 配置都使用的是默认配置
注意: 使用 get 和 post 获取的ajax 数据 是原始数据 数据类型由服务器决定 jquery 不会对数据做处理
*/
//使用 get 方法 发送ajax 请求
$("#btn2").click(function(){
$.get("ajax.do",{'name':'韩梅梅','age':18},function(rs){
console.log(rs);
});
});
//使用post 方法 发送ajax请求
$("#btn3").click(function(){
$.post("ajax.do",{'name':'李磊','age':18},function(rs){
console.log(rs);
});
});
//获取json 格式数据 getJSON 指定返回的数据类型是json类型
$("#btn4").click(function(){
$.getJSON("json.do",function(rs){
console.log(rs);
});
});
//.load() 从服务器加载数据,然后把返回到 HTML 放入匹配元素。
$("#btn5").click(function(){
$("#content").load("load.do");
});
</script>
</body>
</html>
注意:
-
在jQuery 1.9后,全局Ajax事件(ajaxStart, ajaxStop, ajaxSend, ajaxComplete, ajaxError, ajaxSuccess)只在document节点上触发.
只能:$(document).ajaxStart(...)
-
在javascript中:
- 将json字符串转化为json对象:JSON.parse(str) 或者 $.parseJSON(str) evel
- 将对象转化为JSON字符串 :JSON.stringify(obj)
1.4.案例
1.4.1.ajax登录案例
- 使用js获取表单数据
- 服务器获取ajax提交的数据根据数据做出相应的响应数据
- js获取响应数据,做出相应的反映
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<!-- 此时使用ajax form中 无需指定action method 等等 -->
<form >
<p>用户名:<input type="text" id="userName" name="userName" /> </p>
<p>密码:<input type="text" id="password" name="password" /></p>
<p><span id="errorInfo" style="color:red"></span></p>
<!-- 此时 提交表单数据 使用 js提交 所以 一定不要使用submit -->
<input type="button" value="提交" id="subBtn"/>
</form>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$("#subBtn").click(function(){
var userName = $("#userName").val();
if(userName == null || userName == ''){
$("#errorInfo").text("用户名不能为空");
//阻止后面的js 执行
return false;
}
var password = $("#password").val();
if(password == null || password == ''){
$("#errorInfo").text("密码不能为空");
//阻止后面的js 执行
return false;
}
var param = {
'service':'login',
'userName':userName,
'password':password
};
//提交数据给服务器
$.post("user.do",param,function(rs){
//对rs 响应数据进行解析
//如果rs 表示是成功 则 可以跳转到 登录成功的页面
//如果rs 表示是失败 则 将失败原因 显示在页面
// 服务器中返回的数据 code值为 200 时 才表示正常
// 如果不是200 表示都是异常的 msg 就是异常的原因
//协议 服务器返回的数据的协议
console.log(rs);
if(rs.code != 200){
$("#errorInfo").text(rs.msg);
return false;
}
//如果 code 值为 200 说明 用户名和密码是正确 进行页面跳转
//需要使用 js 实现 页面跳转
location.href = "success.html";
});
});
</script>
</body>
</html>
package com.sxt.controller;
import java.io.IOException;
import java.io.PrintWriter;
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 com.alibaba.fastjson.JSONObject;
@WebServlet("/user.do")
public class UserController extends HttpServlet {
private static final long serialVersionUID = 7723086583204133716L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String service = req.getParameter("service");
if("login".equals(service)) {
login(req,resp);
}
}
/**
* @Title: login
* @author: Mr.T
* @date: 2020年2月19日 下午5:42:20
* @Description: 处理登录业务的方法
* @param req
* @param resp
* @return: void
* @throws IOException
*/
private void login(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String userName = req.getParameter("userName");
String password = req.getParameter("password");
JSONObject rs = new JSONObject();
resp.setCharacterEncoding("UTF-8");
resp.setContentType("json/text;charset=UTF-8");
PrintWriter writer = resp.getWriter();
//校验用户名 告诉浏览器 用户名错误
if(!"admin".equals(userName)) {
//业务错误码
rs.put("code", 4001);
//业务错消息
rs.put("msg","用户名错误");
//将结果数据返回给浏览器
writer.write(rs.toJSONString());
writer.flush();
writer.close();
return;
}
// 校验密码
if (!"admin".equals(password)) {
// 业务错误码
rs.put("code", 4002);
// 业务错消息
rs.put("msg", "用户密码错误");
// 将结果数据返回给浏览器
writer.write(rs.toJSONString());
writer.flush();
writer.close();
return;
}
// 业务错误码
rs.put("code", 200);
// 业务错消息
rs.put("msg", "登录成功");
// 将结果数据返回给浏览器
writer.write(rs.toJSONString());
writer.flush();
writer.close();
return;
}
}