AJAX(Asynchronous Javascript And Xml)
传统请求及缺点
-
传统的请求(站在用户的角度)
-
直接在地址栏输入url
-
点击超链接
-
提交form表单
-
使用js代码发送请求
window.open(url) windonw.location.href = url document.location.href = url
-
-
传统请求存在的问题及缺陷
-
页面全部刷新导致了用户体验差。(会把原来的页面全部清空,返回新的页面)
-
传统的请求导致用户的体验有空白期(用户体验不连贯)
-
传统请求的执行流程
-
AJAX概述
![对AJAX异步请求的理解]对AJAX异步请求的理解.png)
- AJAX能称为一种技术,它是多种技术综合产物,需要使用JavaScript、xml、JSON等。
-
AJAX可以让浏览器发送一种特殊的请求,这种请求是异步。
- 什么是异步,什么是同步?
- 假设有t1和t2两个线程,t1和t2线程并发执行,就是异步。
- 假设有t1和t2两个线程,t2必须等待t1完成某个操作才能执行,就是同步。
- AJAX可以发送异步请求,即在同一个浏览器页面中,可以发送多个ajax请求,这些ajax请求之间不需要等待,并发执行。
-
AJAX代码属于WEB前端的JS代码,和后端java没有关系,后端可以是php、也可以是C语言。
-
AJAX可以更新网页的部分,而不需要重新加载整个页面。(页面局部刷新)
-
AJAX可以做到在同一个网页中同时启动多个请求,类似于在同一个网页中启动多线程,一个线程一个请求。
XMLHttpRequest对象
-
XMLHttpRequest对象是AJAX的核心对象,发送请求以及接受服务器数据的返回,都靠该对象实现。
-
现代浏览器都支持XMLHttpRequest对象,可以直接使用。
-
创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
-
XMLHttpRequest对象的方法
方法 描述 abort() 取消当前请求 getAllResponseHeaders() 返回头部信息 getResponseHeader() 返回特定的头部信息 open(method, url, async, user, psw) 规定请求method:请求类型 GET 或 POSTurl:文件位置async:true(异步)或 false(同步)user:可选的用户名称psw:可选的密码 send() 将请求发送到服务器,用于 GET 请求 send(string) 将请求发送到服务器,用于 POST 请求 setRequestHeader() 向要发送的报头添加标签/值对 -
XMLHttpRequest对象的属性
属性 描述 onreadystatechange 定义当 readyState 属性发生变化时被调用的函数 readyState 保存 XMLHttpRequest 的状态。0:请求未初始化 1:服务器连接已建立 2:请求已收到 3:正在处理请求 4:请求已完成且响应已就绪 responseText 以字符串返回响应数据 responseXML 以 XML 数据返回响应数据 status 返回请求的状态号200: “OK”403: “Forbidden”404: “Not Found” statusText 返回状态文本(比如 “OK” 或 “Not Found”)
注意:区分readystate和status状态码
- status是http的状态码,w3c协议规定了相应的状态码
- readyState是变化的;是xhr对象的状态
AJAX GET请求
前后端代码AJAX get代码
-
前端代码,发送AJAX GET请求
<body> <button id="btn">发送ajax请求</button> <!--任一容器都可以,接受回来的东西想要设置到哪里都可以--> <span class="myspan"></span> <script> window.onload = function (){ document.querySelector("#btn").addEventListener('click',function (){ // 创建xhr对象 const xhr = new XMLHttpRequest() // 注册回调函数 xhr.addEventListener("readystatechange", function (){ if (this.readyState===4){ if (this.status===200){ // 通过xhr对象的responseText属性可以获得服务器响应的内容 // response以字符串的形式获取数据。不管服务器响应的是什么,都以普通文本的形式获取。(服务器可能响应回来:普通文本/xml/JSON) document.querySelector('.myspan').innerHTML = this.responseText }else{ alert(this.status) } } }) // 建立通道 xhr.open("get","/ajax/ajaxrequst2",true) // 发送请求 xhr.send() }) } </script> </body>
-
后端代码,响应AJAX GET请求
@WebServlet("/ajaxrequst2") // 此处必须加/,而且前面不用添加项目名称,写前端发送请求的最后一级目录即可 public class AjaxRequest2Servlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置响应的内容、字符集 response.setContentType("text/html;charset=UTF-8"); // 获取响应流 PrintWriter out = response.getWriter(); // 响应 out.print("<font color=red>用户名已经存在!!!</font>"); } }
AJAX get请求如何提交数据给服务器
-
get请求提交数据在“请求行”上提交,格式
url?name=value&name=value&...&name=value
(读法:问号name等于value与)前端将上面格式写在get的url参数处
-
其实这个get请求提交的数据格式是HTTP协议中规定的,遵循协议即可。
AJAX GET 请求缓存问题
- 对于低版本的IE浏览器,AJAX的get请求可能会走缓存,存在缓存问题。
- 对于现代的浏览器来说,大部分浏览器都已经不存在AJAX get缓存问题了。
- 什么是AJAX GET请求缓存问题?
- 在HTTP协议中是这样规定get请求:get请求会被缓存起来。
- 发送AJAX GET请求时,在同一个浏览器上,前后发送的AJAX请求路径一样的话;对于低版本的IE来说,第二次的AJAX GET请求会走缓存,不走服务服务器。
-
POST请求在HTTP协议中规定:不会被浏览器缓存。
- GET缓存优缺点
- 有点:直接从浏览器缓存中获取资源,不需要从服务器上重新加载资源,速度较快,用户体验较好。
- 缺点:无法实时获取最新的服务器资源
- 浏览器什么时候会走缓存?
- 第一:GET请求
- 第二:请求路径已经被浏览器缓存过了。第二次发送请求的时候,请求的路径没有发生变化。
-
解决方法
-
时间戳:
在请求路径url后面添加一个时间戳参数;时间戳随时间变化,每次发送的请求路径都是不一样的,就不会发生走浏览器缓存的问题。
url?t= new Date().gettime()
-
随机数:随机数也变化。
-
理论基础:如果服务器找不到资源,就会去最近的资源目录返回对应的资源。
-
AJAX POST请求资源
AJAX post请求前后端代码
-
AJAX的post请求和get请求有什么区别?
前端代码有区别,后端代码没什么区别。
// 发送post请求,向服务器提交数据 xhr.open("post",url,true) // 怎么模拟AJAX提交form表单呢?设置请求头的内容类型(这行代码非常关键,是模拟form表单的关键代码) xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded") // 获取表单数据 const username = document.querySelector("#username").value const pwd = document.querySelector("#pwd").value // 发送数据 xhr.send("username="+username+"&password="+pwd)
-
注意:
-
设置请求头的内容setRequestHeader方法必须在open方法之后
setRequestHeader第二个参数不用背,写form标签的enctype参数会有提示,复制粘贴即可。
-
xhr.send(“注意格式:放在这里的数据就是在请求体中提交的,需要遵守HTTP协议:
name=value&...&name=value
”) -
浏览器发送的表单格式的数据:
-
经典案例
案例1:验证用户名是否可用
- 需求:用户填写表单,提示用户名是否可用。
-
实现:
- 前端,用户输入用户名后,失去焦点事件发生,发送AJAX post请求,提交用户性
- 后端,接受用户名,连接数据库,根据用户名搜索
-
后盾检查用户名是否存在
- 如果存在,后端响应信息:对不起,用户名已经存在
-
- 如果不存在,后端响应信息:用户名可以使用
案例2:动态展示学员列表
问题:后端要拼接内容成Html内容返回给前端,太复杂。有没有其他办法?
基于JSON的数据交换
JSON基础知识
- JSON定义
- JSON(JavaScript Object Notation,JavaScript 对象表示法) 是一种轻量级的数据交换格式。
- 基于 JavaScript 语言法,但它独立于 JavaScript,大多数编程语言都支持 JSON。
- JSON常用场景
- 前后端传输数据
- 使用Ajax异步加载的数据
- 前后端分离,后端返回的数据
- 开发API
- 不同函数之间传递数据
- 不同语言之间传递数据。
- 前后端传输数据
- 举例
{"key1":"字符型","key2":数字型}
// JSON对象
{
"key1":"字符型",
"key2":数字型,
"key3":{"name":"value","age":12}
}
// JSON数组及数组对象
{
"key":[1,2,4],
"key1":["a","n"],
"key3":[{"name":"pp", "age":22},{"name":"gg","age":33}]
}
web前端
-
在web前端中,如何将json格式的字符串转换成json对象
// json字符串转换成json对象 const obj ="{\"username\":\"zhangsan\",\"password\":\"123\"}" const jsonStr = JSON.parse(obj)
注意:数字类型可以没有双引号。
web后端
从数据库中取得数据拼接成JSON字符串的方法
手动拼接append
rs数据库查询的结果集。
json.append("[");
while (rs.next()){
// 获取每个学生的信息
String name = rs.getString("name");
String age = rs.getString("age");
String addr = rs.getString("addr");
// 手动拼接JSON字符串,示例数据 [{"name":"张三","age":22,"addr":"番禺区" },{"name":"张三","age":22,"addr":"番禺区" }]
// 一共7段落 {"name":" 张三 ","age": 22 ,"addr":" 番禺区 "},
json.append("{\"name\":\" ");
json.append(name);
json.append("\",\"age\":");
json.append(age);
json.append(",\"addr\":\"");
json.append(addr);
json.append("\"},"); // 注意最后一行的数据需要删掉逗号
}
json.append("]");
// 不想要逗号 但是没办法直接删除逗号;于是直接把逗号及之后字母都删除了,再把误删的需要的补充回来
jsonStr = json.substring(0, json.length() - 2) + "]";
阿里巴巴的fastjson组件
拼接JSON格式的字符串太复杂,可以使用阿里巴巴的fastjson组件,将java对象转换成json格式的字符串。
使用该方法前引入该包:
- 在java项目下新建lib文件夹,复制粘贴jar包到lib文件夹下
- 在project structure 中添加依赖
为什么mysql的ja包不添加依赖?
在写代码的时候需要用到jar包里的类才需要添加依赖,mysql的jar包在编程的时候用不到其中的类,所以不需要添加到依赖中。
代码:
基于XML的数据交换
注意点
-
如果服务器端响应XML,响应的类型需要写:
response.setContentType("text/xml;charset=utf-8");
如果里面还html会返回给前端null。
-
前端使用XMLHttpRequest对象的responseXML属性接收返回的数据,而且会自动封装为document对象。
前端不再使用xhr的responseText属性接受返回数据。
-
XML和JSON都是常用的数据交换格式
-
XML体积大,解析麻烦少用。
-
JSON体积小,解析简单,较常用。
-
前端代码
注意点:
-
后端返回xml对象,前端接受到的是一个document文档对象格式的数据。
前端使用xhr.responseXML获得该数据
-
对该数据进行处理渲染到html页面的方法:
- 对该返回对象使用queryselectorAll方法
- 结合数组和join,拼接字符串
// 2.注册回调函数
xhr.addEventListener("readystatechange", function (){
if (xhr.readyState === 4){
if (xhr.status === 200){
// 使用XMLHttpRequest对象的responseXML属性接收返回的数据,可以自动封装为document对象。
// console.log(xhr.responseXML)
// 前端手动拼接
const uname = xhr.responseXML.querySelectorAll("name") // 函数调用者是返回来的document对象;而不是经常用的documnet;因为要查找的内容不再documnet里而在返回的对象中
const age = xhr.responseXML.querySelectorAll("age")
const addr = xhr.responseXML.querySelectorAll("addr")
const stuinfo = []
for (let i =0;i<uname.length;i++){
stuinfo.push("<tr><td>"+(i+1)+"</td><td>"+uname[i].innerHTML+"</td> <td>"+age[i].innerHTML+"</td><td>"+addr[i].innerHTML+"</td></tr>")
}
// 数组转字符串 渲染到页面中
document.querySelector("tbody").innerHTML = stuinfo.join("")
} else{
alert(xhr.status)
}
后端代码
注意点:返回数据的响应类型
/**
* @时间: 2023-05-15
* @作者: ppgo8
* @描述:对应07-使用XML交换数据.html
* 学员信息动态显示
* 后端返xml字符串
**/
@WebServlet("/ajaxrequest7")
public class AjaxRequest8Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应类型:xml
response.setContentType("text/xml;charset=utf-8");
PrintWriter out = response.getWriter();
// 返回数据,这里就不连接数据库了直接写死
StringBuilder xml = new StringBuilder();
xml.append("<students><student>");
xml.append("<name>张三</name>");
xml.append("<age>22</age>");
xml.append("<addr>天河区</addr>");
xml.append("</student>");
xml.append("<student>");
xml.append("<name>李四</name>");
xml.append("<age>23</age>");
xml.append("<addr>番禺区</addr>");
xml.append("</student>");
xml.append("</students>");
// 返回
out.print(xml);
}
}
AJAX乱码问题
-
对于tomcat10来说,get和post请求都不会发生乱码
-
对于tomcat9来说,
-
问题:ajax响应给前端中文的时候乱码。
-
解决方法 在后端添加代码
response.setContentType('text/html;charstet=UTF-8');
-
-
问题:发送ajax post请求的时候,发送给服务器的数据,服务器接受的数据乱码。
-
解决方法 在后端添加代码
request.setCharacterEncoding("UTF-8");
-
-
AJAX的异步和同步
-
同步和异步的概念
-
同步
如果ajax请求1在发送的时候需要等待ajax请求2结束之后才能发送。
同步会影响它之后发送的所有请求,不会影响前面的 -
异步
ajax请求1和ajax请求2,同时并发,互不干扰。
-
-
异步和同步在代码上的实现
// 同步请求 // 同步请求发送后,后面的所有请求都需要等待该请求结束,该请求结束后其他请求才可响应。 xhr1.open("请求方式", "URL", false) xhr1.send() // 异步请求 xhr2.open("请求方式", "URL", true) xhr2.send()
-
在开发过程中,什么时候使用同步?
如果业务有需求,就需要使用同步。
-
用户注册
-
用户名需要发送ajax请求校验
-
其他的也可能需要发送ajax请求
-
最终注册的时候,也是发送ajax请求进行注册。
-
-
业务要求
-
必须等待所有的校验ajax请求结束之后,才能发送注册的ajax请求。
-
注册的ajax请求和校验的ajax请求不能异步
-
-
AJAX代码封装
-
问题:AJAX请求相关的代码都是类似的,有很多重复的代码,能不能封装这些重复的代码。如果再发送AJAX请求,就直接调用这个工具类的相关函数即可。
-
手动封装工具类,js库,起名为jQuery;和后端没有关系,只是为了提高前端效率。
-
对象只能调用自己的方法,
jQuery对象不能调用dom对象的方法,dom对象不能调用jQury对象的方法。
函数可以使用其他变量的方式?
-
this
如果只需要使用函数调用者的相关信息,那么就不需要再次传入函数参数,比较麻烦;只用在函数内使用this即可
-
全局变量
比较作弊的写法
-
传入的参数
一般是获得了用户输入的值;或者其他的业务需要;且不再调用者中的值
第27个视频没看
细节:
js构造函数,当没有new任何对象出来时,构造函数(类)调用静态方法时,会出错。
所以调用静态方法前,必须要先new一个对象出来。
虽然调用这个静态方法不需要使用这个实例化对象。
-
补充
- 字符串.charAt(index):获得下标是index的元素,字符串形式。
附录:IDEA快捷键
shift+tab 代码块左移
alt一直按住+鼠标左键下托(鼠标点击不行) 多个光标同时编辑