摘要:本文將會(huì)詳細(xì)的介紹瀏覽器實(shí)現(xiàn)緩存控制的相關(guān)知識(shí),包括cookie、session、localStorage、Cache-Control、Expires、ETag、Last-Modified等概念。
注:在看本文之前建議可以先看一下網(wǎng)頁(yè)中的登錄注冊(cè)功能是如何實(shí)現(xiàn)的,對(duì)前端和后端的數(shù)據(jù)交互有個(gè)大概的了解。
1、cookie是什么 && cookie能干什么
- 給cookie一個(gè)定義吧:
Cookie(復(fù)數(shù)形態(tài)Cookies),中文名稱為“小型文本文件”或“小甜餅”。指某些網(wǎng)站為了辨別用戶身份而儲(chǔ)存在用戶本地終端(Client Side)上的數(shù)據(jù)(通常經(jīng)過加密)。 ——摘自維基。
-
如何通俗的解釋:
- Cookie 是瀏覽器訪問服務(wù)器后,服務(wù)器傳給瀏覽器的一段數(shù)據(jù)。
- 瀏覽器需要保存這段數(shù)據(jù),不得輕易刪除。
- 此后每次瀏覽器訪問該服務(wù)器,都必須帶上這段數(shù)據(jù)。
-
所以就能得出cookie的特點(diǎn):
- 服務(wù)器通過設(shè)置
Set-Cookie響應(yīng)頭來(lái)設(shè)置 cookie - 瀏覽器得到 cookie 后,每次同源的請(qǐng)求的請(qǐng)求頭都會(huì)帶上 cookie
- 服務(wù)器讀取 cookie 就知道了登錄用戶的信息(如賬戶名等)
- cookie 實(shí)際上存儲(chǔ)在本地計(jì)算機(jī)的硬盤里
- cookie 的最大儲(chǔ)存量一般只有4K
- 服務(wù)器通過設(shè)置
-
那么cookie有哪些缺點(diǎn)呢:
- Cookie很容易被用戶篡改( Session 可以解決這個(gè)問題,防止用戶篡改)
- Cookie 的默認(rèn)有效期理論上在用戶關(guān)閉頁(yè)面后就失效,實(shí)際上在在20分鐘左右,不同瀏覽器策略不同。但是后端可以強(qiáng)制設(shè)置有效期(如何設(shè)置見下文)。
- Cookie 也有一定的同源策略,不過跟 AJAX 的同源策略稍微有些不同。如:
- 當(dāng)請(qǐng)求 qq.com 下的資源時(shí),瀏覽器會(huì)默認(rèn)帶上 qq.com 對(duì)應(yīng)的 Cookie,不會(huì)帶上 baidu.com 對(duì)應(yīng)的 Cookie
- 當(dāng)請(qǐng)求 v.qq.com 下的資源時(shí),瀏覽器不僅會(huì)帶上 v.qq.com 的Cookie,還會(huì)帶上 qq.com 的 Cookie
- 另外 Cookie 還可以根據(jù)路徑做限制,請(qǐng)自行了解,這個(gè)功能用得比較少。
-
有了Cookie,我們就可以實(shí)現(xiàn)這兩件事 :
第一個(gè)作用是識(shí)別用戶身份。如:
比如用戶 A 用瀏覽器訪問了http://a.com,那么http://a.com 的服務(wù)器就會(huì)立刻給 A 返回一段數(shù)據(jù)「uid=1」(這就是 Cookie)。當(dāng) A 再次訪問 http://a.com的其他頁(yè)面時(shí),就會(huì)附帶上「uid=1」這段數(shù)據(jù)。這樣服務(wù)端就知道 A 是誰(shuí)了。第二個(gè)作用是記錄歷史。如:
假設(shè) http://a.com 是一個(gè)購(gòu)物網(wǎng)站,當(dāng) A 在上面將商品 B1 、B2 加入購(gòu)物車時(shí),JS 可以改寫 Cookie,改為「uid=1; cart=B1,B2」,表示購(gòu)物車?yán)镉?B1 和 B2 兩樣商品了。這樣一來(lái),當(dāng)用戶關(guān)閉網(wǎng)頁(yè),過三天再打開網(wǎng)頁(yè)的時(shí)候,依然可以看到 B1 、B2躺在購(gòu)物車?yán)?,因?yàn)闉g覽器并不會(huì)無(wú)緣無(wú)故地刪除這個(gè) Cookie。(需要注意的是:上面的例子只是為了讓大家了解 Cookie 的作用而構(gòu)想出來(lái)的,實(shí)際的網(wǎng)站使用 Cookie 時(shí)會(huì)更謹(jǐn)慎一些。為什么要非常謹(jǐn)慎的使用cookie請(qǐng)從下文尋找答案。)
-
那么我們?nèi)绾卧O(shè)置cookie呢:
其實(shí)只要一句話:在響應(yīng)頭中設(shè)置Set-Cookie即可,詳見Set-Cookie MDN 。具體參數(shù)如下:-
Set-Cookie: <cookie-name>=<cookie-value>
普通的cookie,所有參數(shù)默認(rèn) -
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
cookie 的最長(zhǎng)有效時(shí)間,形式為符合 HTTP-date 規(guī)范的時(shí)間戳。 -
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
在 cookie 失效之前需要經(jīng)過的秒數(shù)。一位或多位非零(1-9)數(shù)字。假如二者 (指 Expires 和Max-Age) 均存在,那么 Max-Age 優(yōu)先級(jí)更高。 -
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
指定 cookie 可以送達(dá)的主機(jī)名。假如沒有指定,那么默認(rèn)值為當(dāng)前文檔訪問地址中的主機(jī)部分(但是不包含子域名)。與之前的規(guī)范不同的是,域名之前的點(diǎn)號(hào)會(huì)被忽略。假如指定了域名,那么相當(dāng)于各個(gè)子域名也包含在內(nèi)了。 -
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
指定一個(gè) URL 路徑,這個(gè)路徑必須出現(xiàn)在要請(qǐng)求的資源的路徑中才可以發(fā)送 Cookie 首部。 -
Set-Cookie: <cookie-name>=<cookie-value>; Secure
一個(gè)帶有安全屬性的 cookie 只有在請(qǐng)求使用SSL和HTTPS協(xié)議的時(shí)候才會(huì)被發(fā)送到服務(wù)器。(注意:非安全站點(diǎn)(http:)已經(jīng)不能再在 cookie 中設(shè)置 secure 指令了) -
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
設(shè)置了 HttpOnly 屬性的 cookie 不能使用 JavaScript 經(jīng)由Document.cookie屬性、XMLHttpRequest和RequestAPIs 進(jìn)行訪問,以防范跨站腳本攻擊(XSS)。 Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict-
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
上面兩個(gè)允許服務(wù)器設(shè)定一則 cookie 不隨著跨域請(qǐng)求一起發(fā)送,這樣可以在一定程度上防范跨站請(qǐng)求偽造攻擊(CSRF)。
-
-
如何刪除cookie
通過設(shè)置cookie的有效期在當(dāng)前時(shí)間之前,就可以刪除cookie啦var delete_cookie = function(name) { document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:01 GMT;'; }; -
cookie 的
HttpOnly屬性
為避免跨域腳本 (XSS)攻擊,通過JavaScript的Document.cookieAPI無(wú)法訪問帶有HttpOnly標(biāo)記的Cookie,它們只應(yīng)該發(fā)送給服務(wù)端。如果包含服務(wù)端 Session 信息的 Cookie 不想被客戶端 JavaScript 腳本調(diào)用,那么就應(yīng)該為其設(shè)置HttpOnly標(biāo)記。Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
2、使用session保存信息
- 先舉個(gè)例子看如何使用session
之前的寫法:直接將數(shù)據(jù)放到cookie里面:
這樣寫一來(lái)會(huì)暴露用戶的個(gè)人信息,二來(lái)用戶可以直接通過瀏覽器修改cookie,極有可能獲取到別人的用戶信息,極不安全。因此出現(xiàn)了下面的使用session的操作:response.setHeader('Set-Cookie', `login_email=${email}`)
首先來(lái)解釋一下上面的代碼:即設(shè)置let sessions = {} let sessionId = Math.random() * 10000 // 設(shè)置sessionId 為一個(gè)隨機(jī)數(shù) sessions[sessionId] = {login_email:email} // 將email 存儲(chǔ)在sessions這個(gè)對(duì)象中 response.setHeader('Set-Cookie', `sessionId = ${sessionId}`) // cookie中存儲(chǔ)的是 sessionId 這個(gè)隨機(jī)數(shù)cookie的中存儲(chǔ)的值為一個(gè)隨機(jī)數(shù),當(dāng)后臺(tái)獲取到cookie時(shí),就可以獲取到該隨機(jī)數(shù)并在sessions這個(gè)對(duì)象中查找key為這個(gè)隨機(jī)數(shù)的value,即可知道用戶的郵箱是什么 。如圖所示,此時(shí)的響應(yīng)頭是這樣的:

-
那么究竟如何定義session呢:
首先我們得知道session的本質(zhì):就是存儲(chǔ)在服務(wù)器上的一個(gè)哈希表。- 將sessionID(隨機(jī)數(shù)) 通過 Cookie 發(fā)給客戶端
- 客戶端訪問服務(wù)器時(shí),服務(wù)器讀取 sessionID
- 服務(wù)器有一塊內(nèi)存(哈希表)保存了所有 session
- 通過sessionID 后臺(tái)可以得到對(duì)應(yīng)用戶的隱私信息,如 id,email
- 這塊內(nèi)存(哈希表)就是服務(wù)器上的所有 session
那么session相對(duì)于cookie就沒有缺點(diǎn)了嗎?
很明顯,答案是否定的。session最大的缺點(diǎn)就是占內(nèi)存,如果你的用戶量非常大,服務(wù)器就需要足夠的容量來(lái)存儲(chǔ)數(shù)據(jù)。-
不基于cookie能否實(shí)現(xiàn)session呢
答案是肯定的,可以通過設(shè)置網(wǎng)址的查詢參數(shù) + localStorage 來(lái)達(dá)成目的。具體過程如下:- 后端待用戶登陸后設(shè)置他的sessionID,但不把它放在 cookie 里,而是將信息通過響應(yīng)體傳JSON給前端。
- 前端拿到響應(yīng)體中的JSON后將其轉(zhuǎn)換成對(duì)象(
JSON.parse) - 將從JSON中獲取到的數(shù)據(jù)(如 sessionID)放在 localStorage 里面(localStorage里的數(shù)據(jù)目前暫時(shí)用不到)
- 以后跳轉(zhuǎn)到其他頁(yè)面(如首頁(yè))時(shí),將 sessionID 放在 URL 的查詢參數(shù)里(如:
window.location.href = '/?sessionId=object.sessionId') - 那么進(jìn)入首頁(yè)后,該頁(yè)面的 URL 的查詢參數(shù)就帶上了你的sessionID
- 后端通過在用戶訪問首頁(yè)時(shí),傳到服務(wù)器的 URL ,來(lái)獲取到查詢參數(shù),從而獲取到用戶的 sessionID,然后在數(shù)據(jù)庫(kù)中查到sessionID對(duì)應(yīng)的信息就可以知道用戶是誰(shuí)。
3、localStorage是什么 & localStorage 怎么用
localStorage 是HTML5 技術(shù)提供的api ,是window對(duì)象下的一個(gè)方法(window.localStorage)。
localStorage 的實(shí)質(zhì)是一個(gè)存儲(chǔ)在計(jì)算機(jī)本地的哈希表。
-
localStorage常用的api
-
localStorage.setItem('myCat', 'Tom')
訪問當(dāng)前域名下的本地Storage對(duì)象,并增加了一個(gè)數(shù)據(jù)項(xiàng)通過使用Storage.setItem()作為 Storage 接口的方法,接受一個(gè)鍵名和值作為參數(shù),將會(huì)把鍵名添加到存儲(chǔ)中,如果鍵名已存在,則更新其對(duì)應(yīng)的值。 -
let cat = localStorage.getItem('myCat')
該語(yǔ)法用于讀取 localStorage 項(xiàng) -
localStorage.removeItem('myCat')
該語(yǔ)法用于移除 localStorage 項(xiàng) -
localStorage.clear()
該語(yǔ)法用于移除所有的 localStorage 項(xiàng)
-
需要注意的是:localStorage 只能存 string,所以如果想存Object,就需要用JSON來(lái)存,舉個(gè)例子:
localStorage.setItem('jsonObj',JSON.stringify({name:'obj'}))
然后如果想要解析這個(gè) JSON 將其轉(zhuǎn)換成對(duì)象可以使用JSON.parse()-
那么localStorage怎么使用呢:
- 首先我們需要知道JS中的變量有這樣的問題:變量只在當(dāng)前的會(huì)話期內(nèi)有效。即只要刷新頁(yè)面,之前存儲(chǔ)的變量就被回收了。那么我們?nèi)绾巫屩八鎯?chǔ)的變量在刷新頁(yè)面之后還存在呢,所以就有了localStorage 來(lái)解決這個(gè)需求。
- 來(lái)看一個(gè)小demo,這個(gè)demo通過使用 localStorage 完成了變量的持久化存儲(chǔ),因?yàn)閘ocalStorage實(shí)際上是存儲(chǔ)在本地計(jì)算機(jī)中的,不會(huì)因?yàn)轫?yè)面刷新就導(dǎo)致變量被回收。
let a = localStorage.getItem('a') if(!a){ a = 0 }esle{ a = parseInt(a,10) + 1 // 如果不進(jìn)行轉(zhuǎn)換,將會(huì)變成字符串的相加 } console.log(a) localStorage.setItem('a',a) // 每次刷新頁(yè)面 ,a 的值都會(huì)加 1 - 常見的使用情景:用戶第一次進(jìn)入頁(yè)面時(shí)提示用戶一些信息,第二次進(jìn)入以后就不再提示。 示例代碼如下:
let already = localStorage.getItem('isPrompt') if(!already){ alert('我們的頁(yè)面改版啦') localStorage.setItem('isPrompt', true) }esle{ // 已經(jīng)提示了就什么也不做 }
-
localStorage的特點(diǎn)
- localStorage 與 HTTP 無(wú)關(guān)
- HTTP 不會(huì)帶上 localStorage 的值
- 只有相同域名的頁(yè)面才能互相讀取 localStorage(遵循同源策略)
- 每個(gè)域名 localStorage 最大存儲(chǔ)量為 5Mb 左右(每個(gè)瀏覽器不一樣)
- 常用場(chǎng)景:記錄有沒有提示過用戶(記錄一些不敏感的信息)
- localStorage 理論上永久有效,除非用戶清理緩存,無(wú)法設(shè)置過期時(shí)間
-
sessionStorage 和 localStorage 有什么關(guān)系和區(qū)別
- 上一條記錄的 localStorage 的特點(diǎn),1~4條二者都有。
- 區(qū)別:sessionStorage 在用戶關(guān)閉頁(yè)面后(即 session 結(jié)束后或者說會(huì)話結(jié)束后)就失效,而且沒辦法控制;而 localStorage 理論上永久有效。
- sessionStorage 的 api 和 localStorage 完全一樣。如
setItem()、getItem()、remove()、clear()
4、關(guān)于上面的概念需要注意的事情
cookie 和 session 有什么關(guān)系:
答:一般來(lái)說 cookie 是基于 session 實(shí)現(xiàn)的。cookie是存在客戶端本地的,而session是保存在服務(wù)器上的。cookie 和 localStorage 的區(qū)別是什么
答:cookie 每次請(qǐng)求會(huì)被帶給服務(wù)器,而 localStorage不會(huì);cookie的最大儲(chǔ)存量一般只有4k,而localStorage 一般有5Mb ;cookie的有效期一般在用戶關(guān)閉頁(yè)面后就失效,而localStorage理論上永久有效。可能你就要問了,看起來(lái)cookie 和 localStorage 幾乎沒有關(guān)系,為什么要放在一起比較?
這是由歷史原因的:localStorage 是新API,在它出現(xiàn)以前,之前的前端如何實(shí)現(xiàn)跨頁(yè)面的數(shù)據(jù)持久化存儲(chǔ)呢?只能通過cookie ,要知道cookie 和 localStorage 都是存放在計(jì)算機(jī)本地,所以當(dāng)時(shí)很多程序員都把數(shù)據(jù)放在cookie里,但是有個(gè)問題,你所有存在 cookie里面的東西,每次請(qǐng)求都會(huì)帶到服務(wù)器里面去,如果cookie里面放的東西太多,那么每次請(qǐng)求就要花費(fèi)更多的時(shí)間。所以要達(dá)到跨頁(yè)面的數(shù)據(jù)持久化存儲(chǔ),最優(yōu)解就是使用 localStorage。前端永遠(yuǎn)不要讀或者寫cookie,讀寫cookie一系列的操作是后端需要完成的工作。(這里的前后端指的是代碼上的分離而不是人員上的分離)
5、HTTP緩存 & Cache-Control 緩存控制
需要提一句的是:緩存控制其實(shí)也是前端性能優(yōu)化的一部分,所以這一點(diǎn)其實(shí)很值得關(guān)注。
緩存控制的使用場(chǎng)景:一些網(wǎng)站需要加載的資源很多,導(dǎo)致每次刷新頁(yè)面速度都非常都慢,那么該如何加快請(qǐng)求速度,緩存控制就應(yīng)運(yùn)而生。
Cache-Control 通用消息頭被用于在http 請(qǐng)求和響應(yīng)中通過指定指令來(lái)實(shí)現(xiàn)緩存機(jī)制。緩存指令是單向的, 這意味著在請(qǐng)求設(shè)置的指令,在響應(yīng)中不一定包含相同的指令。
最常用的響應(yīng)指令:Cache-Control: max-age=<seconds> :
- 設(shè)置緩存存儲(chǔ)的最大周期,超過這個(gè)時(shí)間緩存被認(rèn)為過期(單位秒)。與Expires相反,時(shí)間是相對(duì)于請(qǐng)求的時(shí)間。即在設(shè)置的時(shí)間內(nèi),請(qǐng)求相同的URL將不會(huì)把請(qǐng)求發(fā)送到服務(wù)器,瀏覽器會(huì)阻斷這個(gè)請(qǐng)求(即這個(gè)請(qǐng)求實(shí)際并沒有發(fā)送出去),然后然后之間展示緩存過的上一次的數(shù)據(jù)(存儲(chǔ)在本地的硬盤或內(nèi)存)。實(shí)際開發(fā)中,我們一般設(shè)置為一年31536000秒以上。
- 需要注意的是:一般首頁(yè)(甚至包括所有的html頁(yè)面)不應(yīng)該設(shè)置緩存(chrome瀏覽器甚至?xí)苯咏眠@個(gè)設(shè)置,也就是說你給首頁(yè)設(shè)置Cache-Control也不會(huì)生效)。因?yàn)槿绻氵B首頁(yè)都設(shè)置了緩存,用戶即使刷新頁(yè)面,也不會(huì)向服務(wù)器發(fā)送任何請(qǐng)求,那么如果你的代碼更新了,用戶在緩存期間將始終無(wú)法獲取到最新的版本。
- 實(shí)際開發(fā)中的使用:html頁(yè)面不設(shè)置Cache-Control,其他資源Cache-Control設(shè)置一年以上,如果代碼更新(比如js或css),該資源的請(qǐng)求的url的查詢參數(shù)加上一個(gè)版本號(hào),或者文件名后加隨機(jī)數(shù)即可。也就是說,只要你的請(qǐng)求的url有一點(diǎn)點(diǎn)不一樣,就不會(huì)使用緩存
6、Expires 是什么 & 有什么不好的地方
Expires 也是用來(lái)控制緩存的,但是現(xiàn)在在開發(fā)中,優(yōu)先使用Cache-Control。
Expires 響應(yīng)頭包含日期/時(shí)間, 即在此時(shí)候之后,緩存過期。如何使用Expires呢:
設(shè)置響應(yīng)頭,如:Expires:"Wed, 22 Aug 2018 07:43:17 GMT"
后面接的是格林尼治時(shí)間。當(dāng)過了設(shè)置的時(shí)間后緩存就過期了。所以
Expires與Cache-Control的區(qū)別就是:前者設(shè)置的是什么時(shí)候過期,后者設(shè)置的是過了多久過期。需要注意的是:如果在
Cache-Control響應(yīng)頭設(shè)置了 "max-age" 或者 "s-max-age" 指令,那么Expires頭會(huì)被忽略。那么為什么 Cache-Control 優(yōu)先級(jí)比Expire 高呢?因?yàn)?Cache-Control 相對(duì)于 Expires 是個(gè)更新的技術(shù), 而且使用 Expires 是存在bug 的。
Expires 的bug:時(shí)間使用的是計(jì)算機(jī)本地的時(shí)間,如果某一天計(jì)算機(jī)時(shí)間錯(cuò)亂,本地時(shí)間一直在你設(shè)置的時(shí)間之后,那么他就永遠(yuǎn)使用不了緩存。
7、ETag 是什么 & MD5 是什么
首先,Etag 是用來(lái)給文件一個(gè)版本號(hào)的。
那么我們先來(lái)了解一下MD5 。MD5是一個(gè)消息摘要算法。MD5 的常見使用場(chǎng)景:你在網(wǎng)上下載一個(gè)很大的文件,下載過程中你怎么知道自己下載的對(duì)不對(duì)呢?所以MD5 就是為了這種情景而生的。即網(wǎng)上的文件除了有資源本身外,還會(huì)有一個(gè)MD5值,然后你下載到本地后的文件也可以算出一個(gè)MD5 值,然后二者對(duì)比,如果完全相同則說明下的文件是正確的。
Etag 的使用場(chǎng)景:
- 后端算出資源的MD5值,將其設(shè)置到響應(yīng)頭的Etag里,如:
Etag:"33a64df551425fcc55e4d42a148795d9f25f89d4" - 然后下一次請(qǐng)求時(shí),里面這個(gè)資源的請(qǐng)求頭就多了一個(gè)值:
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4" - 后端就有如下設(shè)置:
如果請(qǐng)求頭的If-None-Match中的值和資源的MD5一樣,說明資源是最新的,不需要下載,即可以返回304狀態(tài)碼( Not Modified),然后在此分支下就不用設(shè)置響應(yīng)體了。 - 如果MD5的值不一樣,說明你的資源需要更新,此時(shí)再返回最新的資源作為響應(yīng)體。
Etag 與 Cache-Control 的區(qū)別:
- Cache-Control 直接不會(huì)發(fā)請(qǐng)求,只要url一樣,直接使用緩存了的數(shù)據(jù)
- Etag 則每一次都會(huì)請(qǐng)求,只不過如果資源的MD5一樣,就不下載
8、Last-Modified 是什么 & 使用過程是怎么樣的
Last-Modified 是一個(gè)響應(yīng)首部,其中包含源頭服務(wù)器認(rèn)定的資源做出修改的日期及時(shí)間。 它通常被用作一個(gè)驗(yàn)證器來(lái)判斷接收到的或者存儲(chǔ)的資源是否彼此一致。由于精確度比 ETag 要低,所以這是一個(gè)備用機(jī)制。包含有 If-Modified-Since 或 If-Unmodified-Since首部的條件請(qǐng)求會(huì)使用這個(gè)字段。
使用過程:
- 在瀏覽器第一次請(qǐng)求某一個(gè)URL時(shí),服務(wù)器端的返回狀態(tài)會(huì)是200,內(nèi)容是你請(qǐng)求的資源,同時(shí)有一個(gè)Last-Modified的屬性標(biāo)記在響應(yīng)頭里,此文件在服務(wù)期端最后被修改的時(shí)間,格式類似這樣:
Last-Modified:Tue, 24 Feb 2009 08:01:04 GMT - 客戶端第二次請(qǐng)求此URL時(shí),根據(jù)HTTP協(xié)議的規(guī)定,瀏覽器會(huì)向服務(wù)器傳送If-Modified-Since請(qǐng)求頭,詢問該時(shí)間之后文件是否有被修改過:
If-Modified-Since:Tue, 24 Feb 2009 08:01:04 GMT - 如果服務(wù)器端的資源沒有變化,則自動(dòng)返回HTTP 304(NotChanged.)狀態(tài)碼,內(nèi)容為空,這樣就節(jié)省了傳輸數(shù)據(jù)量。當(dāng)服務(wù)器端代碼發(fā)生改變或者重啟服務(wù)器時(shí),則重新發(fā)出資源,返回和第一次請(qǐng)求時(shí)類似。從而保證不向客戶端重復(fù)發(fā)出資源,也保證當(dāng)服務(wù)器有變化時(shí),客戶端能夠得到最新的資源。
(END)