【基础知识点收集(1)】

307 阅读44分钟

【1】http和https

1、基本概念:

http是超文本传输协议,是互联网上应用最广的一种网络协议,是一个客户端和服务器端请求和相应的标准,基于tcp,用于从www服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,网络效率更高, 相应的https是以安全为目标的http通道,在http的基础上加入了ssl加密,主要作用就是保证网站的真实性

2、http和https区别

  • http的传输是未加密的,也就是明文的,https是加密的

  • https需要ca证书,花费较高,深入理解链接

  • 使用不同的链接方式,端口也不同,http一般是80端口,https是443端口

3、https过程

HTTPS要使客户端与服务器端的通信过程得到安全保证,必须使用的对称加密算法,但是协商对称加密算法的过程,需要使用非对称加密算法来保证安全,然而直接使用非对称加密的过程本身也不安全,会有中间人篡改公钥的可能性,所以客户端与服务器不直接使用公钥,而是使用数字证书签发机构颁发的证书来保证非对称加密过程本身的安全。这样通过这些机制协商出一个对称加密算法,就此双方使用该算法进行加密解密。从而解决了客户端与服务器端之间的通信安全问题

4、https工作过程

  • ssl+ca:客户用url访问服务器,请求建立ssl连接,服务器收到后,会发送自己的经过签名得CA证书以及服务器信息一起发送给浏览器,而浏览器会用自身本就携带的CA证书公钥对发来的证书进行解签,查看证书里面的信息和服务器发来的信息是否一致,如果一致,就验证成功
  • 非对称加密:然后会用把自己支持的加密方式,用公钥加密发送给服务器,服务器收到后选择一种加密方式再次发给浏览器
  • 对称加密通信:以后就会以这个加密方式来进行交换数据

5、https优缺点

  • 优点:安全,能够验证用户和服务器身份,
  • 缺点:SSL和CA证书都是需要钱的,建立连接是比价费时,会使页面加载时间延长50%,增加10%-20%耗电

【2】非对称加密与CA

1、信息安全解决的两个问题

  • client->server信息不会被截取
  • server->client保证这个就是真正的server

2、非对称加密

  • 博客
  • 对称加密的缺陷:协商使用什么密钥时候,协商过程会被发现
  • 使用非对称加密解决上述问题:协商过程使用非对称加密,因此https是集对称加密和非对称加密为一体的加密过程

3、ca

  • client拥有公钥,server拥有私钥
  • 使用SSL+CA解决client向server获取公钥时被截取的风险:数字签名,server使用私钥加密,将加密后的内容(https中,这个内容一般是公钥)和公钥(和前面的公钥不同)一起发给client,client使用公钥验证,数字签名
  • 数字签名的原理:非对称加密的两个密钥之间存在一些特殊的数学关系,使得密钥具备一些有用的特性。如果利用某人的公钥加密数据,那么只有他们对应的私钥能够解密(client->server信息不会被截取)。从另一方面讲,如果某人用私钥加密数据,任何人都可以利用对应的公钥解开消息。后面这种操作不提供机密性,但可以用作数字签名(server->client保证这个就是真正的server)。

【3】TCP和UDP

1、两者区别

  • TCP是面向连接的,UDP是面向无连接的

  • TCP提供可靠地服务,也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达,但是UDP则是尽最大努力交付,即不保证可靠交付,并且因为TCP可靠,面向连接,不丢失数据,因此适合大数据量的交换

可靠和正确的区别(可靠:收什么都是对的;正确:内容不出错,但是有可能丢失报文、报文无续等等,但是收到的报文内容都是正确的)

  • TCP是面向字节流的

  • UDP是面向报文的,并且网络出现拥塞不会使得发送速率降低(因此会出现丢包,比如通话或者视频会议)

  • TCP 是一对一的,UDP是一对一,一对多

  • TCP的首部大小为20字节,UDP只有8字节

2、TCP

2-1、请求连接
  • 第一次握手:客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入 SYN-SENT 状态。

  • 第二次握手:服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入 SYN-RECEIVED 状态。

  • 第三次握手:当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功。

这里可能大家会有个疑惑:为什么 TCP 建立连接需要三次握手,而不是两次?如果没有第三次握手,只要收到A的请求连接,服务器就会开启资源等待了,即为了防止出现失效的连接请求报文段被服务端接收的情况

2-2、释放
  • 第一次握手:若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。

  • 第二次握手:B 收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明 A 到 B 的连接已经释放,不再接收 A 发的数据了。但是因为 TCP 连接是双向的,所以 B 仍旧可以发送数据给 A。

  • 第三次握手:B 如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进入 LAST-ACK 状态。

  • 第四次握手:A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。

为什么要第四次握手?只有当B发送结束报文FIN,收到A的确认后,才算是真正的断开连接

为什么要第四次握手后等待时间为什么为RTT?要是第四次ACK丢了,第三次(B的FIN)可以在RTT时间内再次到达A,提醒A的第四次ACK丢失

3、UDP

3-1、面向无连接

首先 UDP 是不需要和 TCP一样在发送数据前进行三次握手建立连接的,想发数据就可以开始发送了。并且也只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操作。 具体来说就是:

  • 在发送端,应用层将数据传递给传输层的 UDP 协议,UDP 只会给数据增加一个 UDP 头标识下是 UDP 协议,然后就传递给网络层了
  • 在接收端,网络层将数据传递给传输层,UDP 只去除 IP 报文头就传递给应用层,不会任何拼接操作
3-2、有单播,多播,广播的功能

UDP 不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播,广播的功能。

3-3、面向报文的

发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。因此,应用程序必须选择合适大小的报文

