AJAX

前置知识

客户端与服务器

上网的本质目的:通过互联网的形式来获取和消费资源
服务器:上网过程中,负责存放和对外提供资源的计算机
客户端:上网过程中,负责获取和消费资源的计算机
image

URL地址

URL(全称是Uniform Resource Locator)中文叫统一资源定位符,用于标识互联网上每个资源的唯一存放位置。浏览器只有通过URL地址,才能正确定位资源的存放位置,从而成功访问到对应的资源。
URL地址一般由三部组成:
① 客户端与服务器之间的通信协议
② 存有该资源的服务器名称
③ 资源在服务器上具体的存放位置
image

分析网页的打开过程

image
客户端:

  1. 打开浏览器
  2. 输入要访问的网站地址
  3. 回车,向服务器发起资源请求
    服务器:
  4. 服务器接收到客户端发来的资源请求
  5. 服务器在内部处理这次请求,找到相关的资源
  6. 服务器把找到的资源,响应(发送)给客户端
    注意:
    ① 客户端与服务器之间的通信过程,分为 请求 – 处理 – 响应 三个步骤。
    ② 网页中的每一个资源,都是通过 请求 – 处理 – 响应 的方式从服务器获取回来的。

浏览器开发者工具的相关使用

  1. 打开 Chrome 浏览器
  2. F12键 打开 Chrome 的开发者工具
  3. 切换到 Network 面板
  4. 选中 Doc 页签
  5. 刷新页面,分析客户端与服务器的通信过程

以Chrome网络控制台查看请求报文为例
当前网页加载的所有请求在检查的network面板列出
image

image

image

image

image

image

image

资源的请求方式

客户端请求服务器时,请求的方式有很多种,最常见的两种请求方式分别为 get 和 post 请求。

  • get 请求通常用于获取服务端资源(向服务器要资源)
    例如:根据 URL 地址,从服务器获取 HTML 文件、css 文件、js文件、图片文件、数据资源等
  • post 请求通常用于向服务器提交数据(往服务器发送资源)
    例如:登录时向服务器提交的登录信息、注册时向服务器提交的注册信息、添加用户时向服务器提交的用户信息等各种数据提交操作

数据交换格式

数据交换格式,就是服务器端与客户端之间进行数据传输与交换的格式。
前端领域,经常提及的两种数据交换格式分别是 XML 和 JSON。其中 XML 用的非常少,所以,我们重点要学习的数据交换格式就是 JSON
image

XML 简介

XML(EXtensible Markup Language) 可扩展标记语言。因此,XML 和 HTML 类似,也是一种标记语言。XML 被设计用来传输和存储数据。
XML和HTML的区别
XML 和 HTML 虽然都是标记语言,但是,它们两者之间没有任何的关系。

  • HTML 被设计用来描述网页上的内容,是网页内容的载体
  • XML 被设计用来传输和存储数据,是数据的载体
  • HTML 中都是预定义标签,而 XML 中没有预定义标签,全都是自定义标签,用来表示一些数据
    image

比如有一个学生数据:
name = "孙悟空" ; age = 18 ; gender = "男" ;
用 XML 表示:

<student>
<name>孙悟空</name>
<age>18</age>
<gender></gender>
</student>

XML的缺点
① XML 格式臃肿,和数据无关的代码多,体积大,传输效率低
② 在 Javascript 中解析 XML 比较麻烦
XML现在已经被 JSON 取代了。
用 JSON 表示:{"name":"孙悟空","age":18,"gender":"男"}

基于XML的数据交换

  • 注意:如果服务器端响应XML的话,响应的内容类型需要写成:

    response.setContentType("text/xml;charset=UTF-8");
  • xml和JSON都是常用的数据交换格式

    • XML体积大,解析麻烦。较少用。
    • JSON体积小,解析简单,较常用。
  • 基于XML的数据交换,前端代码

    <!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(){
    // 1.创建XMLHTTPRequest对象
    var xhr = new XMLHttpRequest();
    // 2.注册回调函数
    xhr.onreadystatechange = function () {
    if (this.readyState == 4) {
    if (this.status == 200) {
    // 服务器端响应了一个XML字符串,这里怎么接收呢?
    // 使用XMLHTTPRequest对象的responseXML属性,接收返回之后,可以自动封装成document对象(文档对象)
    var xmlDoc = this.responseXML
    //console.log(xmlDoc)
    // 获取所有的<student>元素,返回了多个对象,应该是数组。
    var students = xmlDoc.getElementsByTagName("student")
    //console.log(students[0].nodeName)
    var html = "";
    for (var i = 0; i < students.length; i++) {
    var student = students[i]
    // 获取<student>元素下的所有子元素
    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") {
    //console.log("name = " + node.textContent)
    html += "<td>"+node.textContent+"</td>"
    }
    if (node.nodeName == "age") {
    //console.log("age = " + node.textContent)
    html += "<td>"+node.textContent+"</td>"
    }
    }
    html += "</tr>"
    }
    document.getElementById("stutbody").innerHTML = html
    }else{
    alert(this.status)
    }
    }
    }
    // 3.开启通道
    xhr.open("GET", "/ajax/ajaxrequest6?t=" + new Date().getTime(), true)
    // 4.发送请求
    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">
    <!--<tr>
    <td>1</td>
    <td>zhangsan</td>
    <td>20</td>
    </tr>
    <tr>
    <td>2</td>
    <td>lisi</td>
    <td>22</td>
    </tr>-->
    </tbody>
    </table>
    </body>
    </html>
  • 基于XML的数据交换,后端java程序:

    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;
    /**
    * @program: 代码
    * @ClassName: AjaxRequest6Servlet
    * @version: 1.0
    * @description: 服务器端返回XML字符串
    * @author: bjpowernode
    * @create: 2022-05-15 11:48
    **/
    @WebServlet("/ajaxrequest6")
    public class AjaxRequest6Servlet 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();
    /*
    <students>
    <student>
    <name>zhangsan</name>
    <age>20</age>
    </student>
    <student>
    <name>lisi</name>
    <age>22</age>
    </student>
    </students>
    */
    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);
    }
    }

