Ajax的使用
传统请求及缺点
传统的请求都有哪些?
点击超链接
- 提交form表单
使用JS代码发送请求
window.open(url)
- document.location.href = url
- window.location.href = url
….
传统请求存在的问题
页面全部刷新导致了用户的体验较差。
- 传统的请求导致用户的体验有空白期。(用户的体验是不连贯的)
AJAX概述
- AJAX不能称为一种技术,它是多种技术的综合产物。
- AJAX可以让浏览器发送一种特殊的请求,这种请求可以是:异步的。
什么是异步,什么是同步?
假设有t1和t2线程,t1和t2线程并发,就是异步。
- 假设有t1和t2线程,t2在执行的时候,必须等待t1线程执行到某个位置之后t2才能执行,那么t2在等t1,显然他们是排队的,排队的就是同步。
AJAX可以发送异步请求。也就是说,在同一个浏览器页面当中,可以发送多个ajax请求,这些ajax请求之间不需要等待,是并发的。
AJAX代码属于WEB前端的JS代码。和后端的java没有关系,后端也可以是php语言,也可以是C语言。
- AJAX 应用程序可能使用 XML 来传输数据,但将数据作为纯文本或 JSON 文本传输也同样常见。
- AJAX可以更新网页的部分,而不需要重新加载整个页面。(页面局部刷新)
- AJAX可以做到在同一个网页中同时启动多个请求,类似于在同一个网页中启动“多线程”,一个“线程”一个“请求”。
XMLHttpRequest对象
- XMLHttpRequest对象是AJAX的核心对象,发送请求以及接收服务器数据的返回,全靠它了。
- XMLHttpRequest对象,现代浏览器都是支持的,都内置了该对象。直接用即可。
- 创建XMLHttpRequest对象
1
| var xhr = new XMLHttpRequest();
|
| 方法 | 描述 |
|---|
| abort() | 取消当前请求 |
| getAllResponseHeaders() | 返回头部信息 |
| getResponseHeader() | 返回特定的头部信息 |
| open(method, url, async, user, psw) | 规定请求method:请求类型 GET 或 POSTurl:文件位置async:true(异步)或 false(同步)user:可选的用户名称psw:可选的密码 |
| send() | 将请求发送到服务器,用于 GET 请求 |
| send(string) | 将请求发送到服务器,用于 POST 请求 |
| setRequestHeader() | 向要发送的报头添加标签/值对 |
| 属性 | 描述 |
|---|
| onreadystatechange | 定义当 readyState 属性发生变化时被调用的函数 |
| readyState | 保存 XMLHttpRequest 的状态。0:请求未初始化 1:服务器连接已建立 2:请求已收到 3:正在处理请求 4:请求已完成且响应已就绪 |
| responseText | 以字符串返回响应数据 |
| responseXML | 以 XML 数据返回响应数据 |
| status | 返回请求的状态号200: “OK”403: “Forbidden”404: “Not Found” |
| statusText | 返回状态文本(比如 “OK” 或 “Not Found”) |
AJAX GET请求
发送AJAX get请求,前端代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>发送ajax get请求</title> </head> <body> <script type="text/javascript"> window.onload = function () { document.getElementById("btn").onclick = function () { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if (this.readyState == 4) { if (this.status == 200) { document.getElementById("mydiv").innerHTML = this.responseText }else{ alert(this.status) } } } xhr.open("GET", "/ajax/ajaxrequest2", true) xhr.send() } } </script> <button id="btn">发送ajax get请求</button> <span id="myspan"></span> <div id="mydiv"></div> </body> </html>
|
AJAX GET请求的缓存问题
- 对于低版本的IE浏览器来说,AJAX的get请求可能会走缓存。存在缓存问题。对于现代的浏览器来说,大部分浏览器都已经不存在AJAX get缓存问题了。
什么是AJAX GET请求缓存问题呢?
在HTTP协议中是这样规定get请求的:get请求会被缓存起来。
发送AJAX GET请求时,在同一个浏览器上,前后发送的AJAX请求路径一样的话,对于低版本的IE来说,第二次的AJAX GET请求会走缓存,不走服务器。
POST请求在HTTP协议中规定的是:POST请求不会被浏览器缓存。
GET请求缓存的优缺点:
优点:直接从浏览器缓存中获取资源,不需要从服务器上重新加载资源,速度较快,用户体验好。
缺点:无法实时获取最新的服务器资源。
浏览器什么时候会走缓存?
第一:是一个GET请求
第二:请求路径已经被浏览器缓存过了。第二次发送请求的时候,这个路径没有变化,会走浏览器缓存。
如果是低版本的IE浏览器,怎么解决AJAX GET请求的缓存问题呢?
可以在请求路径url后面添加一个时间戳,这个时间戳是随时变化的。所以每一次发送的请求路径都是不一样的,这样就不会走浏览器的缓存问题了。
- 可以采用时间戳:”url?t=” + new Date().getTime()
- 或者可以通过随机数:”url?t=” + Math.random()
- 也可以随机数+时间戳….
AJAX POST请求
- AJAX POST请求和GET请求只是前端代码有区别。后端代码没有区别。
1 2 3 4 5 6 7
| // 4. 发送AJAX POST请求 xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") // 设置请求头的内容类型。模拟form表单提交数据。 // 获取表单中的数据 var username = document.getElementById("username").value; var password = document.getElementById("password").value; // send函数中的参数就是发送的数据,这个数据在“请求体”当中发送。 xhr.send("username="+username+"&password="+password)
|
实现一个案例:使用AJAX POST请求实现用户注册的时候,用户名是否可用。(验证用户名是否可以注册)实现步骤如下:
在前端,用户输入用户名之后,失去焦点事件blur发生,然后发送AJAX POST请求,提交用户名
- 在后端,接收到用户名,连接数据库,根据用户名去表中搜索
如果用户名已存在
后端响应消息:对不起,用户名已存在(在前端页面以红色字体展示)
如果用户名不存在
后端响应消息:用户名可以使用(在前端页面以绿色字体展示)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>AJAX POST请求验证用户名是否可用</title> </head> <body> <script type="text/javascript"> window.onload = function(){ document.getElementById("username").onfocus = function (){ document.getElementById("tipMsg").innerHTML = "" } document.getElementById("username").onblur = function (){ //console.log("正在发送AJAX POST请求验证用户名") // 发送AJAX POST请求 // 1. var xhr = new XMLHttpRequest() // 2. xhr.onreadystatechange = function () { if (this.readyState == 4) { if (this.status == 200) { document.getElementById("tipMsg").innerHTML = this.responseText }else{ alert(this.status) } } } // 3. xhr.open("POST", "/ajax/ajaxrequest4", true) // 4. xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") // 获取表单数据 var username = document.getElementById("username").value xhr.send("uname=" + username)//这个uname随便写,前端的发送,后端使用这个接受 } } </script> 用户名:<input type="text" id="username"> <span id="tipMsg"></span> </body> </html> package com.bjpowernode.ajax.servlet;
import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.PrintWriter; import java.sql.*;
/** * @program: 代码 * @ClassName: AjaxRequest4Servlet * @version: 1.0 * @description: 验证用户名是否可用 * @author: bjpowernode * @create: 2022-05-14 10:19 **/ @WebServlet("/ajaxrequest4") public class AjaxRequest4Servlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取用户名 String uname = request.getParameter("uname"); // 打布尔标记(一种编程模型) boolean flag = false; // 默认是用户名不存在。 // 连接数据库验证用户名是否存在 Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { // 1.注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 2.获取连接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC", "root", "root"); // 3.获取预编译的数据库操作对象 String sql = "select id,name from t_user where name = ?"; ps = conn.prepareStatement(sql); ps.setString(1, uname); // 4.执行SQL语句 rs = ps.executeQuery(); // 5.处理结果集 if (rs.next()) { // 用户名已存在。 flag = true; }
} catch (Exception e) { e.printStackTrace(); } finally { // 6.释放资源 if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
// 响应结果到浏览器 response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); if (flag) { // 用户名已存在,不可用 out.print("<font color='red'>对不起,用户名已存在</font>"); }else{ // 用户名不存在,可以使用 out.print("<font color='green'>用户名可以使用</font>"); } } }
|
基于JSON的数据交换
在WEB前端中如何将一个json格式的字符串转换成json对象
最简单粗暴的方法:在后端拼接JSON格式的字符串,响应给前端的浏览器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| json.append("["); while (rs.next()) { // 获取每个学生的信息 String name = rs.getString("name"); String age = rs.getString("age"); String addr = rs.getString("addr"); // 拼接json格式的字符串 // {"name":" 王五 ","age": 20 ,"addr":" 北京大兴区 "}, json.append("{\"name\":\""); json.append(name); json.append("\",\"age\":"); json.append(age); json.append(",\"addr\":\""); json.append(addr); json.append("\"},"); } jsonStr = json.substring(0, json.length() - 1) + "]";
|
但在后端拼接JSON格式的字符串过于痛苦,可以使用阿里巴巴的fastjson组件,可以直接将java对象转换成json格式的字符串
1 2 3 4 5 6 7 8 9 10 11 12 13
| List<Student> studentList = new ArrayList<>(); while (rs.next()) { // 取出数据 String name = rs.getString("name"); int age = rs.getInt("age"); String addr = rs.getString("addr"); // 将以上数据封装成Student对象 Student s = new Student(name, age, addr); // 将Student对象放到List集合 studentList.add(s); } // 将List集合转换成json字符串 jsonStr = JSON.toJSONString(studentList);
|
注意:使用fastjson需要引入fastjson-1.2.2.jar
基于XML的数据交换
- 注意:如果服务器端响应XML的话,响应的内容类型需要写成:
1
| response.setContentType("text/xml;charset=UTF-8");
|
xml和JSON都是常用的数据交换格式
XML体积大,解析麻烦。较少用。
JSON体积小,解析简单,较常用。
基于XML的数据交换,前端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用XML完成数据交换</title> </head> <body> <script type="text/javascript"> window.onload = function(){ document.getElementById("btn").onclick = function(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (this.readyState == 4) { if (this.status == 200) { var xmlDoc = this.responseXML var students = xmlDoc.getElementsByTagName("student") var html = ""; for (var i = 0; i < students.length; i++) { var student = students[i] html += "<tr>" html += "<td>"+(i+1)+"</td>" var nameOrAge = student.childNodes for (var j = 0; j < nameOrAge.length; j++) { var node = nameOrAge[j] if (node.nodeName == "name") { html += "<td>"+node.textContent+"</td>" } if (node.nodeName == "age") { html += "<td>"+node.textContent+"</td>" } } html += "</tr>" } document.getElementById("stutbody").innerHTML = html }else{ alert(this.status) } } } xhr.open("GET", "/ajax/ajaxrequest6?t=" + new Date().getTime(), true) xhr.send() } } </script> <button id="btn">显示学生列表</button> <table width="500px" border="1px"> <thead> <tr> <th>序号</th> <th>姓名</th> <th>年龄</th> </tr> </thead> <tbody id="stutbody">
</tbody> </table> </body> </html>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| package com.bjpowernode.ajax.servlet;
import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.PrintWriter;
@WebServlet("/ajaxrequest6") public class AjaxRequest6Servlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/xml;charset=UTF-8"); PrintWriter out = response.getWriter();
StringBuilder xml = new StringBuilder(); xml.append("<students>"); xml.append("<student>"); xml.append("<name>zhangsan</name>"); xml.append("<age>20</age>"); xml.append("</student>"); xml.append("<student>"); xml.append("<name>lisi</name>"); xml.append("<age>22</age>"); xml.append("</student>"); xml.append("</students>");
out.print(xml); } }
|
AJAX乱码问题
1
| response.setContentType("text/html;charset=UTF-8");
|
- 发送ajax post请求的时候,发送给服务器的数据,服务器接收之后乱码,怎么解决?
1
| request.setCharacterEncoding("UTF-8");
|
AJAX的异步与同步
1 2 3 4 5 6 7 8 9 10
|
xhr1.open("请求方式", "URL", false) xhr1.send()
xhr2.open("请求方式", "URL", true) xhr2.send()
|
-