3-4、不可靠性
  • 首先不可靠性体现在无连接上,通信都不需要建立连接,想发就发,这样的情况肯定不可靠。
  • 并且收到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。
  • 再者网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是 TCP。

【4】websocket

1、socket

1-1、什么是socket(和http协议无关):
  • 理解1:是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
  • 理解2:socket起源于Unix,unix基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
  • 理解3:标识地址,<ip,port>
1-2、socket的OS实现
  • 套接字API里有个函数socket(),它就是用来创建一个套接字,类似于文件中的open()函数,返回文件描述符
  • 虽然套接字的内部数据结构包含很多字段,但是系统创建套接字后,大多数字字段没有填写,应用程序创建套接字后在该套接字可以使用之前,必须调用其他的过程来填充这些字段。
  • 文件描述符和文件指针的区别
    • 文件描述符: 在linux系统中打开文件就会获得文件描述符,它是个很小的正整数(0,1,2对应 stdout stdin stderr,一般从3开始)。文件描述符表中的数组下标

    • 文件指针: 文件指针指向进程用户区中的一个被称为FILE结构的数据结构,文件描述符表中的内容

1-2、socket工作过程
  • 服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接
  • 在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了
  • 客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据
  • 最后关闭连接,一次交互结束

2、websocket

2-1、什么是ws

websocket是HTML5中的协议,支持持久连续,使得连接成功之后,server主动发消息给client

2-2、网络请求实现方案(ws之前):
  • http1.0,轮询:一问一答,有资源就返回资源,没有资源就返回告知信息
  • http1.1,长连接(即http1.1中keep-alive):一问一答,不过没有资源就不返回,有了资源才返回

两种方案的req和res的个数相等,而ws的应用场景是res个数>>req个数,这也是长连接和的不同

2-3、ws通信过程
  • 浏览器、服务器建立TCP连接,三次握手。这是通信的基础,传输控制层,若失败后续都不执行
  • TCP连接成功后,浏览器通过HTTP协议向服务器传送WebSocket支持的版本号等信息。(开始前的HTTP握手,主要是告知server要是用websocket这个应用层协议,而不是http)
  • 服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据。
  • 当收到了连接成功的消息后,通过TCP通道进行传输通信
2-4、ws区别于通信的核心
  • 借用了Http协议来完成一部分握手,在握手阶段与Http是相同的,header入下
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
  • 多了两个属性
Upgrade:webSocket 
Connection:Upgrade

这个就是Websocket的核心了,告诉 Apache 、 Nginx 等服务器:注意啦,我发起的是Websocket协议,快点帮我找到对应的助理处理~不是那个老土的http

【5】一个图片url访问后直接下载怎么实现

1、方式1

<a href="http://somehost/somefile.zip" download="filename.zip">Download file</a>

2、方式2:

2-1、思路:
* 用 JavaScript 创建一个隐藏的 `<a>` 标签
* 设置它的 `href` 属性
* 设置它的 `download` 属性
* 用js来触发这个它的 `click` 事件
2-2、实现
fetch('http://somehost/somefile.zip').then(res => res.blob().then(blob =>{
 
    var a = document.createElement('a');
     
    var url = window.URL.createObjectURL(blob);
     
    var filename = 'myfile.zip';
     
    a.href = url;
     
    a.download = filename;
     
    a.click();
     
    window.URL.revokeObjectURL(url);
     
}))
2-3、window.URL
  • createObjectURL 用 blob 对象来创建一个 object URL(它是一个 DOMString),我们可以用这个 object URL 来表示某个 blob 对象,这个 object URL 可以用在 href 和 src 之类的属性上。
  • revokeObjectURL 释放由 createObjectURL 创建的 object URL,当该 object URL 不需要的时候,我们要主动调用这个方法来获取最佳性能和内存使用。
  • 那么问题来了,blob 对象哪里来
2-4、blob对象
  • Blob 全称是 Binary large object,它表示一个类文件对象,可以用它来表示一个文件
  • 那我们构建 blob 的方式就是通过服务器返回的文件来创建 blob,即res.blob()

3、两种方式的比较:

3-1、什么时候使用h5:

服务器上面的静态文件的话

3-2、使用js的局限:
  • 不同浏览器实现方案有差异
  • 浪费资源

这一点限制对小文件(几十kb)可能没什么影响,但对稍微大一点的文件影响就很大了。试想,用户要下载一个 100mb 的文件,如果他点击了下载按钮之后没看到下载提示的话,他肯定会继续按,等他按了几次之后还没看到下载提示时,他就会抱怨我们的网站,然后离开了。然而事实上下载的的确确发生了,只是要等到下载完文件之后才能构建 blob 对象,再转化成文件。而且,用户再触发多几次下载就会造成一些资源上的浪费

3-3、使用js的优势:
  • 预处理(权限校验)

    • 有些时候,我们需要对下载做一些限制,最常见的就是权限校验了,如检查该用户是否有下载的权限,是否有高速下载的权限等等。这时候,我们可以利用 JavaScript 做一些预处理
    • 实现代码
      fetch('http://somehost/check-permission', options).then(res => {
      
         if (res.code === 0) {
      
             var a = document.createElement('a');
      
             var url = res.data.url;
              
             var filename = 'myfile.zip';
              
             a.href = url;
              
             a.download = filename;
              
             a.click();
          
         } else {
          
             alert('You have no permission to download the file!');
          
         }
          
      });
      
  • 动态文件,这时候我们就不能简单的指定 href 属性,因为对应的 URL 并不存在,我们只能通过js对服务器发出一个请求,通知它去生成某个文件,然后把对应的 URL 返回给客户端

【6】web quality

