同步请求
用户向HTTP服务器提交一个处理请求。服务器端接收到该请求后,按照预先编写好的程序中的业务逻辑进行处理。服务器对请求进行响应,将结果返回给客户端,由CSS样式丰富页面的显示效果。
优点
可以保留浏览器后退按钮的正常功能。
不足之处
- 给用户一种不连贯的体验,当服务器处理请求时,用户只能等待状态,页面中的显示内容只能是空白。
- 因为已经跳转到新的页面,原本在页面上的信息无法保存,信息需要重新填写。
异步请求
用户向HTTP服务器提交一个处理请求,不需要等待返回,随时可以再发送下一个请求。先响应用户的请求,然后写入数据库,用户体验较好。
优点
- 前端用户操作和后台服务器可以同时进行。
- 页面没有跳转,页面原有信息会保留。
不足之处
可能会破坏浏览器后退按钮的正常行为。在动态更新页面的情况下,用户无法回到前一个页面状态,这是因为浏览器仅能记录的始终是当前一个的静态页面。
Ajax 介绍
Ajax(Asynchronous Javascript And XML):利用js和xml实现的异步网络请求
Aja 有什么用?
例如:在搜索功能中,当用户点击"搜索"按钮,请求会开始提交,浏览器会刷新页面,在新页面中告知操作结果。
如果我们希望用户点击"搜索",让用户停留在当前页面,同时发送新的HTTP请求,获取到数据后再更新页面,这样用户体验会更好。基本上所有的网站都用到了异步网络请求技术。
Ajax 工作原理
通过XmlHttpRequest对象来向服务器发出异步请求,从服务器中获得数据,然后用JavaScript来操作DOM从而更新局部页面。
Ajax 是一种无需重新加载整个网页,能够更新部分网页的技术。
HTTP请求方式
- OPTIONS 返回服务器所支持的请求方法
- GET 向服务器获取指定资源
- HEAD 与 GET 一致,只不过响应体不返回,只返回响应头
- POST 向服务器提交数据,数据放在请求体里
- PUT 与 POST相似,只是具有幂等特性,一般用于更新
- DELETE 删除服务器指定资源
- TRACE 回显服务器端收到的请求,测试的时候会用到这个
- CONNECT预留,暂无使用
POST与GET的区别
- 语义不同:get是获取数据的,而post是提交数据的
- 功能表现:
- get用于获取信息,是无副作用的,是幂等的,且可缓存
- post用于修改服务器上的数据,有副作用,非幂等,不可缓存
XMlHttpRequest 对象的三个重要的属性
属性 | 描述 |
onreadystatechange | 存储函数(或函数名),每当readystate属性改变是,就会调用该函数 |
readystate | 存有XMlHttpRequest 的状态。从0到4发生百变化。
|
status | 200:ok 404:not found |
HTTP状态码
分类 | 描述 |
1xx | 信息,服务器收到请求,需要请求者继续执行操作 |
2xx | 成功,操作被成功接收并处理 |
3xx | 重定向,需要进一步的操作以完成请求 |
4xx | 客户端错误,请求包含语法错误或无法完成请求 |
5xx | 服务器错误,服务器在处理请求的过程中发生了错误 |
Ajax 异步请求
准备好服务端请求:http://172.16.10.110:5000/users
[root@python ~]# cat Ajax_test.py
#!/usr/bin/python3
import json
from flask import Flask
app = Flask(__name__)
@app.route("/users")
def users():
"""
返回用户年龄信息
"""
res = [
{"name":"root","age":18},
{"name":"admin","age":19},
{"name":"jack","age":20},
{"name":"rose","age":18},
]
return json.dumps(res,ensure_ascii=False)
if __name__ == '__main__':
app.run('0.0.0.0',5000,threaded=True)
启动
[root@python ~]# python3 Ajax_test.py
Traceback (most recent call last):
File "Ajax_test.py", line 4, in <module>
from flask import Flask
ModuleNotFoundError: No module named 'flask'
[root@python ~]# pip3 install flask
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting flask
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/cd/77/59df23681f4fd19b7cbbb5e92484d46ad587554f5d490f33ef907e456132/Flask-2.0.3-py3-none-any.whl (95kB)
100% |████████████████████████████████| 102kB 512kB/s
Collecting Werkzeug>=2.0 (from flask)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/f4/f3/22afbdb20cc4654b10c98043414a14057cd27fdba9d4ae61cea596000ba2/Werkzeug-2.0.3-py3-none-any.whl (289kB)
100% |████████████████████████████████| 296kB 2.0MB/s
Collecting itsdangerous>=2.0 (from flask)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/9c/96/26f935afba9cd6140216da5add223a0c465b99d0f112b68a4ca426441019/itsdangerous-2.0.1-py3-none-any.whl
Collecting click>=7.1.2 (from flask)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/4a/a8/0b2ced25639fb20cc1c9784de90a8c25f9504a7f18cd8b5397bd61696d7d/click-8.0.4-py3-none-any.whl (97kB)
100% |████████████████████████████████| 102kB 4.3MB/s
Collecting Jinja2>=3.0 (from flask)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/20/9a/e5d9ec41927401e41aea8af6d16e78b5e612bca4699d417f646a9610a076/Jinja2-3.0.3-py3-none-any.whl (133kB)
100% |████████████████████████████████| 143kB 12.0MB/s
Collecting dataclasses; python_version < "3.7" (from Werkzeug>=2.0->flask)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/fe/ca/75fac5856ab5cfa51bbbcefa250182e50441074fdc3f803f6e76451fab43/dataclasses-0.8-py3-none-any.whl
Collecting importlib-metadata; python_version < "3.8" (from click>=7.1.2->flask)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/a0/a1/b153a0a4caf7a7e3f15c2cd56c7702e2cf3d89b1b359d1f1c5e59d68f4ce/importlib_metadata-4.8.3-py3-none-any.whl
Collecting MarkupSafe>=2.0 (from Jinja2>=3.0->flask)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/fc/d6/57f9a97e56447a1e340f8574836d3b636e2c14de304943836bd645fa9c7e/MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl
Collecting zipp>=0.5 (from importlib-metadata; python_version < "3.8"->click>=7.1.2->flask)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/bd/df/d4a4974a3e3957fd1c1fa3082366d7fff6e428ddb55f074bf64876f8e8ad/zipp-3.6.0-py3-none-any.whl
Collecting typing-extensions>=3.6.4; python_version < "3.8" (from importlib-metadata; python_version < "3.8"->click>=7.1.2->flask)
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/45/6b/44f7f8f1e110027cf88956b59f2fad776cca7e1704396d043f89effd3a0e/typing_extensions-4.1.1-py3-none-any.whl
Installing collected packages: dataclasses, Werkzeug, itsdangerous, zipp, typing-extensions, importlib-metadata, click, MarkupSafe, Jinja2, flask
Successfully installed Jinja2-3.0.3 MarkupSafe-2.0.1 Werkzeug-2.0.3 click-8.0.4 dataclasses-0.8 flask-2.0.3 importlib-metadata-4.8.3 itsdangerous-2.0.1 typing-extensions-4.1.1 zipp-3.6.0
[root@python ~]# python3 Ajax_test.py
* Serving Flask app 'Ajax_test' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://172.16.10.110:5000/ (Press CTRL+C to quit)
172.16.10.1 - - [27/Sep/2023 11:47:43] "GET / HTTP/1.1" 404 -
172.16.10.1 - - [27/Sep/2023 11:47:43] "GET /favicon.ico HTTP/1.1" 404 -
172.16.10.1 - - [27/Sep/2023 11:47:59] "GET /users HTTP/1.1" 200 -
172.16.10.1 - - [27/Sep/2023 11:49:14] "GET /users HTTP/1.1" 200 -
访问
原生Ajax
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<button onclick="getDate()">点击加载</button>
<h1>请求结果</h1>
<p id="content"></p>
<script>
function getDate(){
console.log("请求开始")
//新建XMLHttpRequest对象
var request = new XMLHttpRequest();
//创建请求
request.open("GET","http://172.16.10.110:5000/users")
//发送请求
request.send()
//监听request的状态
request.onreadystatechange = function(){
if(request.readyState == 4){
console.log("请求已完成")
if(request.status == 200){
console.log("请求成功")
console.log(request.responseText)
document.getElementById("content").innerHTML = request.responseText
}else{
console.log("请求失败")
}
}else{
console.log("请求进行中,继续等待",request.readyState)
}
}
console.log("请求结束")
}
</script>
</body>
</html>
测试
跨域问题
跨域问题来源于JavaScript的同源策略:
- 只有同源的资源允许相互访问
- 同源:两个网站之间 协议头、端口号、域名 三个都一样就是同源
- 跨域:两个网站之间 协议头、端口号、域名 三个有任意一个不一样就是跨域
- 也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。
跨域问题是针对js和Ajax的,HTML本身没有跨域问题,例如a标签、script标签、甚至form标签(可以直接跨域发送数据并且接收数据)等。
跨域问题解决方案:CORS,跨域资源共享(Cross-origin resource sharing)
- CORS允许浏览器向跨域的服务器,发出XMlHttpRequest请求,从而克服了Ajax只能同源使用的限制。它是一种基于HTTP头的机制,该机制通过允许服务器标示除了它自己以外的其他origin(域,协议,端口),这样浏览器可以访问加载这些资源。
- CORS需要浏览器和服务器同时支持。目前,所有的浏览器都支持该功能。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。
- 服务端解决主要是通过添加:"Access-Control-Allow-Origin"头信息,允许对于站点访问。
解决跨域问题
[root@python ~]# cat Ajax_test.py
#!/usr/bin/python3
import json
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app,resources={r"/*":{"origins":"*"}})
@app.route("/users")
def users():
"""
返回用户年龄信息
"""
res = [
{"name":"root","age":18},
{"name":"admin","age":19},
{"name":"jack","age":20},
{"name":"rose","age":18},
]
return json.dumps(res,ensure_ascii=False)
if __name__ == '__main__':
app.run('0.0.0.0',5000,threaded=True)
重新启动
[root@python ~]# python3 Ajax_test.py
Traceback (most recent call last):
File "Ajax_test.py", line 5, in <module>
from flask_cors import CORS
ModuleNotFoundError: No module named 'flask_cors'
[root@python ~]# pip3 install flask_cors
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting flask_cors
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/10/69/1e6cfb87117568a9de088c32d6258219e9d1ff7c131abf74249ef2031279/Flask_Cors-4.0.0-py2.py3-none-any.whl
Requirement already satisfied: Flask>=0.9 in /usr/local/lib64/python3.6/site-packages (from flask_cors)
Requirement already satisfied: Werkzeug>=2.0 in /usr/local/lib/python3.6/site-packages (from Flask>=0.9->flask_cors)
Requirement already satisfied: Jinja2>=3.0 in /usr/local/lib/python3.6/site-packages (from Flask>=0.9->flask_cors)
Requirement already satisfied: click>=7.1.2 in /usr/local/lib/python3.6/site-packages (from Flask>=0.9->flask_cors)
Requirement already satisfied: itsdangerous>=2.0 in /usr/local/lib/python3.6/site-packages (from Flask>=0.9->flask_cors)
Requirement already satisfied: dataclasses; python_version < "3.7" in /usr/local/lib/python3.6/site-packages (from Werkzeug>=2.0->Flask>=0.9->flask_cors)
Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib64/python3.6/site-packages (from Jinja2>=3.0->Flask>=0.9->flask_cors)
Requirement already satisfied: importlib-metadata; python_version < "3.8" in /usr/local/lib/python3.6/site-packages (from click>=7.1.2->Flask>=0.9->flask_cors)
Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.6/site-packages (from importlib-metadata; python_version < "3.8"->click>=7.1.2->Flask>=0.9->flask_cors)
Requirement already satisfied: typing-extensions>=3.6.4; python_version < "3.8" in /usr/local/lib/python3.6/site-packages (from importlib-metadata; python_version < "3.8"->click>=7.1.2->Flask>=0.9->flask_cors)
Installing collected packages: flask-cors
Successfully installed flask-cors-4.0.0
[root@python ~]# python3 Ajax_test.py
* Serving Flask app 'Ajax_test' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://172.16.10.110:5000/ (Press CTRL+C to quit)
172.16.10.1 - - [27/Sep/2023 12:23:12] "GET /users HTTP/1.1" 200 -
测试