目录
HTTP协议
HTTP协议简介
HTTP (全称为 “超文本传输协议”) 是一种应用非常广泛的 应用层协议.
所谓 “超文本” 的含义, 就是传输的内容不仅仅是文本(比如 html, css 这个就是文本), 还可以是一些其他的资源, 比如图片, 视频, 音频等二进制的数据
HTTP往往是基于传输层的TCP协议实现的,目前我们主要使用的是HTTP1.1和HTTP2.0
像我们平时打开一个网站,就是同各国HTTP协议来传输数据的
当我们在输入框中输入一个搜狗搜索的网址(URL)时,浏览器就会给搜狗的服务器发送一个HTTP请求,搜狗的服务器返回一个HTTP响应
这个响应结果被浏览器解析之后, 就展示成我们看到的页面内容. (这个过程中浏览器可能会给服务器发送多个 HTTP 请求, 服务器会对应返回多个响应, 这些响应里就包含了页面 HTML, CSS, JavaScript, 图片, 字体等信息).
理解应用层协议
我们已经学过 TCP/IP , 已经知道目前数据能从客户端进程经过路径选择跨网络传送到服务器端进程[ IP+Port ].
可是,仅仅把数据从A点传送到B点就完了吗?
应用层则是决定,拿到数据后用来做什么,对于不同的应用程序来说,拿到的数据起到的作用也是不同的,例如QQ,拿到的应用层数据就是用来消息传递,对于淘宝来说,应用层数据主要用来展示商品信息和下单等。
HTTP协议的工作过程
HTTP协议是一问一答模式的协议,就是客户端向服务器端发送一个请求,服务器端向客户端返回一个响应,请求和响应之间是一一对应的
事实上, 当我们访问一个网站的时候, 可能涉及不止一次的 HTTP 请求/响应 的交互过程.
可以通过 chrome 的开发者工具观察到这个详细的过程.
通过 F12 打开 chrome 的开发者工具, 切换到 Network 标签页. 然后刷新页面即可看到如下图效果. 每一条记录都是一次 HTTP 请求/响应
【注意】: 当前 搜狗主页 是通过 https 来进行通信的. https 是在 http 基础之上做了一个加密解密的工作, 后面再介绍.
【补充】:客户端和服务器之间的通信模式
- 一问一答:请求和响应一一对应
- 多问一答:N个请求,对应一个响应,例如上传文件
- 一问多答:一个请求,对应N个响应,例如下载文件> + 多问多答:N个请求,对应N个响应,例如游戏串流
HTTP协议格式
对于学习HTTP协议的格式,需要用到Fiddler这个抓包工具
通过抓包工具就能获取到一个HTTP请求/响应的详细的数据内容
Fiddler的简介
抓包工具相当于是一个"代理",同样Fiddler也就属于是"代理"
浏览器访问 sogou.com 时, 就会把 HTTP 请求先发给 Fiddler, Fiddler 再把请求转发给 sogou 的服务器. 当 sogou 服务器返回数据时, Fiddler 拿到返回数据, 再把数据交给浏览器.
因此 Fiddler 对于浏览器和 sogou 服务器之间交互的数据细节, 都是非常清楚的
Fiddler的使用
(1)HTTP请求列表
(2)双击左侧HTTP请求后,右侧出现该HTTP请求的详细内容
(3)通过记事本查看请求/响应的详细内容
我们通过记事本打开后发现,HTTP协议和TCP/UDP/IP这些协议的组织格式是不同的,HTTP是用文本格式来组织数据的,而TCP/UCP/IP是以二进制的方式来组织的,如果用记事本打开,里面是一堆乱码
但当我们用记事本打开一个请求的数据时,发现有乱码,这是为什么呢?
这是因为响应数据可能会比较长,会被压缩,通过压缩,就可以节省带宽
(4)对响应数据进行解压缩
HTTP请求格式概述
首先抓到一个HTTP请求
HTTP请求由4部分组成
首行:[方法]+[url]+[版本号]
Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
空行
空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度;(GET请求的Body一般为空,此处抓到的请求中Body为空)
HTTP响应格式概述
HTTP响应由4部分构成
首行: [版本号] + [状态码] + [状态码解释]
Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
空行
Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面,
那么html页面内容就是在body中.
补充:HTTP报文中空行的作用
因为 HTTP 协议并没有规定报头部分的键值对有多少个. 空行就相当于是 “报头的结束标记”, 或者是 “报头和正文之间的分隔符”.
HTTP 在传输层依赖 TCP 协议, TCP 是面向字节流的. 如果没有这个空行, 就会出现 “粘包问题”.
协议格式概括图
HTTP请求格式详解
URL
平时我们俗称的 “网址” 其实就是说的 URL (Uniform Resource Locator 统一资源定位符).互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
URL 的详细规则由 因特网标准RFC1738进行了约定
【URL的格式】
分析一个具体的URL
- https : 协议方案名. 常见的有 http 和 https, 也有其他的类型. (例如访问 mysql 时用的jdbc:mysql )
- user:pass : 登陆信息. 现在的网站进行身份认证一般不再通过 URL 进行了. 一般都会省略
- www.miguvideo.com:服务器地址. 此处是一个 “域名”, 域名会通过 DNS 系统解析成一个具体的 IP 地址.
- 端口号: 上面的 URL 中端口号被省略了. 当端口号省略的时候, 浏览器会根据协议类型自动决定使用哪个端口. 例如 http 协议默认使用 80 端口, https 协议默认使用 443 端口.
- /mgs/website/prd/sportLive.html: 带层次的文件路径.
- mgdbId=120000266875:查询字符串(query string). 本质是一个键值对结构. 键值对之间使用 & 分隔. 键和值之间使用 = 分隔
- 片段标识: 此 URL 中省略了片段标识. 片段标识主要用于页面内跳转
【使用ping命令查看域名对应的IP地址】
例如查看搜狗搜索域名对应的IP地址
【关于query string】
query string 中的内容是键值对结构. 其中的 key 和 value 的取值和个数, 完全都是程序猿自己约定的. 我们可以通过这样的方式来自定制传输我们需要的信息给服务器.
【URL中可省略的部分】
- 协议名: 可以省略, 省略后默认为 http://
- ip 地址 / 域名: 在 HTML 中可以省略(比如 img, link, script, a 标签的 src 或者 href 属性). 省略后表示服务器的 ip / 域名与当前 HTML 所属的 ip / 域名一致.
- 端口号: 可以省略. 省略后如果是 http 协议, 端口号自动设为 80; 如果是 https 协议, 端口号自动设为 443.
- 带层次的文件路径: 代表访问的是服务器上的哪个资源,可以省略. 省略后相当于 / 有些服务器会在发现 / 路径的时候自动访问/index.html
- 查询字符串: 可以省略,请求发给服务器时带上的参数,?作为查询字符串的起始标志
- 片段标识: 可以省略,现在有些"文档类"网站是有的,起到页面内跳转的效果 ,定位到一网页的某个章节
- 通过IP地址确定主机,通过端口号确定对应的应用程序,通过文件路径确定要访问的应用程序中的某个资源
【关于URL encode】
像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.
一个中文字符由 UTF-8 或者 GBK 这样的编码方式构成, 虽然在 URL 中没有特殊含义, 但是仍然需要进行转义. 否则浏览器可能把UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号.
转义的规则如下: 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式
例如:
urlencode操作是非常有必要的,如果查询字符串中带有了特殊符号,很容易导致浏览器对url解析失败,可能导致无法跳转到对应的页面
urldecode就是urlencode的逆过程;
方法
【注意】:方法名区分大小写,注意要用大写字母
【GET方法】
GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源,也可使用GET请求让服务器型新增/删除/修改一个数据(完全取决于代码的写法).
在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求.
另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求,使用 JavaScript 中的 ajax 也能构造 GET 请求.
【通过Fidder抓到一个GET请求】
GET请求的特点:
- 首行的第一部分为 GET
- URL 的 query string 可以为空, 也可以不为空. query string的长度是没有限制的
- header 部分有若干个键值对结构.
- body 部分通常为空.
【POST方法】
POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面),但实际开发中也完全可以使用post来获取/删除/新增某个数据
通过 HTML 中的 form 标签可以构造POST 请求, 或者使用 JavaScript 的 ajax 也可以构造 POST 请求.
【通过Fidder抓到一个POST请求】
POST请求的特点:
- 首行的第一部分为POST
- URL的query string 一般为空(也可以不为空)
- header 部分有若干个键值对结构
- body 部分一般不为空,body 内的数据格式通过header中的Content-Type指定,body的长度由header中的Content-Length指定
【补充】:
浏览器在和服务器交互的时候,总是需要提交一些数据给服务器,关于数据的相关信息可以放到query string 中,也可以放到body中
query string中是固定的键值对格式 body中则可以使用更多的格式来组织
【面试题:谈谈GET和POST的区别】
- 二者没有本质的区别(本质区别是指彼此之间不能相互替代),GET和POST之间则是可以相互替代的,但在使用习惯上还是存在区别的
- GET 一般用于获取数据, POST 一般用于提交数据.
- GET主要通过query string传递数据,POST主要通过body传递数据
- GET 请求一般是幂等的, POST 请求一般是不幂等的. (如果多次请求得到的结果一样, 就视为请求是幂等的).
- GET一般可以被缓存(可以放到收藏夹),POST一般不能被缓存(不能放到收藏夹),这一点也是承接的幂等性
【补充】
- GET 完全可以用于提交数据, POST 也完全可以用于获取数据
- 标准建议 GET 实现为幂等的. 实际开发中 GET 也不必完全遵守这个规则(主流网站都有 “猜你喜欢” 功能, 会根据用户的历史行为实时更新现有的结果.
- 关于安全性: 有些资料上说 “POST 比 GET 请安全”. 这样的说法是不科学的. 是否安全取决于前端在传输密码等敏感信息时是否进行加密, 和 GET POST 无关.
- 关于传输数据量: 有的资料上说 “GET 传输的数据量小, POST 传输数据量大”. 这个也是不科学的, 标准没有规定 GET 的 URL 的长度, 也没有规定 POST 的 body 的长度. 传输数据量多少, 完全取决于不同浏览器和不同服务器之间的实现区别.
- 关于传输数据类型: 有的资料上说 “GET 只能传输文本数据, POST 可以传输二进制数据”. 这个也是不科学的. GET 的 query string 虽然无法直接传输二进制数据, 但是可以针对二进制数据进行 url encode.
【其他方法】
- PUT 与 POST 相似,只是具有幂等特性,一般用于更新
- DELETE 删除服务器指定资源
- OPTIONS 返回服务器所支持的请求方法
- HEAD 类似于GET,只不过响应体不返回,只返回响应头
- TRACE 回显服务器端收到的请求,测试的时候会用到这个
- CONNECT 预留,暂无使用
这些方法的HTTP请求都可以使用ajax来构造,或postman等第三方工具
任何一个能进行网络编程的语言都可以构造HTTP请求.本质上就是通过TCP socket写入一个符合HTTP协议规则的字符串
请求报头
header 的整体的格式也是 “键值对” 结构.
每个键值对占一行. 键和值之间使用分号分割.报头的种类有很多
【Host】:表示服务器主机的地址和端口.
【Content-Length】:表示 body 中的数据长度.
由于HTTP协议是基于TCP实现的协议,因此需要明确数据报和数据报之间的边界,否则就会出现"粘包"问题,当HTTP报文带有body的时候就需要明确指出body的结束位置
【Content-Type】:表示请求的 body 中的数据格式.
请求中常见的body的数据格式:
- application/x-www-form-urlencoded: form 表单提交的数据格式. 此时 body 的格式形如:
title=test&content=hello
- application/json: 数据为 json 格式. body 格式形如:
{"username":"15846232645","password":"mVBZFYhzUA5ZVndr9lggpw==","uuid":"5a4f303bddb147e39aabadf2819f1a33","status":0}
- multipart/form-data: form 表单提交的数据格式,在 form 标签中加上
enctyped=“multipart/form-data” . 通常用于提交图片/文件. body 格式形如:
Content-Type:multipart/form-data; boundary=----
WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
【User-Agent】:表示浏览器/操作系统的属性
UA这个属性,现在已经不太关键了,但在20年前这个属性是很重要的,主要是因为,在过去20年中浏览器飞速发展,使得同一时间段内,市面上的浏览器种类繁多,可能有的浏览器是能播放视频的,而有的浏览器却只能显示文字,因此开发网站的程序员为了解决这个问题,在HTTP请求包头中添加个这个属性,使得浏览器在访问网站的时候,告诉服务器浏览器自身是什么样的客户端(能支持什么功能),服务器就会根据浏览器的能力分别做处理。
由于现代的浏览器的差距已经很小了,现在UA起到的作用主要是用来区分请求时来自于PC还是移动端
【Referer】:表示这个页面是从哪个页面跳转过来的.
如果直接在浏览器中输入URL, 或者直接通过收藏夹访问页面时是没有 Referer 的.
例如:
- 我们直接在浏览器中输入sogou网页的URL,在抓到的请求包中是没有Referer的
- 当我们在搜狗搜索中进行搜索的时候,抓到的请求中就是带有Referer的
Referer能起到什么样的实际作用呢?
在我们日常进行搜索时,总是会到"广告"的字样
每当我们点击一次带有"广告"的链接,广告主都要向搜狗付费,因为这相当于是搜狗为其引流了,那么问题来了,如何记录该广告被点击了多少次呢?就是通过Referer
对于搜狗来说,每次点击都会跳转到搜狗的计费服务器
对于广告主来说,它通过自己网站的日志来查看哪些请求的Referer是来自于搜狗的
【Cookie】:浏览器在本地存储数据的一种机制
Cookie 中存储了一个字符串, 这个数据可能是客户端(网页)自行通过 JS 写入的, 也可能来自于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据). 往往可以通过这个字段实现 “身份标识” 的功能.
每个不同的域名下都可以有不同的 Cookie, 不同网站之间的 Cookie 并不冲突.
有些网站,如果想要访问需要进行登录, 登录的过程就是在进行身份认证,按理说,当我们登录成功后,就能顺畅使用网站的剩余功能了,不能说出现登录成功后,过一个会还要让我们登录的情况,Cookie机制就能避免这种重复登录的情况发生
浏览器为了保证用户的安全,针对页面上的代码做出了很多的限制,其中的一个限制就是禁止浏览器页面的代码访问本地磁盘
但我们又想在浏览器中持久化的保存一些信息,就需要访问本地磁盘,因此浏览器决定放开一点限制,允许在磁盘中存储少量的数据,但页面的代码还是不能访问磁盘的其他文件,同时存储的数据也只能是一些简单键值对,于是Cookie机制就产生了
从图中我们能观察到,不同的域名有不同的Cookie
Cookie中存储的是一些键值对,名称作为key,内容作为value
这些Cookie内容都是存储在硬盘上的,只不过页面代码不能直接任意的访问硬盘,而是只能存储和修改cookie这样的简单键值对
cookie 中的内容是从哪来的呢?
从服务器来,网站上主要的数据仍然是存储在服务器上,数据也是从服务器写回个浏览器的
cookie中的内容又要到哪里去呢?
传回给服务器,例如网站通过登录之后,明确了用户的身份信息,就把身份标识返回给了浏览器,浏览器再次访问服务器,就会带着身份标识,服务器通过身份标识就能够认出是哪个用户发来的请求了
【通过抓包观察Cookie所起到的作用】:以登录gitee为例
(1)清除之前的 cookie
(2)输入账号密码进行登录
请求:第一次登录时,触发的请求中是没有Cookie字段的
响应:第一次登录收到的响应中存在Set-Cookie的这样的键值对,Set-Cookie的效果就是服务器给客户端些Cookie
里面包含了一个 gitee-session-n 这样的属性, 属性值是一串很长的加
密之后的信息. 这个信息就是用户当前登陆的身份标识. 也称为 “令牌(token)”
(3)访问其他页面
登录成功之后,此时通过抓包发现在访问码云的其他页面(例如个人主页时),请求中就会带着刚才获取到的Cookie信息
请求你中的 Cookie 字段也包含了一个 gitee-session-n 属性, 里面的值和刚才服务器返回的值相同.
下一次的请求中带上的Cookie是上一次请求返回的响应中设置的Cookie
每次请求收到的响应都可能设置Cookie,用于下一次的请求
【举例理解登录过程】
这个过程和去医院看病很相似.
- 到了医院先挂号. 挂号时候需要提供身份证, 同时得到了一张 “就诊卡”, 这个就诊卡就相当于 患者的 “令牌”.
- 后续去各个科室进行检查, 诊断, 开药等操作, 都不必再出示身份证了, 只要凭就诊卡即可识别 出当前患者的身份.
- 看完病了之后, 不想要就诊卡了, 就可以注销这个卡. 此时患者的身份和就诊卡的关联就销毁 了. (类似于网站的注销操作)
- 又来看病, 可以办一张新的就诊卡, 此时就得到了一个新的 “令牌”
请求正文(body)
和报头中的Content-Type和Content-Length相关
(1) application/x-www-form-urlencoded
(2)multipart/form-data
(3)application/json
HTTP响应格式详解
状态码
状态码表示访问一个页面的结果
【200 OK】:这是最常见的一个状态码,表示访问成功
【404 Not Found】:表示没有找到资源
浏览器输入一个 URL, 目的就是为了访问对方服务器上的一个资源. 如果这个 URL 标识的资源不存在, 那么就会出现 404
例如, 在浏览器中输入 www.sogou.com/index.html , 此时就在尝试访问 sogou 上的/index.html
这个资源. 如果输入正确, 则可以正确访问到. 但是如果输入错误, 比如www.sogou.com/index2.html , 就会看到404 这样的响应.
【403 Forbidden】:表示访问被拒绝,有的页面通常需要用户具有一定的权限才能访问(登陆后才能访问),如果用户没有登录直接访问,就可能出现403
例如: 查看码云的私有仓库, 如果不登陆, 就会出现 403.
【405 Method Not Alllowed】:表示要请求的服务器不支持该请求中的方法
【500 Internal Server Error】:服务器内部出现错误, 一般是服务器的代码执行过程中遇到了一些特殊情况(服务器异常崩溃)会产生这个状态码.
【504 Gateway Timeout】:当服务器负载比较大的时候, 服务器处理单条请求的时候消耗的时间就会很长, 就可能会导致出现超时的情况.
【302 Move temporarily】:临时重定向
举例理解重定向,相当于手机号码中的 “呼叫转移” 功能
比如我本来的手机号是 188-888-888, 后来换了个新号码 199-999-999 那么不需要让我的朋友知道新号码, 只要我去办理一个呼叫转移业务, 其他人拨打 186-1234-5678 , 就会自动转移到 199-999-999 上.
在登陆页面中经常会见到 302. 用于实现登陆成功后自动跳转到主页.
响应报文的 header 部分会包含一个 Location 字段, 表示要跳转到哪个页面
例如,码云的登录页面
可以看到 header 中的 Location: https://gitee.com/, 接下来浏览器就会自动发送GET 请求, 获取 https://gitee.com/
【301 Moved Permanently】:永久重定向,当浏览器收到这种响应时, 后续的请求都会被自动改成新的地址. 301 也是通过 Location 字段来表示要重定向到的新地址.
响应报头
响应报头的基本格式和请求报头的格式基本一致.
类似于 Content-Type , Content-Length 等属性的含义也和请求中的含义一致.
【Content-Type】:响应中的Content-Type常见取值
- text/html : body 数据格式是 HTML
- text/css : body 数据格式是 CSS
- application/javascript : body 数据格式是 JavaScript
- application/json : body 数据格式是 JSON
(1)text/html
(2)text/css
(3)application/javascript
(4)application/json
【补充】:
在响应的Content-Type中,可能还会包含字符编码,下面这个响应就指定字符编码为utf8,表示对响应中body部分的数据采用utf8进行编码
响应正文(body)
正文的具体格式取决于 Content-Type. 具体内容可观察上面关于Content-Type的抓包结果
构造HTTP请求
form表单构造HTTP请求
form (表单) 是 HTML 中的一个常用标签. 可以用于给服务器发送 GET 或者 POST 请求.
【form 标签的参数介绍】
- action:构造的HTTP请求的URL
- method:构造的HTTP请求的方法GET或POST
【input标签的参数介绍】
- type:表示输入框的类型,text表示文本,password表示密码,submit表示提交按钮
- name:表示构造出的HTTP请求的query string的key,query string的value 就是输入框的用户输入的内容
- value:inpu标签的值,对于type为submit类型来说,value就对应了按钮上显示的文本
- 构造代码
<!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>
</head>
<body>
<form action="https://www.sogou.com/index.html" method="get">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
- 页面展示效果
- 在输入框中填入数据后,点击提交,就会发送请求
4. 抓到请求包
- form 的 action 属性对应 HTTP 请求的 URL
- form 的 method 属性对应 HTTP 请求的方法
- input 的 name 属性对应 query string 的 key
- input 的 内容 对应 query string 的 value
同理还可以使用form构造post请求,流程完全类似
区别在于,method从GET变成POST,数据从query string移动到了body中
同时还可以使用form提交文件,后面servlet中有介绍
【补充】:数据放在query string中好还是放在body中好?
放在body中更好,因为如果放在query string 中,账号和密码就会暴漏在浏览器的地址栏中
这也就是为什么登录大部分是基于post请求实现的原因
通过ajax构造HTTP请求
ajax 全称 Asynchronous Javascript And XML, 是 2005 年提出的一种 JavaScript 给服务器发送HTTP 请求的方式.
从前端角度, 除了浏览器地址栏能构造 GET 请求, form 表单能构造 GET 和 POST 之外, 还可以通过 ajax 的方式来构造 HTTP 请求. 并且功能更强大 特点是可以不需要 刷新页面/页面跳转 就能进行数据传输
ajax是浏览器提供给JS提供的一个和服务器交互数据的机制,浏览器就提供了一组原生的API(XMLRequest),但这个原生的API 用起来很不方便,因此,有很多js的第三方库,针对ajax进行了封装,其中最典型的第三方库就是jQuery
【jQuery构造ajax请求的核心函数】
$.ajax();
$ 是一个变量名,是jQuery中的一个特殊对象,jQuery里面提供的各种API都是以 $ 对象的方法的方式来体现的
该方法的参数是一个js对象,使用js对象作为参数的好处,参数是自解释的,同时参数的顺序没有限制
【构造一个GET请求】
下面构造的ajax请求使用的都是jQuery中封装好的ajax
因此在编写代码之前需要先引入jQuery
$.ajax({
type:'GET', //请求的方法(支持各种HTTP的方法,GET,POST,PUT,DELETE...)
url:'https://www.baidu.com', //请求的url
success:function(body){
//参数body表示HTTP响应的正文部分,该函数是一个回调函数
//在浏览器收到服务器的数据之后,才执行这个回调函数
//ajax的"异步"特性,就是回调函数所体现的
//发送请求的程序员,只管发送,不必主动的获取结果,等到收到结果
//浏览器就会触发回调函数
console.log(body);
}
});
运行结果:
这个错误是因为 ajax 默认不能 “跨域”,当前的HTML的"域名"是一个本地路径,ajax访问的请求是百度的服务器,这种做法默认是不允许的,浏览器为了保证网络的安全,禁止ajax的跨域访问
如果想要强行进行跨域, 则需要服务器进行配合, 在服务器的响应中 “允许跨域” 才可以,但对于百度的服务器来说,肯定不会鸟我们
在后面学习Tomcat的时候,我们可以自己搭建一个服务器来使用
注意:
通过ajax发送get请求的代码要写到jQuery的下面,要保证先加载jQuery,然后才能编写jQuery相关的代码