1、目标是易用性(accessibility)

2、举例

  • alt 属性允许为图像(也可以为其它的元素)提供一条相对应的文字
  • 实现:
<img src="images/banana.jpg" alt="Banana">
  • 有时候浏览器会无法显示图像,如使用了 alt 属性,那么浏览器至少可以显示或读出有关图像的描述

【7】BOM对象方法

1、介绍简称浏览器对象模型,主要处理浏览器窗口和框架描述了与浏览器进行交互的方法和接口,可以对浏览器窗口进行访问和操作,譬如回退历史记录,获取urL等等

image.png

2、几个主要对象 链接

2-1、window(浏览器窗口,浏览器实例,全局对象
  • name:指浏览器窗口的名字或框架的名字,这个名字是给a标记的target属性来用的
    • 设置窗口的名字:window.name='newWin'
    • 获取名字document.write(name)
  • top:代表最顶层窗口。如:window.top
  • parent:代表父级窗口,主要用于框架。
  • self:代表当前窗口,主要用于框架中。
  • alert():弹出一个警告对话框。
  • confirm(text):弹出一个确认对话框
  • text:要显示的纯文本
  • close():关闭窗口
  • print():打印窗口
  • open():打开一个新窗口
  • 延时 window.setTimeout(fun,1000),返回值是延时器的id,给clearTimeout使用
  • 定时 window.setInterval(fun,1000),返回值是定时器的id,给clearInterval使用
2-2、location
  • window.location 和document.location指向的是同一个对象

image.png

2-3、screen(显示器屏幕)
  • Width:屏幕的宽度,只读属性
  • Height:屏幕的高度,只读属性
  • availWidth:屏幕的有效宽度,不含任务栏。只读属性。
  • availHeight:屏幕的有效高度,不含任务栏。只读属性。
2-4、navigator(浏览器软件)
  • appName:浏览器软件名称,主要用来判断客户使用的是什么核心的浏览器。
    • 如果是IE浏览器的话,返回值为:Microsoft Internet Explorer
    • 如果是Firefox浏览器的话,返回值为:Netscape
  • appVersion:浏览器软件的核心版本号。
  • systemLanguage:系统语言
  • userLanguage:用户语言
  • platform:平台
2-5、history(浏览历史)
  • length:历史记录的个数,if(history.length == 0)//判断是否是新打开的页面
  • go(n):同时可以实现“前进”和“后退。”
    • history.go(0) 刷新网页
    • history.go(-1) 后退
    • history.go(1) 前进一步
    • history.go(3) 前进三步
  • forward():相当于浏览器的“前进”按钮
  • back():相当于浏览器的“后退”按钮

【8】状态码

状态码代号行为
100Continue继续。应继续其请求
101Switching Protocols切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
 
200OK请求成功。一般用于GET与POST请求
201Created已创建。成功请求并创建了新的资源
202Accepted已接受。已经接受请求,但未处理完成
203Non-Authoritative Information非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204No Content无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205Reset Content重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206Partial Content部分内容。服务器成功处理了部分GET请求
 
300Multiple Choices多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301Moved Permanently永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302Found临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303See Other查看其它地址。与301类似。使用GET和POST请求查看
304Not Modified未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305Use Proxy使用代理。所请求的资源必须通过代理访问
306Unused已经被废弃的HTTP状态码
307Temporary Redirect临时重定向。与302类似。使用GET请求重定向
 
*400Bad Request客户端请求的语法错误,服务器无法理解
*401Unauthorized请求要求用户的身份认证
402Payment Required保留,将来使用
*403Forbidden服务器理解请求客户端的请求,但是拒绝执行此请求
*404Not Found服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405Method Not Allowed客户端请求中的方法被禁止
406Not Acceptable服务器无法根据客户端请求的内容特性完成请求
407Proxy Authentication Required请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408Request Time-out服务器等待客户端发送的请求时间过长,超时
409Conflict服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突
410Gone客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411Length Required服务器无法处理客户端发送的不带Content-Length的请求信息
412Precondition Failed客户端请求信息的先决条件错误
413Request Entity Too Large由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414Request-URI Too Large请求的URI过长(URI通常为网址),服务器无法处理
415Unsupported Media Type服务器无法处理请求附带的媒体格式
416Requested range not satisfiable客户端请求的范围无效
417Expectation Failed服务器无法满足Expect的请求头信息
 
*500Internal Server Error服务器内部错误,无法完成请求
501Not Implemented服务器不支持请求的功能,无法完成请求
502Bad Gateway作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503Service Unavailable由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504Gateway Time-out充当网关或代理的服务器,未及时从远端服务器获取请求
505HTTP Version not supported服务器不支持请求的HTTP协议的版本,无法完成处理

【9】 HTTP fetch发送2次请求的原因

参考链接

1、 发送2次请求需要满足以下2个条件:

  • 必须要在跨域的情况下。
  • 除GET、HEAD和POST(only with application/x-www-form-urlencoded, multipart/form-data, text/plain Content-Type)以外的跨域请求(我们可以称为预检(Preflighted)的跨域请求),如application/json就会触发两次

post默认 application/x-www-form-urlencoded

2、总结

  • 以会发送2次请求,那是因为我们使用了带预检(Preflighted)的跨域请求。该请求会在发送真实的请求之前发送一个类型为OPTIONS的预检请求。预检请求会检测服务器是否支持我们的真实请求所需要的跨域资源,唯有资源满足条件才会发送真实的请求。
  • 我们在请求头部增加了authorization项,那么在服务器响应头中需要放入Access-Control-Allow-Headers,并且其值中必须要包含authorization,否则OPTIONS预检会失败,从而导致不会发送真实的请求

3、深入理解为什么要发预检请求

  • 都知道浏览器的同源策略,就是出于安全考虑,浏览器会限制从脚本发起的跨域HTTP请求,像XMLHttpRequest和Fetch都遵循同源策略。浏览器限制跨域请求一般有两种方式: 

    • 浏览器限制发起跨域请求 
    • 跨域请求可以正常发起,但是返回的结果被浏览器拦截了
  • 浏览器都是第二种方式限制跨域请求,那就是说请求已到达服务器,并有可能对数据库里的数据进行了操作,但是返回的结果被浏览器拦截了,那么我们就获取不到返回结果,这是一次失败的请求,但是可能对数据库里的数据产生了影响。

  • 防止这种情况的发生,规范要求,对这种可能对服务器数据产生副作用的HTTP请求方法,浏览器必须先使用OPTIONS方法发起一个预检请求,从而获知服务器是否允许该跨域请求:如果允许,就发送带数据的真实请求;如果不允许,则阻止发送带数据的真实请求。

【10】cookie、session

1、Cookie机制:

  • 如果不在浏览器中设置过期时间,cookie被保存在内存中,生命周期随浏览器的关闭而结束,这种cookie简称会话cookie
  • 如果在浏览器中设置了cookie的过期时间,cookie被保存在硬盘中,关闭浏览器后,cookie数据仍然存在,直到过期时间结束才消失。

2、Session机制:

  • 当服务器收到请求需要创建session对象时,首先会检查客户端请求中是否包含sessionid:
    • 如果有sessionid,服务器将根据该id返回对应session对象。
    • 如果客户端请求中没有sessionid,服务器会创建新的session对象,并把sessionid在本次响应中返回给客户端

    通常使用cookie方式存储sessionid到客户端,在交互中浏览器按照规则将sessionid发送给服务器。

3、应用场景:

3-1、cookie:
  • 判断用户是否登陆过网站,以便下次登录时能够实现自动登录(或者记住密码)。如果我们删除cookie,则每次登录必须重新填写登录的相关信息。
  • 保存上次登录的时间等信息。
  • 保存上次查看的页面
  • 浏览计数
3-2、session:

Session用于保存每个用户的专用信息,变量的值保存在服务器端,通过SessionID来区分不同的客户。

  • 网上商城中的购物车
  • 保存用户登录信息
  • 将某些数据放入session中,供同一用户的不同页面使用
  • 防止用户非法登录,(cookie会被人窃取)

4、cookie与session的归属

4-1、session
  • 同一机器的两个浏览器窗口访问服务器时,会生成两个不同的Session。但是由浏览器窗口内的链接、脚本等打开的新窗口(也就是说,不是双击桌面浏览器图标等打开的窗口)除外。这类子窗口会共享父窗口的Cookie,因此会共享一个Session。

新开的浏览器窗口会生成新的Session,但子窗口除外。子窗口会共用父窗口的Session。例如,在链接上右击,在弹出的快捷菜单中选择“在新窗口中打开”时,子窗口便可以访问父窗口的Session

4-2、cookie
  • 与session相同

5、URL地址重写

  • 对客户端不支持Cookie的解决方案(第二次请求时,没法使用cookie保存sessionId

  • 通过将该用户Session的id信息重写到URL地址中。服务器能够解析重写后的URL获取Session的id。这样即使客户端不支持Cookie,也可以使用Session来记录用户状态。HttpServletResponse类提供了encodeURL(Stringurl)实现URL地址重写,

  • 代码

    <a href="<%=response.encodeURL("index.jsp?c=1&wd=Java") %>"> 
    Homepage</a>
  • 该方法会自动判断客户端是否支持Cookie。如果客户端支持Cookie,会将URL原封不动地输出来。如果客户端不支持Cookie,则会将用户Session的id重写到URL中,重写后的输出可能是这样的:
    <ahref="index.jsp;jsessionid=0CCD096E7F8D97B0BE608AFDC3E1931E?c=
    1&wd=Java">Homepage</a>

【11】sessionStorage、localStorage

1、生命周期:

  • localStorage:localStorage的生命周期是永久的,关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。

  • sessionStorage的生命周期是在仅在当前会话下有效。sessionStorage引入了一个“浏览器窗口”的概念,sessionStorage是在同源的窗口中始终存在的数据。只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。但是sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面,sessionStorage也是不一样的。

2、存储大小:

  • localStorage和sessionStorage的存储数据大小一般都是:5MB

3、存储位置:

  • localStorage和sessionStorage都保存在客户端,不与服务器进行交互通信。

4、WebStorage的优点:

  • 存储空间更大:cookie为4KB,而WebStorage是5MB;
  • 节省网络流量:WebStorage不会传送到服务器,存储在本地的数据可以直接获取,也不会像cookie一样每次请求都会传送到服务器,所以减少了客户端和服务器端的交互,节省了网络流量;
  • 对于那种只需要在用户浏览一组页面期间保存而关闭浏览器后就可以丢弃的数据,sessionStorage会非常方便;
  • 快速显示:有的数据存储在WebStorage上,再加上浏览器本身的缓存。获取数据时可以从本地获取会比从服务器端获取快得多,所以速度更快;
  • 安全性:WebStorage不会随着HTTP header发送到服务器端,所以安全性相对于cookie来说比较高一些,不会担心截获,但是仍然存在伪造问题;

【12】web worker

  • webWorker允许js创造多线程环境,worker,将任务分配在后台运行。这样高延迟,密集型的任务可以由worker线程负担,主线程负责UI交互就会很流畅,不会会阻塞或拖慢
  • 对于一般js在html页面如果在执行脚本的时候,页面的状态是不可响应的,直到脚本执行完成之后,页面才变成可响应的,web worker是一个运行在后台的js,独立于其它脚本,不会影响你的页面性能,并且通过postMessage将结果传回到主线程,这样在进行复杂的操作时,就不会阻塞主线程了

1、api

  • 主线程使用new命令调用Worker()构造函数创建一个Worker线程

    • var worker = new Worker('xxxxx.js')
    • Worker构造函数接收参数为脚本文件路径
  • 主线成指定监听函数监听Worker线程的返回消息

    • worker.onmessage = function (event) {console.log(event.data)}
    • data为Worker发来的数据
  • 由于主线程与Worker线程存在通信限制,不再同一个上下文中,所以只能通过消息完成

    • worker.postMessage("hello world")
    • worker.postMessage({action: "ajax", url: "xxxxx", method: "post"})
  • 当使用完成后,如果不需要再使用可以在主线程中关闭Worker

    • worker.terminate()
    • Worker也可以关闭自身,在Worker的脚本中执行 self.close()
  • webWorker监听事件切向主线程发送消息

    self.addEventListener('message', function (e) {
      self.postMessage('You said: ' + e.data);
    }, false);
    
    //同种写法
    // 写法一
    this.addEventListener('message', function (e) {
      this.postMessage('You said: ' + e.data);
    }, false);
    
    // 写法二
    addEventListener('message', function (e) {
      postMessage('You said: ' + e.data);
    }, false);
    

2、数据通信

  • 前面说过,主线程与 Worker 之间的通信内容,可以是文本,也可以是对象。需要注意的是,这种通信是拷贝关系,即是传值而不是传址,Worker 对通信内容的修改,不会影响到主线程。事实上,浏览器内部的运行机制是,先将通信内容串行化,然后把串行化后的字符串发给 Worker,后者再将它还原。

  • 主线程与 Worker 之间也可以交换二进制数据,比如 File、Blob、ArrayBuffer 等类型,也可以在线程之间发送。下面是一个例子。

// 主线程
var uInt8Array = new Uint8Array(new ArrayBuffer(10));
for (var i = 0; i < uInt8Array.length; ++i) {
  uInt8Array[i] = i * 2; // [0, 2, 4, 6, 8,...]
}
worker.postMessage(uInt8Array);

// Worker 线程
self.onmessage = function (e) {
  var uInt8Array = e.data;
  postMessage('Inside worker.js: uInt8Array.toString() = ' + uInt8Array.toString());
  postMessage('Inside worker.js: uInt8Array.byteLength = ' + uInt8Array.byteLength);
};
  • 但是,拷贝方式发送二进制数据,会造成性能问题。比如,主线程向 Worker 发送一个 500MB 文件,默认情况下浏览器会生成一个原文件的拷贝。为了解决这个问题,js允许主线程把二进制数据直接转移给子线程,但是一旦转移,主线程就无法再使用这些二进制数据了,这是为了防止出现多个线程同时修改数据的麻烦局面。这种转移数据的方法,叫做Transferable Objects。这使得主线程可以快速把数据交给 Worker,对于影像处理、声音处理、3D 运算等就非常方便了,不会产生性能负担。如果要直接转移数据的控制权,就要使用下面的写法。

     // Transferable Objects 格式
     worker.postMessage(arrayBuffer, [arrayBuffer]);
    
     // 例子
     var ab = new ArrayBuffer(1);
     worker.postMessage(ab, [ab]);
    

3、同页面的 Web Worker

  • 通常情况下,Worker 载入的是一个单独的js脚本文件,但是也可以载入与主线程在同一个网页的代码。
<!DOCTYPE html>
  <body>
    <script id="worker" type="app/worker">
      addEventListener('message', function () {
        postMessage('some message');
      }, false);
    </script>
  </body>
</html>
  • 上面是一段嵌入网页的脚本,注意必须指定<script>标签的type属性是一个浏览器不认识的值,上例是app/worker。然后,读取这一段嵌入页面的脚本,用 Worker 来处理。
var blob = new Blob([document.querySelector('#worker').textContent]);
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);

worker.onmessage = function (e) {
  // e.data === 'some message'
};
  • 上面代码中,先将嵌入网页的脚本代码,转成一个二进制对象,然后为这个二进制对象生成 URL,再让 Worker 加载这个 URL。这样就做到了,主线程和 Worker 的代码都在同一个网页上面

【13】浏览器解析渲染html文档的过程

1、参考链接

2、自己的理解

2-1、脚本
  • web的模式是同步的,开发者希望解析到一个script标签时立即解析执行脚本,并阻塞文档的解析直到脚本执行完。如果脚本是外引的,则网络必须先请求到这个资源——这个过程也是同步的,会阻塞文档的解析直到资源被请求到。
  • 这个模式保持了很多年,并且在html4及html5中都特别指定了。开发者可以将脚本标识为defer,以使其不阻塞文档解析,并在文档解析结束后执行。Html5增加了标记脚本为异步的选项,以使脚本的解析执行使用另一个线程。
2-2、预解析 Speculative parsing
  • Webkit和Firefox都做了这个优化,当执行脚本时,另一个线程解析剩下的文档,并加载后面需要通过网络加载的资源。
  • 这种方式可以使资源并行加载从而使整体速度更快。需要注意的是,预解析并不改变Dom树,它将这个工作留给主解析过程,自己只解析外部资源的引用,比如外部脚本、样式表及图片。
2-3、样式表 Style sheets
  • 样式表采用另一种不同的模式。理论上,既然样式表不改变Dom树,也就没有必要停下文档的解析等待它们。
  • 然而,脚本可能在文档的解析过程中请求样式信息,如果样式还没有加载和解析,脚本将得到错误的值,显然这将会导致很多问题,这看起来是个边缘情况,但确实很常见。
  • Firefox在存在样式表还在加载和解析时阻塞所有的脚本,而chrome只在当脚本试图访问某些可能被未加载的样式表所影响的特定的样式属性时才阻塞这些脚本。
2-4、dom树被阻塞的条件
  • HTML的响应流被阻塞在了网络中
  • 有未加载完的脚本(执行在阻塞之后,执行都会阻塞dom树了,何况加载
  • 遇到了script节点(还没有开始执行,只是碰到节点而已),但是此时还有未加载完的样式文件
2-5、阻塞总结
  • css如果在js之前,会阻塞js的执行(而不是阻塞js的加载),从而阻塞DOM tree构建,要想不阻塞DOM tree构建,需要将js在body底部或者使用defer
  • html解析的过程中遇到script时,如果是嵌入脚本,会执行并阻塞dom tree构建,如果是外链JS脚本,则会进行加载后执行,并阻塞dom tree构建(但是在执行之前浏览器都会渲染出页面来)

因为浏览器不知道脚本的内容,因而碰到脚本时,只好先渲染页面(之前已经解析部分页面),确保脚本能获取到最新的DOM元素信息,尽管脚本可能不需要这些信息

  • 但不管怎样,由于浏览器的预解析优化,会新开一个线程加载后续资源。并且,为了确保js能拿到最新的DOM元素信息和CSSOM信息,js执行前会等待css加载完毕并渲染页面

【14】、浏览器性能优化方案

JS的加载和执行会阻塞浏览器渲染,所以目前业界普遍推荐把script放到</body>之前,以解决js执行时找不到dom等问题。但随着现代浏览器的普及,浏览器为我们提供了更多强大的武器,合理利用,方可大幅提高页面加载速度。

1、理解渲染过程(HTML Parser)

  • 首先我们从浏览器的角度解释一下从输入URL到页面展示经历了些什么,以如下html文档举例
<html>
<head>
    <link rel="stylesheet" type="text/css" href="/style.css">
    <script type="text/javascript" src="/header.js"></script>
</head>
<body>
  <p>Text</p>
  <script type="text/javascript" src="/main.js"></script>
</body>
</html>
  • 浏览器自上而下读取html文档(此过程叫html parser),当发现style.css文件时,浏览器parser停下来去搞css,等style.css下载并解析完毕,浏览器继续parser。紧接着发现header.js, 于是html parser又停了,浏览器下载并执行完header.js,继续parser。此时屏幕上还什么都没有。

  • ...parser,发现<p>,遂将p中文字展示了出来。紧接着又发现main.js,浏览器又停下parser,下载并执行完main.js才继续parser,直到页面渲染完毕。

  • 我们假设header.js中只有一行代码console.log('header'), 但服务器响应很慢,要10秒才能把它返回给浏览器,浏览器执行这段代码需要1ms,那在这 10s+1ms 内,页面将一直空白。浏览器执行JS的时间取决于代码质量和硬件,并不是前端工程师随便可以优化的,所以优化的重点在JS的下载时间。

2、核心:减少JS下载时间

2-1、预先解析DNS
  • 非常简单,效果立竿见影,加快页面加载时间,多用于预解析CDN的地址的DNS
<!--在head标签中,越早越好-->
<link rel="dns-prefetch" href="//example.com">
2-2、Preload
  • 浏览器会在遇到如下link标签时,立刻开始下载main.js(不阻塞parser),并放在内存中,但不会执行其中的JS语句。
  • 只有当遇到script标签加载的也是main.js的时候,浏览器才会直接将预先加载的JS执行掉。
<link rel="preload" href="/main.js" as="script">
2-3、Prefetch
  • 浏览器会在空闲的时候,下载main.js, 并缓存到disk。当有页面使用的时候,直接从disk缓存中读取。其实就是把决定是否和什么时间加载这个资源的决定权交给浏览器。

  • 如果prefetch还没下载完之前,浏览器发现script标签也引用了同样的资源,浏览器会再次发起请求,这样会严重影响性能的,加载了两次,所以不要在当前页面(即,尽量在不同的页面中使用)马上就要用的资源上用prefetch,要用preload。

<link href="main.js" rel="prefetch">

preload如加载到一半,就遇到script标签时,会等待加载完成,在执行,与prefetch不同

3、JS在什么时候执行的(defer和async)

  • 上面我们的例子中,script标签都是在没有多余属性的情况下执行的,只要下载过程结束,浏览器就会将JS执行掉。

  • defer和async是script标签的两个属性,用于在不阻塞页面文档解析的前提下,控制脚本的下载和执行。

  • 具体看这张图。

  • 两者的不同

    • defer的执行时间是在所有元素解析完成之后,DOMContentLoaded 事件触发之前。

    • async的执行时间是在当前JS脚本下载完成后,所以多个async script是执行顺序是不固定的。所以async只能用于加载一些独立无依赖的代码,比如Google Analysis之类。

4、完美的结构

  • 前面两节帮我们弄懂了JS的下载和执行时机,那什么样的页面才是完美符合现代浏览器的那?其实关键在于的preload和prefetch!提前告知浏览器,我们的网站马上要用的是什么,以后可能要用的是什么,浏览器才能更快的渲染页面。下面是一段实例代码
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Faster</title>
  <link rel="dns-prefetch" href="//cdn.com/">
  <link rel="preload" href="//js.cdn.com/currentPage-part1.js" as="script">
  <link rel="preload" href="//js.cdn.com/currentPage-part2.js" as="script">
  <link rel="preload" href="//js.cdn.com/currentPage-part3.js" as="script">

  <link rel="prefetch" href="//js.cdn.com/prefetch.js">
</head>
<body>

<script type="text/javascript" src="//js.cdn.com/currentPage-part1.js" defer></script>
<script type="text/javascript" src="//js.cdn.com/currentPage-part2.js" defer></script>
<script type="text/javascript" src="//js.cdn.com/currentPage-part3.js" defer></script>
</body>
</html>
  • 首先,Parser在遇到head中preload时开始下载JS,读到script标签的时候,如果已经下载完了,直接按顺序执行之。如果没下载完,会等到下载完再执行,这样就刚进入页面就开始非阻塞的下载JS了。

  • 其次,页面会在空闲时,加载prefetch的JS,如果之后页面发生跳转,跳转的目标页面引入了prefetch.js,浏览器会直接从disk缓存中读取执行。

  • 将script标签依然放在</body>之前,并增加defer标签,确保老浏览器兼容,并在所有DOM元素解析完成之后执行其中的代码。

【14】在地址栏里输入一个URL,到这个页面呈现出来,中间会发生什么?

  • 首先说一下url的构造,url是统一资源定位符,它由协议,域名,端口,路径,携带的参数,定位的片段组成,因此当输入一个url以后,会首先根据域名找到相应的ip地址,这个有一个查询的顺序
    • 首先会在浏览器缓存中找
    • 然后是路由器缓存
    • 如果都没有,去本地的hosts文件中找是否有
    • 如果也没有去DNS域名服务器中找,通过迭代或者递归的方法找到对应的IP地址
  • 然后通过IP地址以及端口号封装成一个http请求,http请求会包含请求的方法,请求所携带的数据或者参数,然后在传输层将http封装成一个tcp报文段,然后在网络层添加头部标识封装成IP数据报,然后数据链路层加上头部拆分成一个个数据帧(网卡),然后在物理层转化成电信号发送到服务器
  • 然后通过一层层的解析,解析出这个http请求,然后返回一个HTML文件
  • 接收到这个HTML文件后,浏览器会构建一个树结构,首先是构造dom树,在构造dom树的时候如果遇到js或者引入的外部js,会停止构建进行解析,这也就是为什么js一般引入在页面的最后(或者一些其他的优化方案)
  • 当dom树构建完后,会根据一定的优先级,外部样式小于内部样式小于内联样式,去构建CSS对象模型树,然后和dom树一起形成渲染树
  • 之后进行布局,布局主要是确定各个元素的位置和尺寸
  • 之后是渲染页面,因为html文件中会含有图片,视频,音频等资源,在解析DOM的过程中,遇到这些都会进行并行下载

【15】iframe是什么?有什么优缺点?

1、优点

  • iframe能够原封不动的把嵌入的网页展现出来。
  • 如果有多个网页引用iframe,那么你只需要修改iframe的内容,就可以实现调用的每一个页面内容的更改,方便快捷。
  • 网页如果为了统一风格,头部和版本都是一样的,就可以写成一个页面,用iframe来嵌套,可以增加代码的可重用。
  • 如果遇到加载缓慢的第三方内容如图标和广告,这些问题可以由iframe来解决。

2、缺点

  • iframe会阻塞主页面的onload事件;
  • iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。,会产生很多页面,不容易管理。
  • iframe框架结构有时会让人感到迷惑,如果框架个数多的话,可能会出现上下、左右滚动条,会分散访问者的注意力,用户体验度差。
  • 代码复杂,无法被一些搜索引擎索引到,这一点很关键,现在的搜索引擎爬虫还不能很好的处理iframe中的内容,所以使用iframe会不利于搜索引擎优化(SEO)。
  • 很多的移动设备无法完全显示框架,设备兼容性差。
  • iframe框架页面会增加服务器的http请求,对于大型网站是不可取的。

3、优化

  • 如果需要使用iframe,最好是通过js动态给iframe添加src属性值,这样可以绕开以上一些问题

【16】doctype 严格模式和混杂模式

  • 声明在最前面,告诉浏览器以何种方式渲染页面,有两种模式,严格模式和混杂模式

    • 严格模式下的排版和JS运作模式是以该浏览器支持的最高标准执行

    • 混杂模式,向后兼容,模拟老式浏览器,防止浏览器无法兼容页面

【17】CDN

1、概念

  • 使用CDN会极大地简化网站的系统维护工作量,网站维护人员只需将网站内容注入CDN的系统,通过CDN部署在各个物理位置的服务器进行全网分发,就可以实现跨运营商、跨地域的用户覆盖。由于CDN将内容推送到网络边缘,大量的用户访问被分散在网络边缘,不再构成网站出口、互联互通点的资源挤占,也不再需要跨越长距离IP路由了
  • CDN的全称是 Content Delivery Network,即内容分发网络。CDN 是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN 的关键技术主要有内容存储和分发技术。

2、传统DNS

  • 用户通过浏览器等方式访问网站的过程如图1-2所示。

①用户在自己的浏览器中输入要访问的网站域名。

②浏览器向本地DNS服务器请求对该域名的解析。

③本地DNS服务器中如果缓存有这个域名的解析结果,则直接响应用户的解析请求。

④本地DNS服务器中如果没有关于这个域名的解析结果的缓存,则以递归方式向整个DNS系统请求解析,获得应答后将结果反馈给浏览器。

⑤浏览器得到域名解析结果,就是该域名相应的服务设备的IP地址。

⑥浏览器向服务器请求内容。

⑦服务器将用户请求内容传送给浏览器。

3、CDN

在网站和用户之间加入CDN以后,用户不会有任何与原来不同的感觉。最简单的CDN网络有一个DNS服务器和几台缓存服务器就可以运行了。一个典型的CDN用户访问调度流程如图1-3所示。

3-1、工作过程

①当用户点击网站页面上的内容URL,经过本地DNS系统解析,DNS系统会最终将域名的解析权交给CNAME指向的CDN专用DNS服务器

②CDN的DNS服务器将CDN的全局负载均衡设备IP地址返回用户。

③用户向CDN的全局负载均衡设备发起内容URL访问请求。

④CDN全局负载均衡设备根据用户IP地址,以及用户请求的内容URL,选择一台用户所属区域的区域负载均衡设备,告诉用户向这台设备发起请求。

⑤区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务,选择的依据包括:根据用户IP地址,判断哪一台服务器距用户最近;根据用户所请求的URL中携带的内容名称,判断哪一台服务器上有用户所需内容;查询各个服务器当前的负载情况,判断哪一台服务器尚有服务能力。基于以上这些条件的综合分析之后,区域负载均衡设备会向全局负载均衡设备返回一台缓存服务器的IP地址

⑥全局负载均衡设备把服务器的IP地址返回给用户。

⑦用户向缓存服务器发起请求,缓存服务器响应用户请求,将用户所需内容传送到用户终端。如果这台缓存服务器上并没有用户想要的内容,而区域均衡设备依然将它分配给了用户,那么这台服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉到本地。

3-2、总结
  • DNS服务器根据用户IP地址,将域名解析成相应节点的缓存服务器IP地址,实现用户就近访问。使用CDN服务的网站,只需将其域名解析权交给CDN的GSLB设备,将需要分发的内容注入CDN,就可以实现内容加速了
  • 优势
    • CDN 节点解决了跨运营商和跨地域访问的问题,访问延时大大降低;
    • 大部分请求在 CDN 边缘节点完成,CDN 起到了分流作用,减轻了源站的负载
  • 静态资源本身具有访问频率高、承接流量大的特点,因此静态资源加载速度始终是前端性能的一个非常关键的指标。CDN 是静态资源提速的重要手段

【18】介绍知道的http返回的状态码

200 OK 请求成功。一般用于GET与POST请求

201 Created 已创建。成功请求并创建了新的资源,

204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档,比如fetch的post操作一般会有两次,第一次是询问服务器是否支持携带请求头,第二次才发送真正的请求

301 Moved Permanently 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。

302 Found 请求的资源现在临时从不同的URI响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。

301是永久重定向,而302是临时重定向

305 Use Proxy 使用代理。所请求的资源必须通过代理访问

400 Bad Request 客户端请求的语法错误,服务器无法理解,json的格式错误等等

401 Unauthorized 请求要求用户的身份认证

403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求

410 Gone 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置

500 Internal Server Error 服务器内部错误,无法完成请求

501 Not Implemented 服务器不支持请求的功能,无法完成请求

503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中

505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理

【19】301 302

字面上的区别就是301是永久重定向,而302是临时重定向。 当然,他们之间也是有共同点的,就是用户都可以看到url替换为了一个新的,然后发出请求

1、301 Moved Permanently

被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。

比如,我们访问 http://www.baidu.com 会跳转到 https://www.baidu.com,发送请求之后,就会返回301状态码,然后返回一个location,提示新的地址,浏览器就会拿着这个新的地址去访问

2、302 Found

请求的资源现在临时从不同的URI响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求

比如未登陆的用户访问用户中心重定向到登录页面;访问404页面会重新定向到首页

3、两者的不同

  • 301是永久重定向,而302是临时重定向
  • 301比较常用的场景是使用域名跳转。302用来做临时跳转 比如未登陆的用户访问用户中心重定向到登录页面
  • 搜索引擎
    • 302搜索搜索引擎认为新的网址是暂时的。
    • 而301重定向是永久的重定向,搜索引擎在抓取新的内容的同时也将旧的网址替换为了重定向之后的网址

【20】post与put

1、总结

  • PUT是幂等的,POST是非幂等的

幂等:对于相同的输入,每次得到的结果都是相等的,如 min(a,b){return a>b?b:a;}

2、我们经常在创建对象时用POST,更新对象时用PUT,为什么呢?

  • POST用于提交请求,可以更新或者创建资源,是非幂等的

    • 比如新建一个备忘录便签条,点几次新建就会新建几张空白的便签,这时就用POST,(对于每次的提交结果不一定相同)
  • PUT用于向指定的URI传送更新资源,是幂等的

    • 对便签1输入计划ABCD,得到一张更新的便签表,不管更新几次都一样,仍然是那张便签,得到的内容也一样,这时就用PUT

3、其他理解

  • POST: 请求服务器接受所指定的文档作为对所标识的URI的新的从属实体(add)

  • PUT: 从客户端向服务器传送的数据取代指定的文档的内容(update)

  • 本质上来讲, PUT和POST极为相似,都是向服务器发送数据,但它们之间有一个重要区别,PUT通常指定了资源的存放位置,而POST则没有POST的数据存放位置由服务器自己决定。举个例子:如一个用于提交博文的URL,/addBlog。如果用PUT,则提交的URL会是像这样的”/addBlog/abc123”,其中abc123就是这个博文的地址。而如果用POST,则这个地址会在提交后由服务器告知客户端。目前大部分博客都是这样的。显然,PUT和POST用途是不一样的。具体用哪个还取决于当前的业务场景

网不好的时候,post提交后没收到响应,于是客户端再次尝试提交,成功后刷新看到新建了两条资源,如果用put的话就不会出现这样的情况。所以尽量使用put去代替post