Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)
AJAX是多个技术联合实现的产物
只要是做web开发,B/S架构的,不管服务器端使用什么编程语言,前端AJAX都是要学习的
A线程和B线程,并发执行,谁也不等谁,这就是异步
A线程和B线程,在A线程执行的时候,B线程需要等待,或者在B线程执行的时候,A线程需要等待,这就是同步
传统的请求:都是同步的
AJAX请求:可以做到同步
Google auto_complete(输入框自动补全)
Google Map(谷歌地图)
浏览器本身这个软件是支持多线程并发的,其中ajax请求就是一个线程;
一个页面上可以同时发送多个ajax请求,多个ajax请求对象浏览器多个线程;
当整个浏览器采用的是传统的请求的时候,请求只要一发送,整个浏览器窗口会锁定,无法点击按钮,并且浏览器会将整个窗口当中的数据完全清除,迎接新的页面
解决页面的局部刷新问题
使用AJAX可以在同一个网页中并发的发送多个请求,请求与请求之间互不等待,互不干扰,这样可以提高用户的体验
readyState
XMLHttpRequest对象在请求和响应的过程中,该对象的readyState属性值从 0 到 4 发生变化
0: 请求未初始化 1: 服务器连接已建立 2: 请求已接收 3: 请求处理中 4: 请求已完成,且响应已就绪
status
status属性,HTTP响应状态码
200: “OK” 404: 未找到页面
responseText
responseText属性:响应回来的text
open(method,url,async)
method:请求的类型;GET 或 POSTurl:文件在服务器上的位置async:true(异步)或 false(同步)async为true时,表示支持异步,同时可以发送多个ajax请求,多个ajax可以同时发送,请求并发 async为false时,表示支持同步,同时仅可发送一个ajax请求,ajax请求执行完后才能发送新的ajax的请求
大部分情况下,都是async为true,支持异步,
但是在一个表单中,有多个项目需要发送ajax请求进行验证的时候,必须等待所有表单项验证完毕后,才允许用户点击注册,此时注册按钮的ajax必须使用同步ajax
POST请求要在第三步xhr.open()后增加以下代码模拟表单POST提交,因为只有表单才能POST提交
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");POST请求,请求体要在第四步xhr.send()中添加参数,如
xhr.send("test=ajax&method=post"); //1. 创建ajax核心对象XMLHttpRequest var xhr; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } //2. 注册回调函数 xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { alert("AJAX OK"); } } //3. 开启通道 xhr.open("POST","/ajax/userLogin.post",true); //只有表单才能提交POST请求,所以模拟表单,需要加上以下代码 xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8"); //4. 发送请求 //POST请求提交数据在send()方法中提交 xhr.send("test=ajax&method=post");用户注册界面,当用户鼠标失去用户名输入框焦点时,发送ajax请求判断用户名是否被注册 已注册显示红色字体 未注册显示绿色字体
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>使用ajax发送get请求验证用户名是否存在</title> </head> <body> <script type="text/javascript"> function checkUsername(username) { // 1. 创建ajax核心对象XMLHttpRequest(浏览器内置对象,可以直接使用) var xhr; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } // 2. 注册回调函数 xhr.onreadystatechange = function () { if (xhr.readyState == 4) { //服务器端响应结束 if (xhr.status == 200) { var nameTipMsg = document.getElementById("nameTipMsg"); //在浏览器端使用xhr对象接收服务器端响应回来的文本 var text = xhr.responseText; nameTipMsg.innerHTML = text; } else { //弹出错误代码 alert(xhr.status); } } } // 3. 开启浏览器和服务器之间的通道 xhr.open("GET","/ajax/checkusername.do?username="+username,true); // 4. 发送请求 xhr.send(); } </script> 用户名<input type="text" name="username" onblur="checkUsername(this.value)"> <span id="nameTipMsg"></span><br> 密码<input type="password" name="password"> </body> </html>模拟用户登陆 AJAX POST请求,后台返回json字符串, 当{"success":true}时登陆成功,显示绿色登陆成功提示文字; 当{"success":false}时登陆成功,显示红色登陆失败提示文字
<html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>使用ajax发送POST请求验证用户登陆是否成功</title> </head> <body> <script type="text/javascript"> function userLogin() { var username = document.getElementById("username"); var password = document.getElementById("password"); //1. 创建ajax核心对象XMLHttpRequest var xhr ; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } //2. 注册回调函数 xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { var jsonString = xhr.responseText;//这里的jsonString只是一个普通的字符串 eval("var jsonObj = " + jsonString);//将字符串作为js代码执行 let tipMsg = document.getElementById("tipMsg"); if (jsonObj.success) { tipMsg.innerHTML = "<font color='green'>登陆成功!</font>"; } else { tipMsg.innerHTML = "<font color='red'>登陆失败!</font>"; } } } //3. 开启通道 xhr.open("POST","/ajax/userLogin.post",true); //只有表单才能提交POST请求,所以模拟表单,需要加上以下代码 xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8"); //4. 发送请求,POST请求提交数据在send()方法中提交 xhr.send("username="+username.value+"&password="+password.value); } </script> 用户名<input type="text" id="username"><span id="tipMsg"></span><br> 密码<input type="password" id="password"><br> <input type="button" value="登陆" onclick="userLogin()"> </body> </html>问题:get请求,第一次会请求服务器,之后再访问的时候就直接走浏览器缓存,而不再请求服务器了
解决:可以在get请求的URL加上时间戳,这样每次请求的URL都不一样,这样每次都会请求服务器了
var timeStamp = new Date().getTime();//获取毫秒数 xhr.open("GET","/ajax/checkusername.get?_="+timeStamp+"&username="+username,true);完整代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>使用ajax发送get请求验证用户名是否存在</title> </head> <body> <script type="text/javascript"> function checkUsername(username) { var xhr; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (xhr.status == 200) { var nameTipMsg = document.getElementById("nameTipMsg"); var text = xhr.responseText; nameTipMsg.innerHTML = text; } else { alert(xhr.status); } } } // 3. 开启浏览器和服务器之间的通道 // 解决get换出问题,在URL中加上时间戳 var timeStamp = new Date().getTime();//获取毫秒数 xhr.open("GET","/ajax/checkusername.get?_="+timeStamp+"&username="+username,true); // 4. 发送请求 xhr.send(); } </script> 用户名<input type="text" name="username" onblur="checkUsername(this.value)"> <span id="nameTipMsg"></span><br> 密码<input type="password" name="password"> </body> </html>打开网页时初始化,浏览器发送请求获取省份列表;
当用户选择省份时,发送请求获取此省份的市列表
使用 自定义src/Utils.JDBCUtils工具类使用 Druid数据库连接池自定义src/Utils.JDBCUtils工具类
自定义src/prop/druid.properties配置文件用来配置druid数据库连接池
自定义数据库SQL/ajax.sql文件
官方的JDBC驱动jar包/WEB-INF/lib/mysql-connector-java-5.1.7-bin.jar
官方的druid数据库连接池jar包/WEB-INF/lib/druid-1.1.23.jar
数据库名为 ajax
/* Navicat Premium Data Transfer Source Server : local Source Server Type : MySQL Source Server Version : 50562 Source Host : localhost:3306 Source Schema : ajax Target Server Type : MySQL Target Server Version : 50562 File Encoding : 65001 Date: 16/10/2020 23:15:10 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for t_city -- ---------------------------- DROP TABLE IF EXISTS `t_city`; CREATE TABLE `t_city` ( `code` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `pcode` char(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`code`) USING BTREE, INDEX `pcode`(`pcode`) USING BTREE, CONSTRAINT `t_city_ibfk_1` FOREIGN KEY (`pcode`) REFERENCES `t_province` (`code`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of t_city -- ---------------------------- INSERT INTO `t_city` VALUES (1, '保定市', '003'); INSERT INTO `t_city` VALUES (2, '石家庄市', '003'); INSERT INTO `t_city` VALUES (3, '廊坊市', '003'); INSERT INTO `t_city` VALUES (4, '张家口市', '003'); INSERT INTO `t_city` VALUES (5, '济南市', '001'); INSERT INTO `t_city` VALUES (6, '淄博市', '001'); INSERT INTO `t_city` VALUES (7, '青岛市', '001'); INSERT INTO `t_city` VALUES (8, '烟台市', '001'); INSERT INTO `t_city` VALUES (9, '太原市', '002'); INSERT INTO `t_city` VALUES (10, '运城市', '002'); INSERT INTO `t_city` VALUES (11, '大同市', '002'); INSERT INTO `t_city` VALUES (12, '临汾市', '002'); INSERT INTO `t_city` VALUES (13, '郑州市', '004'); INSERT INTO `t_city` VALUES (14, '开封市', '004'); INSERT INTO `t_city` VALUES (15, '洛阳市', '004'); INSERT INTO `t_city` VALUES (16, '平顶山市', '004'); -- ---------------------------- -- Table structure for t_province -- ---------------------------- DROP TABLE IF EXISTS `t_province`; CREATE TABLE `t_province` ( `code` char(3) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`code`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of t_province -- ---------------------------- INSERT INTO `t_province` VALUES ('001', '山东省'); INSERT INTO `t_province` VALUES ('002', '山西省'); INSERT INTO `t_province` VALUES ('003', '河北省'); INSERT INTO `t_province` VALUES ('004', '河南省'); SET FOREIGN_KEY_CHECKS = 1;