AJAX
简介
Ajax:Asynchronous Javascript And XML(异步JavaScript和XML)它不是新的编程语言,而是一种将现有标准组合在一起使用的新方式。它的最大优势就是无刷新获取数据
。但它的缺点也比较明显:
1、没有浏览历史,不能回退。2、存在跨域问题(同源):在a.com访问b.com是不允许的,但是有解决的方法。3、SEO(Search Engine Optimization)不友好:网页中的内容爬虫是爬不到的
作用
1、与服务器进行数据交换
:通过Ajax可以给服务器发送请求,并获取服务器响应的数据,使用Ajax和服务器进行通信,就可以使用HTML + Ajax来替换JSP页面。
2、异步交互
:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。如:搜索联想…
同步和异步
XML简介
XML可扩展标记语言 (Extensible Markup Language, XML)。<Html 超文本标记语言>
XML设计用来传输和存储数据,它和HTML相似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据。
语法:
如有一个学生数据:name:“khan”;age=18;gender=“man”,XML的表示方法如下:
<!-- 用XML方式表示 -->
<student>
<name>khan</name>
<age>18</age>
<gender>man</gender>
</student>
现在使用更多的是JSON的方法去表示。
{"name":"khan","age":"18","gender":"man"}
优势
- 无刷新获取数据,Ajax 的核心是 JavaScript 对象 XMLHttpRequest,XMLHttpRequest使您可以使用 JavaScript 向服务器提出请求并处理响应,而不阻塞用户。
- 允许你根据用户事件来更新部分页面内容
缺点
1、没有浏览历史,不能回退
2、存在跨域问题(同源):在a.com访问b.com是不允许的,但是有解决的方法
3、SEO(Search Engine Optimization)不友好:网页中的内容爬虫是爬不到的
工作原理
在使用AJAX执行操作时,我们需要先安装node.js,以及通过命令行方式安装node.js的web框架express
Node.js安装
下载地址:https://nodejs.org/en
安装教程:https://blog.csdn.net/m0_59900155/article/details/128243983
Express服务端框架
简介
Express是一个基于Node平台的web应用开发框架。它提供了一系列的强大特性,帮助我们创建各种Web应用。
安装步骤
-
新建一个文件夹用来包含学习的内容
-
通过VSCode打开文件夹的方式打开该文件夹
-
在打开窗口的最外层使用右键方式打开终端窗口
-
在打开的窗口中输入npm init --yes
-
安装express框架npm i express
-
使用
//1、引入express const express = require('express'); //2、创建应用对象 const app = express(); //3、创建路由规则 //req 是对请求报文的封装 //resp 是对响应报文的封装 app.get('/', (req, resp)=>{ //设置响应 resp.send("HELLO EXPRESS"); }); //4、监听端口,启动服务 app.listen(8000, ()=>{ console.log("服务已经启动,8000端口监听中..."); })
-
运行和查看结果
- 选中usingExpress右键在终端窗口中打开
- 使用node usingExpress.js
- 打开浏览器,在地址栏中输入localhost:8000可以看结果
Ajax操作
Ajax请求发送前的准备
get.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajax GET 请求</title>
<style>
#result{
width:200px;
height:100px;
border:solid 1px #90b;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
</body>
</html>
server.js
//1、引入express
const express = require('express');
//2、创建应用对象
const app = express();
//3、创建路由规则
//req 是对请求报文的封装
//resp 是对响应报文的封装
app.get('/server', (req, resp)=>{
//设置响应头 设置允许跨域
resp.setHeader("Access-Control-Allow-Origin", '*')
//设置响应体
resp.send("Hello AJAX")
});
//4、监听端口,启动服务
app.listen(8000, ()=>{
console.log("服务已经启动,8000端口监听中...");
})
/* 运行:
选中usingExpress右键在终端窗口中打开
使用node server.js
打开浏览器,在地址栏中输入localhost:8000可以看结果
需要注意的是:如果你先前已经打开了8000端口,i你需要线关闭在使用上面的命令打开
*/
Ajax请求基本操作
get.html
<!-- 前端页面的准备 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajax GET 请求</title>
<style>
#result{
width:200px;
height:100px;
border:solid 1px #90b;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
//获取button元素
const btn = document.getElementsByTagName("button")[0];
//绑定事件
btn.onclick = function(){
// console.log("test");
//1、创建对象
let xhr = new XMLHttpRequest();
const result = document.getElementById("result");
//2、初始化 设置请求方法和url
xhr.open("GET", 'http://127.0.0.1:8000/server');
//3、发送
xhr.send();
//4、事件绑定 处理服务端返回的结果
//readystate 是xhr对象中的属性, 表示状态 0未初始化 1 2 3 4
/*
0:表示未初始化
1:表示open方法已经调用完毕
2:表示send党法已经调用完毕
3:表示服务端返回了部分结果
4:表示服务端返回了所有的结果 */
xhr.onreadystatechange = function(){
//判断当服务端返回了所有结果的时候执行相关操作
if(xhr.readyState === 4){
//判断响应的状态码200 404 403 500
if(xhr.status >= 200 && xhr.status < 300){
//处理结果 行 头 空行 体
//将行 头 体之中的内容进行一个获取并打印
//1、相应行
console.log(xhr.status);//响应状态码
console.log(xhr.statusText);//响应状态字符串
console.log(xhr.getAllResponseHeaders);//所有的响应头
console.log(xhr.response);//响应体
result.innerHTML = xhr.response;
}
}
}
}
</script>
</body>
</html>
server.js
//服务端的准备
//1、引入express
const express = require('express');
//2、创建应用对象
const app = express();
//3、创建路由规则
//req 是对请求报文的封装
//resp 是对响应报文的封装
app.get('/server', (req, resp)=>{
//设置响应头 设置允许跨域
resp.setHeader("Access-Control-Allow-Origin", '*')
//设置响应体
resp.send("Hello AJAX")
});
//4、监听端口,启动服务
app.listen(8000, ()=>{
console.log("服务已经启动 8000端口监听中...");
})
/* 运行:
选中usingExpress右键在终端窗口中打开
使用node server.js
打开浏览器,在地址栏中输入localhost:8000可以看结果
需要注意的是:如果你先前已经打开了8000端口,i你需要线关闭在使用上面的命令打开
*/
结果
在Ajax请求中设置url参数
在浏览器中我我们使用?加参数的方法,在Ajax中也是一样的,多个参数使用&分隔
//2、初始化 设置请求方法和url
xhr.open("GET", 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
Ajax发送post请求
post.html
<!-- Ajax发送POST请求 -->
<!-- 需求是:当鼠标放置在div上的时候,向服务端发请求,将响应体结果在div中座椅个呈现 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajax POST 请求</title>
</head>
<style>
#result{
width: 200px;
height: 100px;
border: solid 1px #903;
}
</style>
<body>
<div id="result"></div>
</body>
<script>
let result = document.querySelector("#result");
//绑定事件
result.addEventListener("mouseover", function(){
console.log("abc");
//1、创建对象
let xhr = new XMLHttpRequest();
//2、初始化 设置类型与URL
xhr.open("POST", "http://localhost:8000/server");
//3、发送
xhr.send();
//4、事件绑定
xhr.onreadystatechange = function(){
//判断
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
result.innerHTML = xhr.response;
}
}
}
})
</script>
</html>
server.js
//服务端的准备
//1、引入express
const express = require('express');
//2、创建应用对象
const app = express();
//3、创建路由规则
//req 是对请求报文的封装
//resp 是对响应报文的封装
app.get('/server', (req, resp)=>{
//设置响应头 设置允许跨域
resp.setHeader("Access-Control-Allow-Origin", '*')
//设置响应体
resp.send("Hello AJAX")
});
app.post('/server', (req, resp)=>{
resp.setHeader('Access-Control-Allow-Origin', '*');
resp.send("Khan.Louis");
})
//4、监听端口,启动服务
app.listen(8000, ()=>{
console.log("服务已经启动 8000端口监听中...");
})
/* 运行:
选中usingExpress右键在终端窗口中打开
使用node server.js
打开浏览器,在地址栏中输入localhost:8000可以看结果
需要注意的是:如果你先前已经打开了8000端口,i你需要线关闭在使用上面的命令打开
*/
结果
post还可以携带参数,设置方法为:
//3、发送
xhr.send('a=100&b=200&c=300');
xhr.send('a:100&b:200&c:300');
Ajax设置请求头信息
- 1、预定义请求头
......
//2、初始化 设置类型与URL
xhr.open("POST", "http://localhost:8000/server");
//设置请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlendcoded');
/* Content-Type:设置请求体内容的类型
application/x-www-form-urlendcoded:设置参数查询字符串的类型
*/
......
- 2、自定义请求头
......
xhr.setRequestHeader("name","khan");
......
但需要注意的是:自定义的请求头如果不再server中设置一些内容会报错,需要在server.js中添加:
app.all('/server', (req, resp)=>{
resp.setHeader('Access-Control-Allow-Origin', '*');
resp.send("Khan.Louis");
resp.setHeader("Access-Control-Allow-Header",'*')
})
服务端响应JSON数据
server.js
//服务端的准备
//1、引入express
const express = require('express');
//2、创建应用对象
const app = express();
//3、创建路由规则
//req 是对请求报文的封装
//resp 是对响应报文的封装
app.get('/server', (req, resp)=>{
//设置响应头 设置允许跨域
resp.setHeader("Access-Control-Allow-Origin", '*')
//设置响应体
resp.send("Hello AJAX JSON")
});
app.all('/json-server', (req, resp)=>{
resp.setHeader('Access-Control-Allow-Origin', '*');
resp.setHeader("Access-Control-Allow-Header", '*');
// resp.send("Khan.Louis Ajax");
//响应一个数据
const data = {
name:'louis'
};
/* 但是send只能接收一个字符串或buffer,所以需要将这个转换 */
let str = JSON.stringify(data);
resp.send(str);
})
//4、监听端口,启动服务
app.listen(8000, ()=>{
console.log("服务已经启动 8000端口监听中...");
})
testJson.html
<!-- 服务端响应JSON数据 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JSON响应</title>
</head>
<style>
#result{
width:200px;
height:100px;
border:solid 1px #90b;
}
</style>
<body>
<div id="result"></div>
</body>
<script>
const result = document.getElementById("result");
//绑定键盘按下事件
window.onkeydown = function(){
// console.log("test");
//发送请求
const xhr = new XMLHttpRequest();
//设置响应体的数据类型,需要注意的是,在使用显示时候不能使用。
xhr.responseType = "json";
//初始化
xhr.open("GET","http://127.0.0.1:8000/json-server");
//发送
xhr.send();
//事件绑定
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
// console.log(xhr.response);
// result.innerHTML = xhr.response;
//如果结果复杂,那么获取数据就比较复杂,我们可以使用方法有
//手动对数据做一个转换
// let data = JSON.parse(xhr.response);
console.log(xhr.response);
result.innerHTML = xhr.response.name;
//自动转换,设置响应体的数据类型(上)
}
}
}
}
</script>
</html>
自动重启工具(nodemon)
https://www.npmjs.com/package/nodemon
停掉服务后,在terminal中输入npm install -g nodemon
安装自动重启工具。
启动服务:使用命令nodemon server.js
注意:nodemon后面的是自己的js文件名。
解决IE缓存问题
IE缓存问题
:IE浏览器会对Ajax发送的请求做一个缓存,当下一发送请求时,走的是本地的缓存而不是服务器的最新数据,因此会影响结果。
server.js
//针对IE缓存
app.get("/ie", (rquest, response)=>{
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Header", "*");
response.send("Hello Ie");
})
Ajax请求超时与网络异常
server.js
app.get("/timeout", (request, response)=>{
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Header", "*");
setTimeout(()=>{
response.send("result timeout");
}, 3000)
})
timeout.html
<!-- Ajax超时与网络异常处理 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Timeout</title>
</head>
<style>
#result{
width:200px;
height:100px;
border:solid 1px #90b;
}
</style>
<body>
<button>点击发送请求</button>
<div id="result"></div>
</body>
<script>
let but = document.getElementsByTagName("button")[0];
but.addEventListener("click", function(){
let result = document.querySelector("#result");
let xhr = new XMLHttpRequest();
// 超时设置
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = function(){
alert("网络异常,请稍后重试。")
}
//网络异常回调
xhr.onerror = function(){
alert("网络似乎出了一些问题")
}
xhr.open("GET", "http://127.0.0.1:8000/timeout?time=" + Date.now());
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
result.innerHTML = xhr.response;
}
}
}
})
</script>
</html>
Ajax取消请求
在请求过程中,如果还没有收到结果,我们可以通过代码手动取消。
<!-- Ajax取消请求 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>取消请求</title>
</head>
<body>
<button>点击发送</button>
<button>点击取消</button>
</body>
<script>
//获取对想想元素
const buts = document.querySelectorAll("button");
let x = null;
buts[0].onclick = function(){
x = new XMLHttpRequest();
x.open("GET", "http://localhost:8000/timeout?time="+Date.now());
x.send();
}
//取消使用到abort方法它是属于X方法
buts[1].onclick = function(){
x.abort();
}
</script>
</html>
Ajax请求重复发送问题
<!-- 请求重复发送问题 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>请求重复解决</title>
</head>
<body>
<button>点击发送</button>
</body>
<script>
//获取对想想元素
const buts = document.querySelectorAll("button");
let x = null;
//标识变量
let isSending = false;
buts[0].onclick = function(){
//判断标识变量
if(isSending === true){
x.abort();
} //如果正在发送,则取消该请求,创建一个新的请求
x = new XMLHttpRequest();
//修改变量的值
isSending = true;
x.open("GET", "http://127.0.0.1:8000/timeout");
x.send();
x.onreadystatechange = function(){
if(x.readyState === 4){
isSending = false;
}
}
}
</script>
</html>
需要注意的是,在服务上设置一个超时处理。
Tomcat&Ajax
Ajax使用步骤
- 🚀 编写AjaxServlet,并使用response输出字符串
package com.ajax;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/AjaxServlet")
public class AjaxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、test响应数据
response.getWriter().write("Hello Ajax");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
- 🚀 创建XMLHttpRequest对象:用于服务器交换数据
<!-- 1、创建核心对象-->
let xhr = new XMLHttpRequest();
- 🚀 向服务器发送请求
// 2、发送请求
xhr.open("GET", "https://localhost:8080/AjaxServlet");
xhr.send();
- 🚀 获得服务器响应数据
// 3 获取响应
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
document.getElementById("demo").innerHTML =
this.responseText;
}
}
示例
package com.ajax;
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 java.io.IOException;
/**
* @author XRY
* @date 2023年05月13日9:48
*/
@WebServlet("/SelectUserServlet")
public class SelectUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1 接收用户名
String username = req.getParameter("username");
//2 调用service查询user对象
boolean flag = true;
//3 响应对应的标记
resp.getWriter().write("" + flag);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<script>
//1 给用户输入框绑定失去焦点的时间
document.getElementById("username").onblur = function (){
//发送Ajax请求
//获取用户名的值
var username = this.value;
<!-- 1、创建核心对象-->
let xhr = new XMLHttpRequest();
// 2、发送请求
xhr.open("GET", "http://localhost:8080/SelectUserServlet?username=" + username);
xhr.send();
// 3 获取响应
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
// document.getElementById("demo").innerHTML =
// this.responseText;
//判断
if(this.responseText == "true"){
//用户名存在
document.getElementById("username_err").style.display = "";
}else{
//用户名不存在
document.getElementById("username_err").style.display = "none";
}
}
}
}
}
</script>
Axios
Axios对原生的Ajax进行封装,简化书写
官网:https://www.axios-http.cn/
使用步骤
1、📕 引入axios的js文件
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.js"></script>
2、📕 使用axios发送请求,并获得响应结果。
<script>
axios({
method:"get",
url:"http://localhost:8080/SelectUserServlet?username=zhangsan"
}).then(function(resp){
alert(resp.data)
})
axios({
method:"post",
url:"http://localhost:8080/SelectUserServlet",
data:"usernaem=zhangsan"
}).then(function(resp){
alert(resp.data)
})
</script>
Axios请求方式别名
为了方便起见,Axios已经为所有支持的请求方法提供了别名
axios.get(url[,config]) #发起GET方式请求
axios.delete(url[,config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[,data[,config]]) #发起post方式请求
axios.put(url[,data[,confid]])
axios.patch(url[,data[,config]])