传统请求及缺点

  • 传统的请求都有哪些?
    • 直接在浏览器地址栏上输入URL。
    • 点击超链接
    • 提交form表单
    • 使用JS代码发送请求
      • window.open(url)
      • document.location.href = url
      • window.location.href = url
      • ....
  • 传统请求存在的问题
    • 页面全部刷新导致了用户的体验较差(页面刷新会导致部分数据丢失,页面刷新时若网速不好导致用户等待)。
    • 传统的请求导致用户的体验有空白期。(就是用户要等请求得到响应并将数据渲染到页面的时候才能继续操作,用户的体验是不连贯的)
    • image

AJAX概述

AJAX(Asynchronous Javascript And Xml):即异步的 JS 和 XML
通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。
AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
image

  • 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可以做到在同一个网页中同时启动多个请求,类似于在同一个网页中启动“多线程”,一个“线程”对应一个“请求”。
  • image
  • image

AJAX 的优点

  1. 可以无需刷新页面而与服务器端进行通信。
  2. 允许你根据用户事件来更新部分页面内容。
    AJAX 的缺点
  3. 没有浏览历史,不能回退
  4. 存在跨域问题(同源)
  5. SEO 不友好

Ajax的典型应用场景

  1. 用户名检测:注册用户时,通过 ajax 的形式,动态检测用户名是否被占用
    image
  2. 搜索提示:当输入搜索关键字时,通过 ajax 的形式,动态加载搜索提示列表
    image
  3. 数据分页显示:当点击页码值的时候,通过 ajax 的形式,根据页码值动态刷新表格的数据, 而无需刷新整个页面
    image
  4. 数据的增删改查:数据的添加、删除、修改、查询操作,都需要通过 ajax 的形式,来实现数据的交互(即修改了服务器上数据库中的数据)
    image

jQuery中的Ajax

浏览器中提供的 XMLHttpRequest 用法比较复杂,所以 jQuery 对 XMLHttpRequest 进行了封装,提供了一系列 Ajax 相关的函数,极大地降低了 Ajax 的使用难度。
jQuery 中发起 Ajax 请求最常用的三个方法如下:

  • $.get():从服务器拿数据
  • $.post():向服务器提交数据
  • $.ajax():既可以从服务器拿数据,又可以向服务器提交数据

$.get()

jQuery 中 .get()get使.get() 函数的语法如下:$.get(url, [data], [callback])
image

例如
url:http://www.liulongbin.top:3006/api/getbooks 内容如下
image

  • 使用 $.get() 函数发起不带参数的请求时,直接提供请求的 URL 地址和请求成功之后的回调函数即可
$.get(url, function(res) {
console.log(res) // 这里的 res 是服务器返回的数据
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/jquery.js"></script>
</head>
<body>
<button id="btnGET">发起不带参数的GET请求</button>
<script>
$(function () {
$('#btnGET').on('click', function () {
$.get('http://www.liulongbin.top:3006/api/getbooks', function (res) {
console.log(res)
})
})
})
</script>
</body>
</html>

image
image

  • 使用 $.get() 函数发起带参数的请求时,参数放入到一个对象中,格式如下
$.get('http://www.liulongbin.top:3006/api/getbooks', { id: 1 }, function(res) {
console.log(res)
})

image

$.post()

jQuery 中 .post()post.post(url, [data], [callback])`
image

$.post(
'http://www.liulongbin.top:3006/api/addbook', // 请求的URL地址
{ bookname: '水浒传', author: '施耐庵', publisher: '上海图书出版社' }, // 提交的数据
function(res) { // 回调函数
console.log(res)
}
)

image

$.ajax()

相比于 .get().post() 函数,jQuery 中提供的 .ajax()Ajax.ajax() 函数的基本语法如下:

$.ajax({
type: '', // 请求的方式,例如 GET 或 POST
url: '', // 请求的 URL 地址
data: { },// 这次请求要携带的数据
success: function(res) { } // 请求成功之后的回调函数
})

使用$.ajax()发起GET请求
使用 $.ajax() 发起 GET 请求时,只需要将 type 属性的值设置为 'GET' 即可:

<!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>Document</title>
<script src="./lib/jquery.js"></script>
</head>
<body>
<button id="btn">向服务器提交数据</button>
<script>
$(function(){
$("#btn").on('click',function(){
$.ajax({
type:'GET',
url:'http://www.liulongbin.top:3006/api/getbooks',
success:(res)=>{
console.log(res);
}
})
})
})
</script>
</body>
</html>

image
若在$.ajax()中的对象参数中添加data:{id:2},则获取的data数组是id为2的书籍信息
image

使用$.ajax()发起POST请求
使用 $.ajax() 发起 POST 请求时,只需要将 type 属性的值设置为 'POST' 即可

$.ajax({
type:'POST',
url:'http://www.liulongbin.top:3006/api/addbook',
data:{ bookname: 'C语言程序设计', author: '谭浩强', publisher: '清华
大学出版社' },
success:(res)=>{
console.log(res);
}
})

image

接口

接口的概念:使用 Ajax 请求数据时,被请求的 URL 地址,就叫做数据接口(简称接口)。同时,每个接口必须有请求方式。
例如:
http://www.liulongbin.top:3006/api/getbooks 获取图书列表的接口(GET请求)
http://www.liulongbin.top:3006/api/addbook 添加图书的接口(POST请求)

分析接口的请求过程

  1. 通过GET方式请求接口的过程
    image
  2. 通过POST方式请求接口的过程
    image

接口测试工具

  1. 什么是接口测试工具
    为了验证接口能否被正常被访问,我们常常需要使用接口测试工具,来对数据接口进行检测。
    好处:接口测试工具能让我们在不写任何代码的情况下,对接口进行调用和测试
    image

接口文档

接口文档,顾名思义就是接口的说明文档,它是我们调用接口的依据。好的接口文档包含了对接口URL,参数以及输出内容的说明,我们参照接口文档就能方便的知道接口的作用,以及接口如何使用。

  1. 接口文档的组成部分
    接口文档可以包含很多信息,也可以按需进行精简,不过,一个合格的接口文档,应该包含以下6项内容,从而为接口的调用提供依据:
  • 接口名称:用来标识各个接口的简单说明,如登录接口,获取图书列表接口等。
  • 接口URL:接口的调用地址。
  • 调用方式:接口的调用方式,如 GET 或 POST。
  • 参数格式:接口需要传递的参数,每个参数必须包含参数名称、参数类型、是否必选、参数说明这4项内容。
  • 响应格式:接口的返回值的详细描述,一般包含数据名称、数据类型、说明3项内容。
  • 返回示例(可选):通过对象的形式,例举服务器返回数据的结构
  1. 接口文档示例
    image
    image
    image

express基本使用

//1. 引入express
const express = require('express');
//2. 创建应用对象
const app = express();
//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/', (request, response)=>{
//设置响应
response.send('HELLO EXPRESS');
});
//4. 监听端口启动服务
app.listen(8000, ()=>{
console.log("服务已经启动, 8000 端口监听中....");
});

XMLHttpRequest对象

数据,也是服务器对外提供的一种资源。只要是资源,必然要通过 “请求 – 处理 – 响应” 的方式进行获取。
如果要在网页中请求服务器上的数据资源,则需要用到 XMLHttpRequest 对象。
XMLHttpRequest(简称 xhr)是浏览器提供的 js 成员(注意不是node.js提供的),通过它,可以请求服务器上的数据资源。
最简单的用法 var xhr = new XMLHttpRequest()
image

  • XMLHttpRequest对象是AJAX的核心对象,AJAX 的所有操作都是通过该对象进行的, 发送请求以及接收服务器数据的返回,全靠它了。

  • XMLHttpRequest对象,现代浏览器都是支持的,都内置了该对象。直接用即可。

  • 创建XMLHttpRequest对象

    • var xhr = new XMLHttpRequest();
  • XMLHttpRequest对象的方法

方法 描述
abort() 取消当前请求
getAllResponseHeaders() 返回头部信息 ,所有响应头
getResponseHeader() 返回特定的头部信息
open(method, url, async, user, psw) 规定请求method:请求类型 GET 或 POST; url:文件位置; async:true(异步)或 false(同步); user:可选的用户名称; psw:可选的密码
send() 将请求发送到服务器,用于 GET 请求
send(string) 将请求发送到服务器,用于 POST 请求
setRequestHeader() 向要发送的报头添加标签/值对
  • XMLHttpRequest对象的属性
属性 描述
onreadystatechange 定义当 readyState 属性发生变化时被调用的函数
readyState 保存 XMLHttpRequest 的状态。0:请求未初始化 1:服务器连接已建立,open()调用完毕 2:请求已收到,send()调用完毕 3:正在处理请求,返回了部分结果 4:请求已完成且响应已就绪,返回了所有的结果
response 响应体
responseText 以字符串返回响应数据
responseXML 以 XML 数据返回响应数据
status 返回请求的状态号200: "OK"403: "Forbidden"404: "Not Found"
statusText 返回状态文本(比如 "OK" 或 "Not Found")
image

XMLHttpRequest的基本使用

XMLHttpRequest(简称 xhr)是浏览器提供的 Javascript 对象,通过它,可以请求服务器上的数据资源。之前所学的 jQuery 中的 Ajax 函数,就是基于 xhr 对象封装出来的。
image

  1. 使用xhr发起GET请求
    步骤:
    ① 创建 xhr 对象
    ② 调用 xhr.open() 函数创建请求
    ③ 调用 xhr.send() 函数发送请求
    ④ 监听 xhr.onreadystatechange 事件
// 1. 创建 XHR 对象
var xhr = new XMLHttpRequest()
// 2. 调用 open 函数,指定 请求方式 与 URL地址
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
// 3. 调用 send 函数,发起 Ajax 请求
xhr.send()
// 4. 监听 onreadystatechange 事件
xhr.onreadystatechange = function() {
// 4.1 监听 xhr 对象的请求状态 readyState ;与服务器响应的状态 status
if (xhr.readyState === 4 && xhr.status === 200) {
// 4.2 打印服务器响应回来的数据
console.log(xhr.responseText)
}
}

image
2. 了解xhr对象的readyState属性
XMLHttpRequest 对象的 readyState 属性,用来表示当前 Ajax 请求所处的状态。每个 Ajax 请求必然处于以
下状态中的一个:
image
3. 使用xhr发起带参数的GET请求
使用 xhr 对象发起带参数的 GET 请求时,只需在调用 xhr.open 期间,为 URL 地址指定参数即可:

// ...省略不必要的代码
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks?id=1')
// ...省略不必要的代码

这种在 URL 地址后面拼接的参数,叫做查询字符串

查询字符串

定义:查询字符串(URL 参数)是指在 URL 的末尾加上用于向服务器发送信息的字符串(变量)。
格式:将英文的 ? 放在URL 的末尾,然后再加上 参数=值 ,想加上多个参数的话,使用 & 符号进行分隔。以这个形式,可以将想要发送给服务器的数据添加到 URL 中。

// 不带参数的 URL 地址
http://www.liulongbin.top:3006/api/getbooks
// 带一个参数的 URL 地址
http://www.liulongbin.top:3006/api/getbooks?id=1
// 带两个参数的 URL 地址
http://www.liulongbin.top:3006/api/getbooks?id=1&bookname=西游记

GET请求携带参数的本质
无论使用 .ajax()使.get(),又或者直接使用 xhr 对象发起 GET 请求,当需要携带参数的时候,本质上,都是直
接将参数以查询字符串的形式,追加到 URL 地址的后面,发送到服务器的。

$.get('url', {name: 'zs', age: 20}, function() {})
// 等价于
$.get('url?name=zs&age=20', function() {})
$.ajax({ method: 'GET', url: 'url', data: {name: 'zs', age: 20}, success: function() {} })
// 等价于
$.ajax({ method: 'GET', url: 'url?name=zs&age=20', success: function() {} })

URL编码与解码

  1. 什么是URL编码
    URL 地址中,只允许出现英文相关的字母、标点符号、数字。
    如果 URL 中需要包含中文字符,则必须对中文字符进行编码(转义)。
    URL编码的原则:使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。
    URL编码原则的通俗理解:使用英文字符去表示非英文字符。
http://www.liulongbin.top:3006/api/getbooks?id=1&bookname=西游记
// 经过 URL 编码之后,URL地址变成了如下格式:
![image](https://img2023.cnblogs.com/blog/2993264/202303/2993264-20230317211637061-1456502081.png)
  1. 对URL进行编码与解码
    浏览器提供了 URL 编码与解码的 API,分别是:
  • encodeURI() 编码的函数
  • decodeURI() 解码的函数
    注意:这两个函数都不是实例方法,它们是全局可用的
const url='http://www.liulongbin.top:3006/api/getbooks?id=1&bookname=西游记'
console.log(encodeURI(url));
console.log(decodeURI(encodeURI(url)));

image
由于浏览器会自动对 URL 地址进行编码操作,因此,大多数情况下,程序员不需要关心 URL 地址的编码与解码操作。

AJAX GET请求

  • 发送AJAX get请求,前端代码:

    <!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 () {
    //1. 创建AJAX核心对象
    var xhr = new XMLHttpRequest();
    //2. 注册回调函数
    xhr.onreadystatechange = function(){
    if (this.readyState == 4) {
    if (this.status == 200) {
    // 通过XMLHttpRequest对象的responseText属性可以获取到服务器响应回来的内容。
    // 并且不管服务器响应回来的是什么,都以普通文本的形势获取。(服务器可能响应回来:普通文本、XML、JSON、HTML...)
    // innerHTML属性是javascript中的语法,和ajax的XMLHttpRequest对象无关。
    // innerHTML可以设置元素内部的HTML代码。(innerHTML可以将后面的内容当做一段HTML代码解释并执行)
    //document.getElementById("myspan").innerHTML = this.responseText
    document.getElementById("mydiv").innerHTML = this.responseText
    // innerText也不是AJAX中的,是javascript中的元素属性,和XMLHttpRequest无关。
    // innerText也是设置元素中的内容,但是即使后面是一段HTML代码,也是将其看做一个普通字符串设置进去。
    //document.getElementById("myspan").innerText = this.responseText
    }else{
    alert(this.status)
    }
    }
    }
    //3. 开启通道
    xhr.open("GET", "/ajax/ajaxrequest2", true)
    //4. 发送请求
    xhr.send()
    }
    }
    </script>
    <button id="btn">发送ajax get请求</button>
    <span id="myspan"></span>
    <div id="mydiv"></div>
    </body>
    </html>
  • 发送AJAX get请求,后端代码:

    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;
    /**
    * @program: 代码
    * @ClassName: AjaxRequest2Servlet
    * @version: 1.0
    * @description:
    * @author: bjpowernode
    * @create: 2022-05-13 10:46
    **/
    @WebServlet("/ajaxrequest2")
    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....
    • 其实这个get请求提交数据的格式是HTTP协议中规定的,遵循协议即可。

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. 创建 xhr 对象
var xhr = new XMLHttpRequest()
// 2. 调用 open 函数
xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook')
// 3. 设置 Content-Type 属性,即设置请求头的内容类型。模拟form表单提交数据。较为固定的写法,注意写在send()之前, open()之后
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 4. 调用 send 函数
xhr.send('bookname=水浒传&author=施耐庵&publisher=上海图书出版社')
// 5. 监听事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
// 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请求,提交用户名
    • 在后端,接收到用户名,连接数据库,根据用户名去表中搜索
    • 如果用户名已存在
      • 后端响应消息:对不起,用户名已存在(在前端页面以红色字体展示)
    • 如果用户名不存在
      • 后端响应消息:用户名可以使用(在前端页面以绿色字体展示)
  • 实现一个案例:用户点击按钮之后,发送AJAX请求,显示学生列表。

    • 在后端java程序中拼接HTML代码,然后将HTML代码直接响应到浏览器客户端。这种方式不好,不应该在java代码中编写HTML代码,能否在java程序中直接向前端响应数据?可以,可以在后端拼接JSON格式的字符串,或者XML格式的字符串,将这个字符串发送给前端,前端解析即可。

一般是把身份校验的信息放在头信息中

AJAX乱码问题

  • 测试内容:

    • 发送ajax get请求
      • 发送数据到服务器,服务器获取的数据是否乱码?
      • 服务器响应给前端的中文,会不会乱码?
    • 发送ajax post请求
      • 发送数据到服务器,服务器获取的数据是否乱码?
      • 服务器响应给前端的中文,会不会乱码?
  • 包括还要测试tomcat服务器的版本:

    • tomcat10和tomcat9都要进行测试。
  • 测试结果:

    • 对于tomcat10来说,关于字符集,我们程序员不需要干涉,不会出现乱码。

    • 对于tomcat9来说呢?

      • 响应中文的时候,会出现乱码,怎么解决?

        response.setContentType("text/html;charset=UTF-8");
      • 发送ajax post请求的时候,发送给服务器的数据,服务器接收之后乱码,怎么解决?

        request.setCharacterEncoding("UTF-8");

AJAX的异步与同步

  • 什么是异步?什么是同步?

    • ajax请求1和ajax请求2,同时并发,谁也不用等谁,这就是异步。(a不等b,b也不等a)
    • 如果ajax请求1在发送的时候需要等待ajax请求2结束之后才能发送,那么这就是同步。(a等待b,或者b等待a,只要发生等待,就是同步。)
  • 异步和同步在代码上如何实现?

    // 假设这个是ajax请求1
    // 如果第三个参数是false:这个就表示“ajax请求1”不支持异步,也就是说ajax请求1发送之后,会影响其他ajax请求的发送,只有当我这个请求结束之后,你们其他的ajax请求才能发送。
    // false表示,不支持异步。我这个请求发了之后,你们其他的请求都要靠边站。都等着。你们别动呢,等我结束了你们再说。
    xhr1.open("请求方式", "URL", false)
    xhr1.send()
    // 假设这个是ajax请求2
    // 如果第三个参数是true:这个就表示“ajax请求2”支持异步请求,也就是说ajax请求2发送之后,不影响其他ajax请求的发送。
    xhr2.open("请求方式", "URL", true)
    xhr2.send()
  • 什么情况下用同步?(大部分情况下我们都是使用ajax异步方式,同步很少用。)

    • 举一个例子
      • 用户注册
        • 用户名需要发送ajax请求进行校验
        • 邮箱地址也需要发送ajax请求校验
        • 其他的也可能需要发送ajax请求。。。
        • 并且最终注册按钮的时候,也是发送ajax请求进行注册。
        • 那么显然,注册的Ajax请求和校验的ajax请求不能异步,必须等待所有的校验ajax请求结束之后,注册的ajax请求才能发。

AJAX代码封装

  • AJAX请求相关的代码都是类似的,有很多重复的代码,这些重复的代码能不能不写,能不能封装一个工具类。要发送ajax请求的话,就直接调用这个工具类中的相关函数即可。

  • 接下来,手动封装一个工具类,这个工具类我们可以把它看做是一个JS的库。我们把这个JS库起一个名字,叫做jQuery。(我这里封装的jQuery只是一个前端的库,和后端的java没有关系,只是为了方便web前端代码的编写,提高WEB前端的开发效率)

  • 手动开发jQuery,源代码

    function jQuery(selector){
    if (typeof selector == "string") {
    if (selector.charAt(0) == "#") {
    domObj = document.getElementById(selector.substring(1))
    return new jQuery()
    }
    }
    if (typeof selector == "function") {
    window.onload = selector
    }
    this.html = function(htmlStr){
    domObj.innerHTML = htmlStr
    }
    this.click = function(fun){
    domObj.onclick = fun
    }
    this.focus = function (fun){
    domObj.onfocus = fun
    }
    this.blur = function(fun) {
    domObj.onblur = fun
    }
    this.change = function (fun){
    domObj.onchange = fun
    }
    this.val = function(v){
    if (v == undefined) {
    return domObj.value
    }else{
    domObj.value = v
    }
    }
    // 静态的方法,发送ajax请求
    /**
    * 分析:使用ajax函数发送ajax请求的时候,需要程序员给我们传过来什么?
    * 请求的方式(type):GET/POST
    * 请求的URL(url):url
    * 请求时提交的数据(data):data
    * 请求时发送异步请求还是同步请求(async):true表示异步,false表示同步。
    */
    jQuery.ajax = function(jsonArgs){
    // 1.
    var xhr = new XMLHttpRequest();
    // 2.
    xhr.onreadystatechange = function(){
    if (this.readyState == 4) {
    if (this.status == 200) {
    // 我们这个工具类在封装的时候,先不考虑那么多,假设服务器返回的都是json格式的字符串。
    var jsonObj = JSON.parse(this.responseText)
    // 调用函数
    jsonArgs.success(jsonObj)
    }
    }
    }
    if (jsonArgs.type.toUpperCase() == "POST") {
    // 3.
    xhr.open("POST", jsonArgs.url, jsonArgs.async)
    // 4.
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
    xhr.send(jsonArgs.data)
    }
    if (jsonArgs.type.toUpperCase() == "GET") {
    xhr.open("GET", jsonArgs.url + "?" + jsonArgs.data, jsonArgs.async)
    xhr.send()
    }
    }
    }
    $ = jQuery
    // 这里有个细节,执行这个目的是为了让静态方法ajax生效。
    new jQuery()
  • 使用以上库,怎么用?

    <script type="text/javascript" src="/ajax/js/jQuery-1.0.0.js"></script>
    <script type="text/javascript">
    $(function(){
    $("#btn1").click(function(){
    $.ajax({
    type : "POST",
    url : "/ajax/ajaxrequest11",
    data : "username=" + $("#username").val(),
    async : true,
    success : function(json){
    $("#div1").html(json.uname)
    }
    })
    })
    })
    </script>

封装自己的Ajax函数

<!-- 1. 导入自定义的ajax函数库 -->
<script src="./myOwn.js"></script>
<script>
// 2. 调用自定义的函数,发起 Ajax 数据请求
myOwn({
method: '请求类型',
url: '请求地址',
data: { /* 请求参数对象 */ },
success: function(res) { // 成功的回调函数
console.log(res) // 打印数据
}
})
</script>

itheima() 函数是我们自定义的 Ajax 函数,它接收一个配置对象作为参数,配置对象中可以配置如下属性:

  • method 请求的类型
  • url 请求的 URL 地址
  • data 请求携带的数据
  • success 请求成功之后的回调函数

这里自定义的函数myOwn()存放在myOwn.js文件夹下

function myOwn(opt){
// 将data属性中的对象转换成查询字符串的格式
let data=opt.data
let arr=[]
for(let k in data){
arr.push(k+'='+data[k])
}
// 连接各数组元素,并以&分隔各项元素,返回该字符串
let qs =arr.join('&')
const xhr=new XMLHttpRequest()
// 判断请求类型
if(opt.method.toUpperCase()==='GET'){
xhr.open('GET',opt.url+'?'+qs)
xhr.send()
}else if(opt.method.toUpperCase()==='POST'){
xhr.open('POST',opt.url)
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
xhr.send(qs)
}
xhr.onreadystatechange=function(){
if (xhr.readyState===4&&xhr.status===200) {
// 返回的结果是JSON字符串,这里将其转换成对象
const result= JSON.parse(xhr.responseText)
opt.success(result)
}
}
}

调用myOwn()
没有查询字符串的GET请求

myOwn({
method: 'GET',
url: 'http://www.liulongbin.
top:3006/api/getbooks',
success: function (res) {
console.log(res)
}
})

image
有查询字符串的GET请求

myOwn({
method: 'GET',
url: 'http://www.liulongbin.
top:3006/api/getbooks',
// data: {
// id: 1
// },
success: function (res) {
console.log(res)
}
})

image
POST请求

myOwn({
method: 'post',
url: 'http://www.liulongbin.top:3006/api/addbook',
data: {
bookname: '水浒传',
author: '施耐庵',
publisher: '北京图书出版社'
},
success: function (res) {
console.log(res)
}
})

XMLHttpRequest Level2的新特性

  1. 旧版XMLHttpRequest的缺点
    ① 只支持文本数据的传输,无法用来读取和上传文件
    ② 传送和接收数据时,没有进度信息,只能提示有没有完成
  2. XMLHttpRequest Level2的新功能
    ① 可以设置 HTTP 请求的时限
    ② 可以使用 FormData 对象管理表单数据
    ③ 可以上传文件
    ④ 可以获得数据传输的进度信息

设置HTTP请求时限

有时,Ajax 操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。新版本的
XMLHttpRequest 对象,增加了 timeout 属性,可以设置 HTTP 请求的时限:
xhr.timeout = 3000
上面的语句,将最长等待时间设为 3000 毫秒。过了这个时限,就自动停止HTTP请求。与之配套的还有一个timeout 事件,用来指定超时后的回调函数:

xhr.ontimeout = function(event){
alert('请求超时!')
}
const xhr= new XMLHttpRequest()
xhr.timeout=30
xhr.ontimeout=function(){
console.log('请求超时');
}
xhr.open('GET','http://www.liulongbin.top:3006/api/getbooks')
xhr.send()
xhr.onreadystatechange=function(){
if(xhr.readyState===4&&xhr.status===200){
console.log(xhr.responseText);
}
}

image

FormData对象管理表单数据

Ajax 操作往往用来提交表单数据。为了方便表单处理,HTML5 新增了一个 FormData 对象,可以模拟表单操作

// 1. 新建 FormData 对象
var fd = new FormData()
// 2. 为 FormData 添加表单项
fd.append('uname', 'zs')
fd.append('upwd', '123456')
// 3. 创建 XHR 对象
var xhr = new XMLHttpRequest()
// 4. 指定请求类型与URL地址
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
// 5. 直接提交 FormData 对象,这与提交网页表单的效果,完全一样
xhr.send(fd)
const xhr = new XMLHttpRequest()
const fs=new FormData()
fs.append('name','za')
fs.append('age','20')
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
xhr.send(fs)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
}

image

FormData对象也可以用来获取网页表单的值,示例代码如下:

// 获取表单元素
var form = document.querySelector('#form1')
// 监听表单元素的 submit 事件
form.addEventListener('submit', function(e) {
// 阻止表单的默认提交事件
e.preventDefault()
// 根据 form 表单创建 FormData 对象,会自动将表单数据填充到 FormData 对象中
var fd = new FormData(form)
var xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
xhr.send(fd)
xhr.onreadystatechange = function() {}
})
<body>
<form id="form1">
<!-- autocomplete="off"表示关闭默认有的自动填充 -->
<input type="text" name="uname" autocomplete="off" />
<input type="password" name="upwd" />
<button type="submit">提交</button>
</form>
<script>
// 1. 通过 DOM 操作,获取到 form 表单元素
var form = document.querySelector('#form1')
form.addEventListener('submit', function (e) {
// 阻止表单的默认提交行为
e.preventDefault()
// 创建 FormData,快速获取到 form 表单中的数据
var fd = new FormData(form)
var xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
xhr.send(fd)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText))
}
}
})
</script>
</body>

image

上传文件

新版 XMLHttpRequest 对象,不仅可以发送文本信息,还可以上传文件。
实现步骤:
① 定义 UI 结构
② 验证是否选择了文件
③ 向 FormData 中追加文件
④ 使用 xhr 发起上传文件的请求
⑤ 监听 onreadystatechange 事件

<body>
<input type="file" id="fl">
<button>上传文件</button>
<br>
<!-- 3. img 标签,来显示上传成功以后的图片 -->
<img src="" id="img">
<script>
const btn=document.getElementsByTagName("button")[0]
const img=document.getElementById('img')
btn.addEventListener('click',function(){
// 获取<input type="file" id="fl">的文件对象
const files=document.getElementById('fl').files
// 判断是否选择了文件
if(files.length===0){
alert("请上传文件");
}
const fd=new FormData()
// 因为标签没有设置可以上传多个文件,所以每次上传只有一个文件,所以只需append() files[0]
fd.append('avatar',files[0])
const xhr=new XMLHttpRequest()
xhr.open('POST','http://www.liulongbin.top:3006/api/upload/avatar')
xhr.send(fd)
xhr.onreadystatechange=function(){
if(xhr.readyState===4&&xhr.status===200){
const data=JSON.parse(xhr.responseText)
console.log(data);
if(data.status===200){
img.src='http://www.liulongbin.top:3006'+data.url
}else{
console.log("图片上传失败!"+data.message);
}
}
}
})
</script>
</body>

image

显示文件上传进度

新版本的 XMLHttpRequest 对象中,可以通过监听 xhr.upload.onprogress 事件,来获取到文件的上传进度。
语法格式如下:

// 创建 XHR 对象
var xhr = new XMLHttpRequest()
// 监听 xhr.upload 的 onprogress 事件
xhr.upload.onprogress = function(e) {
// e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
if (e.lengthComputable) {
// e.loaded 已传输的字节
// e.total 需传输的总字节
var percentComplete = Math.ceil((e.loaded / e.total) * 100)
}
}

......
这个案例的UI是基于Bootstrap(基于jQuery的组件库)的,详见https://www.bilibili.com/video/BV1zs411h74a?p=53&vd_source=efd4241fdf9061e2f928f58914d04b92
我自己写了个原生JS实现进度条,没有依赖第三方库

点击查看代码
<!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>Document</title>
<style>
#box {
position: relative;
width: 300px;
height: 10px;
font-size: 6px;
line-height: 10px;
border-radius: 7px;
border: 2px solid gray;
margin: 20px;
}
#box>span {
position: absolute;
left: 130px;
}
#progress {
height: 100%;
width: 0%;
background-color: green;
border-radius: 5px;
}
.tran{
transition: width 1s;
}
</style>
</head>
<body>
<input type="file" id="fl">
<button>上传文件</button>
<br>
<div id="box">
<span>0%</span>
<div id="progress"></div>
</div>
<!-- 3. img 标签,来显示上传成功以后的图片 -->
<img src="" id="img">
<script>
// 提交按钮
const btn = document.getElementsByTagName("button")[0];
// 提交成功时显示的图片
const img = document.getElementById('img')
const box = document.getElementById("box")
const text = document.querySelector("#box>span")
const progress = document.getElementById("progress")
const fl=document.getElementById("fl")
// 点击“选择文件”按钮时清空上一次提交在页面的缓存数据
fl.addEventListener('click',function(){
// 清除进度条变短时的动画
progress.classList.remove("tran")
// 进度置0
var percent = 0;
progress.style.width = percent + '%';
text.textContent = percent + '%';
// 清除页面上一次提交的图片
img.src=""
})
btn.addEventListener('click', function () {
// 获取<input type="file" id="fl">的文件对象
const files = document.getElementById('fl').files
// 判断是否选择了文件
if (files.length === 0) {
return alert("请上传文件");
}
const fd = new FormData()
// 因为标签没有设置可以上传多个文件,所以每次上传只有一个文件,所以只需append() files[0]
fd.append('avatar', files[0])
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
progress.classList.add("tran")
// 注意不要写成xhr.onprogress,否则进度会直接从0%显示到100%
// 该事件每次提交会触发多次
xhr.upload.onprogress = function (event) {
if (event.lengthComputable) {
// 向上取整计算百分比
percent = Math.ceil((event.loaded / event.total) * 100)
console.log(percent);
// 根据百分比改变进度条的宽度
progress.style.width = percent + '%';
// 将百分比写入进度条
text.textContent = percent + '%';
}
}
xhr.send(fd)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText)
console.log(data);
if (data.status === 200) {
img.src = 'http://www.liulongbin.top:3006' + data.url
} else {
console.log("图片上传失败!" + data.message);
}
}
}
})
</script>
</body>
</html>

image

jQuery高级用法

jQuery实现文件上传

  1. 定义UI结构
<!-- 导入 jQuery -->
<script src="./lib/jquery.js"></script>
<!-- 文件选择框 -->
<input type="file" id="file1" />
<!-- 上传文件按钮 -->
<button id="btnUpload">上传</button>
  1. 验证是否选择了文件
$('#btnUpload').on('click', function() {
// 1. 将 jQuery 对象转化为 DOM 对象,并获取选中的文件列表
var files = $('#file1')[0].files
// 2. 判断是否选择了文件
if (files.length <= 0) {
return alert('请选择图片后再上传!‘)
}
}
  1. 向FormData中追加文件
// 向 FormData 中追加文件
var fd = new FormData()
fd.append('avatar', files[0])
  1. 使用jQuery发起上传文件的请求
$.ajax({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/upload/avatar',
data: fd,
// 不修改 Content-Type 属性,使用 FormData 默认的 Content-Type 值
contentType: false,
// 不对 FormData 中的数据进行 url 编码,而是将 FormData 数据原样发送到服务器
processData: false,
success: function(res) {
console.log(res)
}
}

jQuery实现loading效果

  1. ajaxStart(callback)
    Ajax 请求开始时,执行 ajaxStart 函数。可以在 ajaxStart 的 callback 中显示 loading 效果,示例代码如下:
// 该方法是附加到document上的
$(document).ajaxStart(function() {
$('#loading').show()
})

注意: $(document).ajaxStart() 函数会监听当前文档内所有的 Ajax 请求。
2. ajaxStop(callback)
Ajax 请求结束时,执行 ajaxStop 函数。可以在 ajaxStop 的 callback 中隐藏 loading 效果,示例代码如下:

// 该方法是附加到document上的
$(document).ajaxStop(function() {
$('#loading').hide()
})
<body>
<input type="file" id="fl">
<button>上传文件</button>
<br>
<!-- 3. img 标签,来显示上传成功以后的图片 -->
<img src="./images/loading.gif" id="img" style="display: none;">
<script>
// ajax请求发起的操作
$(document).ajaxStart(()=>{
$("#img").show()
})
// ajax请求结束的操作
$(document).ajaxStop(()=>{
$("#img").hide()
})
$("button").on('click',function(){
// jQuery对象加上[0]下标后就变成了DOM对象
// 获取<input type="file" id="fl">的文件对象
const files=$('#fl')[0].files
// 判断是否选择了文件
if(files.length===0){
return alert("请选择文件后再上传!");
}
const fd=new FormData()
// 因为标签没有设置可以上传多个文件,所以每次上传只有一个文件,所以只需append() files[0]
fd.append('avatar',files[0])
$.ajax({
method:'POST',
url:'http://www.liulongbin.top:3006/api/upload/avatar',
contentType:false,
processData:false,
data:fd,
success:(res)=>{
console.log(res);
}
})
})
</script>
</body>

image

AJAX实现省市联动

  • 什么是省市联动?

    • 在网页上,选择对应的省份之后,动态的关联出该省份对应的市。选择对应的市之后,动态的关联出该市对应的区。(首先要清楚需求)
  • 进行数据库表的设计

    • t_area (区域表)
      id(PK-自增) code name pcode
      ---------------------------------------------
      1 001 河北省 null
      2 002 河南省 null
      3 003 石家庄 001
      4 004 邯郸 001
      5 005 郑州 002
      6 006 洛阳 002
      7 007 丛台区 004
      将全国所有的省、市、区、县等信息都存储到一张表当中。
      采用的存储方式实际上是code pcode形势。
  • 建表t_area,模拟好数据。

  • 首先实现第一个功能:

    • 页面加载完毕之后,先把省份全部展现出来。

AJAX跨域问题

跨域

  • 跨域是指从一个域名的网页去请求另一个域名的资源。比如从百度(https://baidu.com)页面去请求京东(https://www.jd.com)的资源。
  • 通过超链接或者form表单提交或者window.location.href的方式进行跨域是不存在问题的(大家可以编写程序测试一下)。但在一个域名的网页中的一段js代码发送ajax请求去访问另一个域名中的资源,由于同源策略的存在导致无法跨域访问,那么ajax就存在这种跨域问题。
  • 同源策略是指一段脚本只能读取来自同一来源的窗口和文档的属性,同源就是协议、域名和端口都相同。
  • 同源策略有什么用?如果你刚刚在网银输入账号密码,查看了自己还有1万块钱,紧接着访问一些不规矩的网站,这个网站可以访问刚刚的网银站点,并且获取账号密码,那后果可想而知。所以,从安全的角度来讲,同源策略是有利于保护网站信息的。
  • 有一些情况下,我们是需要使用ajax进行跨域访问的。比如某公司的A页面(a..com)有可能需要获取B页面(b.xxx)。

同源还是不同源

  • 区分同源和不同源的三要素

    • 协议
    • 域名
    • 端口
  • 协议一致,域名一致,端口号一致,三个要素都一致,才是同源,其它一律都是不同源

复现AJAX跨域问题

AJAX跨域解决方案

方案1:设置响应头

  • 核心原理:跨域访问的资源允许你跨域访问。

  • 实现:

    • response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080"); // 允许某个
      response.setHeader("Access-Control-Allow-Origin", "*"); // 允许所有

方案2:jsonp

  • jsonp:json with padding(带填充的json【学完之后再理解这个什么意思!!!】)
  • jsonp不是一个真正的ajax请求。只不过可以完成ajax的局部刷新效果。可以说jsonp是一种类ajax请求的机制。
  • jsonp不是ajax请求,但是可以完成局部刷新的效果,并且可以解决跨域问题。
  • 注意:jsonp解决跨域的时候,只支持GET请求。不支持post请求。

方案3:jQuery封装的jsonp

  • 牛人们写的jQuery库,已经对jsonp进行了封装。大家可以直接拿来用。

  • 用之前需要引入jQuery库的js文件。(这里的jQuery库咱们就不再封装了,咱们直接用jQuery写好的jsonp方式。)

  • jQuery中的jsonp其实就是我们方案2的高度封装,底层原理完全相同。

  • 核心代码

    • $.ajax({
      type : "GET",
      url : "跨域的url",
      dataType : "jsonp", // 指定数据类型
      jsonp : "fun", // 指定参数名(不设置的时候,默认是:"callback")
      jsonpCallback : "sayHello" // 指定回调函数的名字
      // (不设置的时候,jQuery会自动生成一个随机的回调函数,
      //并且这个回调函数还会自动调用success的回调函数。)
      })

方案4:代理机制(httpclient)

  • 使用Java程序怎么去发送get/post请求呢?【GET和POST请求就是HTTP请求。】
    • 第一种方案:使用JDK内置的API(java.net.URL.....),这些API是可以发送HTTP请求的。
    • 第二种方案:使用第三方的开源组件,比如:apache的httpclient组件。(httpclient组件是开源免费的,可以直接用)
  • 在java程序中,使用httpclient组件可以发送http请求。
    • 对于httpclient组件的代码,大家目前可以不进行深入的研究,可以从网上直接搜。然后粘贴过来,改一改,看看能不能完成发送get和post请求。
    • 使用httpclient组件,需要先将这个组件相关的jar包引入到项目当中。

方案5:nginx反向代理

  • nginx反向代理中也是使用了这种代理机制来完成AJAX的跨域,实现起来非常简单,只要修改一个nginx的配置即可。以后大家学习nginx之后再说吧。!!!!

AJAX实现搜索联想 自动补全

  • 什么是搜索联想?自动补全?
    • 百度是一个很典型的代表。在百度的搜索框中输入相关信息的时候,会有搜索联想以及自动补全。
    • 搜索联想和自动补全:实际上是为了方便用户的使用。让用户的体验更好。
    • 搜索联想:当用户输入一些单词之后,自动联想出用户要搜索的信息,给一个提示。
    • 自动补全:当联想出一些内容之后,用户点击某个联想的单词,然后将这个单词自动补全到搜索框当中。
    • 搜索联想和自动补全功能,因为是页面局部刷新效果,所以需要使用ajax请求来完成。
  • 搜索联想,自动补全功能的核心实现原理?
    • 当键盘事件发生之后,比如:keyup:键弹起事件。
    • 发送ajax请求,请求中提交用户输入的搜索内容,例如:北京(发送ajax请求,携带“北京”两个字)
    • 后端接收到ajax请求,接收到“北京”两个字,执行select语句进行模糊查询。返回查询结果。
    • 将查询结果封装成json格式的字符串,将json格式的字符串响应到前端。
    • 前端接收到json格式的字符串之后,解析这个json字符串,动态展示页面。

本文作者:Code6E

本文链接:https://www.cnblogs.com/road2code/p/17185476.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Code6E  阅读(27)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.