成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

后端知識(shí)點(diǎn)總結(jié)——NODE.JS(高級(jí))

bovenson / 2098人閱讀

摘要:階段是事件循環(huán)的第一階段習(xí)慣上往往都會(huì)設(shè)置數(shù)將回調(diào)函數(shù)添加到事件循環(huán)的階段的隊(duì)列中等待執(zhí)行。

后端知識(shí)點(diǎn)總結(jié)——NODE.JS(高級(jí)) 1.Node入門:

什么是: 針對(duì)網(wǎng)絡(luò)應(yīng)用開發(fā)的平臺(tái)
主要特征:

基于Google的JavaScript運(yùn)行時(shí)引擎V8

擴(kuò)展了Node標(biāo)準(zhǔn)類庫: TCP,同步或異步文件管理,HTTP

為什么使用Node:

可以在服務(wù)器端運(yùn)行js: 現(xiàn)有前端團(tuán)隊(duì)可直接參與后端js開發(fā)

js天生支持非阻塞IO:
IO: 代表一切數(shù)據(jù)進(jìn)出程序的操作:
包括: 文件讀寫, 數(shù)據(jù)庫操作, 網(wǎng)絡(luò)操作
問題: 有延遲
傳統(tǒng)阻塞IO: IO操作會(huì)阻塞當(dāng)前主線程,直到本次IO操作完成,才能執(zhí)行后續(xù)代碼。
非阻塞IO: 即使處理較慢的IO操作時(shí),主進(jìn)城仍然能處理其他請(qǐng)求
Js天生支持非阻塞: 回調(diào)函數(shù)=事件循環(huán)+回調(diào)隊(duì)列
所有非阻塞的操作,返回的結(jié)果暫時(shí)在回調(diào)隊(duì)列中等待
由事件循環(huán),自動(dòng)依次取回到主程序中恢復(fù)執(zhí)行
回調(diào)隊(duì)列在主程序之外存儲(chǔ)回調(diào)函數(shù),所以,不會(huì)干擾主程序執(zhí)行
非阻塞在Web服務(wù)器中:
普通服務(wù)器端應(yīng)用: 雖然可實(shí)現(xiàn)每個(gè)請(qǐng)求獨(dú)立線程/進(jìn)程, 但如果一個(gè)請(qǐng)求中,包含多個(gè)阻塞IO操作(訪問數(shù)據(jù)庫,網(wǎng)絡(luò),讀寫硬盤文件),該請(qǐng)求返回的時(shí)間就等于所有IO操作的時(shí)間總和——慢
Node服務(wù)器端應(yīng)用: 不但每個(gè)請(qǐng)求是一個(gè)獨(dú)立的線程,且,每個(gè)請(qǐng)求內(nèi)的每個(gè)IO操作,都是非阻塞的。

一個(gè)包含多個(gè)IO操作的請(qǐng)求,返回的總響應(yīng)時(shí)間,僅僅等于其中一個(gè)時(shí)間最長的IO操作的時(shí)間。
Node.js vs javascript: 
Javascript: 編程語言, 依照ECMAScript

2種運(yùn)行環(huán)境:

客戶端瀏覽器: 由各種客戶端瀏覽器中的js解釋器執(zhí)行
擴(kuò)展: DOM API 和 BOM API 主要目的是為了操作網(wǎng)頁內(nèi)容和瀏覽器窗口

獨(dú)立的js解釋器:Node.js 應(yīng)用程序開發(fā)和運(yùn)行的平臺(tái)
僅支持ECMAScript
擴(kuò)展: 各種專門的服務(wù)器模塊: TCP, HTTP, 文件讀寫, MYSQL

構(gòu)建一個(gè)簡單的node應(yīng)用:
創(chuàng)建一個(gè)新的node項(xiàng)目: 基本命令:
mkdir 項(xiàng)目文件夾
cd 項(xiàng)目文件夾
npm init //負(fù)責(zé)在當(dāng)前所在的項(xiàng)目目錄下自動(dòng)生成package.json配置文件
運(yùn)行:node 入口文件.js

2.module

Node應(yīng)用都是由模塊組成
模塊就是組織程序功能的一種文件或文件夾
Node應(yīng)用采用CommonJS模塊規(guī)范
CommonJS規(guī)定:

每個(gè)文件就是一個(gè)模塊,有自己的作用域——避免全局污染
一個(gè)文件內(nèi)定義的變量,函數(shù),類都是該文件私有,對(duì)其它文件默認(rèn)不可見

對(duì)象,方法和變量也可以從一個(gè)文件/模塊中導(dǎo)出(exports),用在其它文件/模塊中。

實(shí)際項(xiàng)目中,都是將各種功能/數(shù)據(jù),劃分為不同項(xiàng)目模塊來管理
如何定義一個(gè)模塊:2步:

在模塊/文件中定義業(yè)務(wù)代碼(對(duì)象,class,函數(shù))

將內(nèi)部的功能拋出,用于將來其它js文件調(diào)用

2種情況:

2.1面向?qū)ο蟮姆绞?

定義一種class或一個(gè)對(duì)象,包裹屬性和功能

將class或?qū)ο笾苯淤x值給module.exports
其中: module,指當(dāng)前模塊對(duì)象/當(dāng)前文件

   exports是當(dāng)前module對(duì)象的一個(gè)屬性
     本質(zhì)上也是一個(gè)對(duì)象,保存將來要拋出的所有東西
     exports是當(dāng)前模塊對(duì)外的唯一接口

今后,只要希望將模塊內(nèi)部的東西,拋出到外部,供其它文件使用時(shí),都要添加到module.exports上
其它文件要想使用當(dāng)前模塊的功能,就必須用require引入當(dāng)前模塊,而require的本質(zhì)是找模塊的exports.

2.2面向函數(shù)的方式:

在文件中,定義多個(gè)零散的方法

將多個(gè)零散的方法添加到module的exports上
其實(shí),可先將零散的方法,先集中定義在一個(gè)對(duì)象中,再將整個(gè)對(duì)象賦值給module.exports屬性

引入模塊: require() 專門負(fù)責(zé)加載模塊文件
何時(shí): 只要在另一個(gè)js文件中,引入自定義模塊并獲取內(nèi)容時(shí),都用require
本質(zhì): 找到j(luò)s文件,并執(zhí)行,返回module.exports對(duì)象
優(yōu)化: 單例模式singleton: 始終保持項(xiàng)目中只有一個(gè)對(duì)象的實(shí)例

模塊的引入和加載也是單例模式: 模塊只在第一次被require時(shí),創(chuàng)建。之后,緩存在內(nèi)存中。反復(fù)require不會(huì)導(dǎo)致反復(fù)創(chuàng)建模塊對(duì)象。

強(qiáng)調(diào): 模塊是同步加載:前一個(gè)加載完,后一個(gè)才能開始

 強(qiáng)烈建議: 所有require必須集中在頂部

路徑: 以./開頭,表示使用相對(duì)路徑,相對(duì)于當(dāng)前正在執(zhí)行腳本所在路徑——不能省略!

    以/開頭,表示Linux系統(tǒng)根目錄——絕對(duì)路徑
    以自定義變量開頭,表示在變量保存的地址下繼續(xù)查找
    什么前綴也不加!只寫模塊名: 表示加載一個(gè)核心模塊或項(xiàng)目引入的第三方模塊
      路徑查找順序:
        /usr/local/lib/node/模塊名.js
        /home/user/projects/node_modules/模塊名.js
        /home/user/node_modules/模塊名.js
        /home/node_modules/模塊名.js
        /node_modules/模塊名.js

坑: 簡寫: module.exports.fun=function(){…}

       可簡寫為: exports.fun=function(){…}
   exports其實(shí)是module.exports的別名
   var exports=module.exports;
問題: 給exports賦值,無法賦值給module.exports
   因?yàn)閑xports只是一個(gè)變量,臨時(shí)保存module.exports的地址值。再次給exports賦任何新值,都導(dǎo)致exports與module.exports分道揚(yáng)鑣!
避免: 不要用簡寫exports

3.目錄模塊:

何時(shí): 當(dāng)一個(gè)模塊代碼,復(fù)雜到需要進(jìn)一步細(xì)分時(shí),一個(gè)模塊,就可能由多個(gè)文件組成,保存在一個(gè)文件夾里。
如何:

創(chuàng)建文件夾,集中保存相關(guān)的多個(gè)js文件模塊

在文件夾中添加一個(gè)主模塊(index.js),主模塊中,引入并組織好多個(gè)小模塊一起導(dǎo)出

在文件夾中添加package.json文件,其中:

  {
    "name":"模塊名",
    "main":"./主模塊相對(duì)路徑"
  }

其實(shí), 如果沒有main甚至沒有package.json,也行。
會(huì)自動(dòng)優(yōu)先找文件夾下的index.js

引入目錄模塊: require("./目錄名")
如果希望直接用目錄名引用模塊,不加相對(duì)路徑:
將目錄放入node_modules文件夾中

npm: 第三方模塊的包管理工具: 查詢,下載
除了核心模塊和自定義本地模塊,node生態(tài)系統(tǒng)還提供了大量優(yōu)質(zhì)第三方模塊
如何:
查詢模塊:

模糊查找: npm search 模塊名
精確查找: npm search /^模塊名$/
  如果現(xiàn)實(shí)完整描述: npm search /^模塊名$/ --parseable

安裝模塊: 2個(gè)位置:

全局安裝: npm install -g 模塊名
路徑: Linux: /usr/local/lib/node_modules

   Windows:
    C:Users用戶名AppDataRoaming
pm
ode_modules

項(xiàng)目本地安裝: npm install 模塊名 -save

全局對(duì)象:
全局作用域?qū)ο蟛皇莣indow,而是global
ECMAScript標(biāo)準(zhǔn)中原本規(guī)定的就是global
在瀏覽器中被window代替
強(qiáng)調(diào): 交互模式: 直接在命令行中測(cè)試node應(yīng)用,所有全局變量/全局函數(shù)自動(dòng)成為global的成員

 腳本模式: 通過加載js文件執(zhí)行node應(yīng)用,文件內(nèi)的"全局變量/全局函數(shù)",僅當(dāng)前文件所有,不會(huì)成為global的成員——避免了全局污染

console對(duì)象:
測(cè)試重要手段: 打樁: 在關(guān)鍵位置輸出關(guān)鍵變量的值
輸出文本信息: 瀏覽器中4種輸出,node中合并為2中:
console.log/info() 輸出普通的文本信息
console.error/warn() 輸出錯(cuò)誤信息
其實(shí): console.xxx()都自帶格式化功能
Console.log vs console.error: .error可直接導(dǎo)出到文件日志中

如何: node xxx.js 2> error-file.log
其中:2>表示輸出流,專門向硬盤文件寫入內(nèi)容

輸出耗時(shí):
Console.time("標(biāo)簽"); //預(yù)備,開始!
正常程序邏輯
Console.timeEnd("標(biāo)簽"); //完成! 自動(dòng)輸出與time之間的時(shí)間間隔
單元測(cè)試:
什么是: 對(duì)程序中最小的執(zhí)行單元進(jìn)行測(cè)試
開發(fā)人員主動(dòng)對(duì)自己的函數(shù)執(zhí)行單元測(cè)試
如何: console.assert(判斷條件, "錯(cuò)誤提示")

               只有條件不滿足時(shí),才輸出msg

輸出堆棧:
console.trace()

全局對(duì)象: process:

process.platform
process.pid
process.kill(pid);

控制臺(tái)輸入輸出:
2步:

讓控制臺(tái)進(jìn)入輸入狀態(tài):

process.stdin.resume()
process.stdin.setEncoding("utf-8")

監(jiān)聽stdin的data事件:
在控制臺(tái)輸入后,按回車,會(huì)觸發(fā)stdin的data事件

  process.stdin.on("data",text=>{
      process.stdout.write( … text … )
    })

控制臺(tái)參數(shù):
2步: 1. 定義關(guān)聯(lián)數(shù)組,保存參數(shù)名和參數(shù)對(duì)應(yīng)的處理函數(shù)

2. 啟動(dòng)時(shí), process.argv數(shù)組可自動(dòng)獲得傳入的所有參數(shù),  根據(jù)參數(shù)調(diào)用不同的處理函數(shù)

process.argv: ["node.exe","xxx.js","參數(shù)值1","參數(shù)值2",…]

高精度計(jì)時(shí):
精確到納秒, 優(yōu)點(diǎn): 不受系統(tǒng)時(shí)間影響
如何: 2步: 1. 獲得開始的時(shí)間戳: var start=process.hrtime();

      2. 獲得結(jié)束時(shí)間戳: var diff=process.hrtime(start);

diff: [秒數(shù), 納秒]

獲得秒差: diff[0]+diff[1]/1e9
獲得毫秒差: diff[0]*1000+diff[1]/1e6

Vs console.time/timeEnd:
time/timeEnd: 缺: 精度低, 優(yōu): 效率高
hrtime: 優(yōu): 精度高,且不受系統(tǒng)時(shí)間影響

      缺點(diǎn): 效率低

非I/O的異步操作(定時(shí)器):
何時(shí): 要執(zhí)行異步回調(diào)時(shí)
如何:

setTimeout/setInterval() 將回調(diào)函數(shù)添加到事件循環(huán)的timer階段的隊(duì)列中等待執(zhí)行。
Timer階段是事件循環(huán)的第一階段
習(xí)慣上: setTimeout往往都會(huì)設(shè)置ms數(shù)

setImmediate() 將回調(diào)函數(shù)添加到事件循環(huán)的check階段的隊(duì)列中等待執(zhí)行。
Check階段比Timer要晚執(zhí)行
習(xí)慣上: 并不設(shè)置毫秒數(shù),而是普通的追加到等待隊(duì)列末尾即可。

process.nextTick() 將回調(diào)函數(shù)加入nextTickQueue隊(duì)列等待執(zhí)行
nextTickQueue不參與事件循環(huán),而是在開始timer之前,就立刻執(zhí)行nextTickQueue中的回調(diào)函數(shù)
優(yōu)點(diǎn): 不會(huì)有延遲

自定義的EventEmiter

5.EventEmitter類型:

Node.js所有異步I/O操作完成時(shí),都會(huì)發(fā)送一個(gè)事件到事件隊(duì)列
Node.js中許多對(duì)象都會(huì)觸發(fā)事件:
比如: http模塊: 創(chuàng)建Server對(duì)象,監(jiān)聽http請(qǐng)求

   一旦收到一個(gè)http請(qǐng)求,則立刻觸發(fā)事件,將處理函數(shù)放入事件隊(duì)列
  fs模塊: 在每次讀寫完文件時(shí),也會(huì)觸發(fā)事件,將處理函數(shù)放入事件隊(duì)列

什么是EventEmitter: 專門封裝事件監(jiān)聽和事件觸發(fā)的API的一種類型
所有可以觸發(fā)事件的對(duì)象,都是EventEmitter類型的子對(duì)象
如何讓一個(gè)對(duì)象可以監(jiān)聽并觸發(fā)事件:

引入events模塊: const events=require("events")

創(chuàng)建events.EventEmitter類型的子對(duì)象:
var emitter=new events.EventEmitter();

用on,為對(duì)象添加事件監(jiān)聽:
emitter.on("自定義事件名",function 處理函數(shù)(參數(shù)列表){

… 獲得參數(shù), 執(zhí)行操作 …

})

在任何情況下,使用對(duì)象的emit方法,觸發(fā)指定的事件:
emitter.emit("自定義事件名",參數(shù)值,…)

觸發(fā)一次后,自動(dòng)解綁:
emitter.once("自定義事件名",處理函數(shù))

錯(cuò)誤處理:
問題: try catch無法捕獲異步調(diào)用中的錯(cuò)誤
解決: Domain
何時(shí): 只要既希望捕獲主程序錯(cuò)誤,又希望捕獲異步操作的錯(cuò)誤時(shí)
如何:

引入domain模塊: const domain=require("domain")

創(chuàng)建domain對(duì)象: const mpDomain=domain.create();

為domain對(duì)象添加error事件監(jiān)聽
mpDomain.on("error",err=>{

console.log("出錯(cuò)啦!"+err);

})

將可能出錯(cuò)的程序放入mpDomain中運(yùn)行:
mpDomain.run(()=>{

musicPlayer.emit("play");

})

6.協(xié)議:

什么是: 計(jì)算機(jī)之間通過網(wǎng)絡(luò)實(shí)現(xiàn)通信時(shí),事先達(dá)成的一種"約定"
為什么: 約定使不同廠商的設(shè)備,不同操作系統(tǒng)之間,都可按照統(tǒng)一約定,任意通信

7.分組交換方式:

什么是: 將大數(shù)據(jù)分割為一個(gè)個(gè)叫做包(packet)的較小單元進(jìn)行傳輸

8.ISO/OSI模型:

ISO(國際標(biāo)準(zhǔn)化組織)
OSI(開放式通信系統(tǒng)互聯(lián)參考模型)
7層:

應(yīng)用層: 規(guī)定應(yīng)用程序中的通信細(xì)節(jié)
包括: HTTP FTP TELNET SMTP DNS

表示層: 負(fù)責(zé)數(shù)據(jù)格式的轉(zhuǎn)換

會(huì)話層: 建立連接

傳輸層: 控制總體數(shù)據(jù)傳輸
包括:
TCP(傳輸控制協(xié)議): 可靠傳輸
優(yōu): 可靠,客戶端和服務(wù)端可雙向通信
缺: 傳輸效率低
何時(shí): 要求可靠性時(shí)
UDP(用戶數(shù)據(jù)報(bào)協(xié)議):
何時(shí): 對(duì)可靠性要求不高,對(duì)傳輸效率要求高,且發(fā)送小數(shù)據(jù)(qq, 微信, 在線視頻播放)

網(wǎng)絡(luò)層: 將數(shù)據(jù)分組傳輸?shù)侥康牡?/p>

數(shù)據(jù)鏈路層: 負(fù)責(zé)規(guī)劃網(wǎng)絡(luò)中節(jié)點(diǎn)間的路線

物理層: 負(fù)責(zé)通過以太網(wǎng),藍(lán)牙,光纖發(fā)送0/1的比特流

9.TCP/IP: 互聯(lián)網(wǎng)協(xié)議套件

包含: TCP 傳輸控制協(xié)議

   IP 互聯(lián)網(wǎng)協(xié)議

TCP/IP不是ISO標(biāo)準(zhǔn)
TCP/IP 只有四層:

鄙視:

TCP/IP四層協(xié)議,分別對(duì)應(yīng)ISO/OSI中的哪一層: 圖6

網(wǎng)絡(luò)建立連接需要3次握手,斷開連接需要4次握手,分別是:
圖7

HTTP/1.0 1.1 2.0每次升級(jí)有哪些不同

10.net模塊:

使用net模塊:

可創(chuàng)建基于TCP的客戶端與服務(wù)器端通信

創(chuàng)建TCP服務(wù)器:
引入net模塊
使用net.createServer方法創(chuàng)建服務(wù)端對(duì)象server

接受一個(gè)回調(diào)函數(shù)作為參數(shù):
 只要有客戶端連接到當(dāng)前服務(wù)端,就自動(dòng)執(zhí)行該回調(diào)函數(shù)
 回調(diào)函數(shù)接受一個(gè)socket參數(shù)對(duì)象,用于與客戶端通信
 Socket對(duì)象: 是客戶端在服務(wù)器端的一個(gè)代理對(duì)象
            可通過socket和真正的客戶端發(fā)送和接受消息
 Socket對(duì)象的data事件,可監(jiān)聽客戶端發(fā)來的消息
   回調(diào)函數(shù)中, data參數(shù)為消息的內(nèi)容
 Socket對(duì)象的end事件,可監(jiān)聽客戶端的斷開
 Socket的write方法向客戶端輸出消息

調(diào)用server的listen方法,綁定到一個(gè)端口,監(jiān)聽客戶端發(fā)來的鏈接請(qǐng)求

也接受一個(gè)回調(diào)函數(shù)參數(shù),但僅在啟動(dòng)監(jiān)聽后執(zhí)行一次

創(chuàng)建TCP客戶端:
引入net模塊
使用net.connect()方法向服務(wù)器建立連接
var client=net.connect(服務(wù)端端口,ip,function(){})
回調(diào)函數(shù)在連接建立后,自動(dòng)觸發(fā)一次
為client的data事件綁定處理函數(shù),處理函數(shù)的data參數(shù)自動(dòng)接收服務(wù)端發(fā)來的消息
為client的end事件添加處理函數(shù),當(dāng)客戶端斷開連接時(shí)執(zhí)行操作
在任何位置可用client.write("消息內(nèi)容")向服務(wù)端發(fā)送
在任何位置可用client.end() 斷開與服務(wù)端連接

11.HTTP模塊:

使用HTTP模塊:

實(shí)現(xiàn)WEB服務(wù)器,接受請(qǐng)求并返回響應(yīng)(代替了apache,tomcat)

模擬客戶端向一個(gè)指定的WEB服務(wù)器發(fā)送請(qǐng)求

創(chuàng)建HTTP服務(wù)端:
引入HTTP模塊
創(chuàng)建HTTP服務(wù)端server:
var server=http.createServer(function(req,res){

 //只要有請(qǐng)求發(fā)送到該服務(wù)器,就自動(dòng)觸發(fā)該回調(diào)函數(shù)
 //其中: 
   //req對(duì)象,封裝了發(fā)來的請(qǐng)求信息
   //res對(duì)象,專門用于向服務(wù)器端返回響應(yīng)
    //res.writeHead(狀態(tài)碼,{ 屬性:值, …:… ,…})
    //res.write("放入響應(yīng)主體中")
    //res.end()

})
啟動(dòng)監(jiān)聽: server.listen(端口,function(){ … })

創(chuàng)建HTTP請(qǐng)求:
使用http.request()方法創(chuàng)建一個(gè)請(qǐng)求(連接),獲得請(qǐng)求對(duì)象req
接收2個(gè)參數(shù):

options對(duì)象參數(shù):
 host
 port
 method
 path  /index.html?page=12
回調(diào)函數(shù): 在服務(wù)器端返回響應(yīng)時(shí)執(zhí)行
 參數(shù)res: 專門用于獲得響應(yīng)內(nèi)容(響應(yīng)頭和響應(yīng)主體)
  HTTP協(xié)議規(guī)定: 先發(fā)響應(yīng)頭部 用res.headers獲得響應(yīng)頭部對(duì)象,用res.statusCode 獲得狀態(tài)碼
  強(qiáng)調(diào): 響應(yīng)主題是稍后才發(fā)送過來
   必須用res.on("data",function(buffer){ … String(buffer) …})
  強(qiáng)調(diào): 凡是從響應(yīng)中獲得的data,默認(rèn)都是字符串

req.end()結(jié)束并發(fā)送請(qǐng)求。
強(qiáng)調(diào):必須加req.end(),請(qǐng)求才能發(fā)送出去

http.get()
專門向服務(wù)器端發(fā)送get請(qǐng)求
是http.request()的簡化:

自動(dòng)設(shè)置method為get;

自動(dòng)調(diào)req.end

但依然需要使用res.on("data",function(buffer){ … })來接受響應(yīng)主體

分塊:
問題: 如果響應(yīng)主體過大,一次性傳不過來
解決:

   分塊發(fā)送和接受,再拼接,再整體轉(zhuǎn)換
   如果分塊接受,res.on("data",function(buf){ … })每收到一塊,就會(huì)反復(fù)觸發(fā)。
   其中buf,僅是其中一塊而已

請(qǐng)求文件,保存在本地:
引入fs模塊:
創(chuàng)建寫入流,指向目標(biāo)文件: var writable=fs.createWriteStream("相對(duì)路徑")
使用管道,將寫入流writable連接到res對(duì)象上: res.pipe(writable)

響應(yīng)頭部: res.writeHead(狀態(tài)碼,{ })
允許跨域: "Access-Control-Allow-Origin":"請(qǐng)求來源的網(wǎng)站"
指定內(nèi)容類型:"Content-Type":"application/json" "text/css"

req對(duì)象:
請(qǐng)求頭部: req.headers
請(qǐng)求方法: req.method
請(qǐng)求地址: req.url
url的處理:

引入url模塊
用url.parse(req.url,true)將req.url字符串轉(zhuǎn)為對(duì)象
 其中true,表示將search中的參數(shù)也轉(zhuǎn)為對(duì)象屬性
 如何: var obj=url.parse(req.url, true)
  其中: obj.query中保存了所有參數(shù)及其值

獲得請(qǐng)求參數(shù):
Get: get方式的參數(shù)都通過url中的search傳遞

  obj=url.parse(req.url,true)
  obj.query

Post: post方式的參數(shù)都是放在請(qǐng)求主體中,沒有在url中

  問題:obj.query無法獲得
  解決: req.on("data",function(buf){ … })
  問題: String(buf)獲得的是參數(shù)的字符串
  解決: querystring模塊


12.https模塊:

問題: http協(xié)議是明文的
危害: 1. 通信使用明文,內(nèi)容可能被竊聽

   2. 不驗(yàn)證身份,有可能遭遇偽裝
   3. 無法證明消息的完整性,消息有可能被篡改

網(wǎng)絡(luò)嗅探器:

13.解決: https協(xié)議

https是更安全的http協(xié)議:

客戶端和服務(wù)器端的雙向認(rèn)證

完整性檢查

內(nèi)容加密

https=http+ssl

ssl/tls: ssl 安全套接層,對(duì)傳統(tǒng)socket進(jìn)一步提供安全的保護(hù)

 tls 傳輸層安全, 其實(shí)是ssl的繼任者
14.提供三大服務(wù):

客戶端和服務(wù)器端的雙向認(rèn)證 ——可靠

完整性檢查 ——完整

數(shù)據(jù)加密 ——機(jī)密性
tls/ssl的執(zhí)行過程:

15.Step0: 獲得服務(wù)器端證書, 3步:

在服務(wù)器端生成私鑰

用私鑰生成一個(gè)證書申請(qǐng)文件

將私鑰和申請(qǐng)文件交給第三方CA,第三方CA經(jīng)過審查,會(huì)生成并頒發(fā)證書給申請(qǐng)的服務(wù)器
證書包含2樣?xùn)|西: 公鑰+公司的信息
Step1: 客戶端請(qǐng)求https協(xié)議的web服務(wù)器
Step2: 服務(wù)器返回證書給客戶端
Step3: 客戶端拿到證書后,將證書交給CA。

  客戶端利用CA中的公鑰隨機(jī)生成自己的私鑰
  將私鑰發(fā)給服務(wù)器端

Step4: 服務(wù)器端獲得客戶端發(fā)來的客戶端私鑰
到此,客戶端和服務(wù)器端,擁有了相同的兩個(gè)鑰匙
之后,服務(wù)器和客戶端發(fā)送的所有消息,都用兩個(gè)相同的私鑰加密和解密

16.如何實(shí)現(xiàn)https的web服務(wù)器應(yīng)用:

申請(qǐng)https網(wǎng)站的認(rèn)證證書:

Step1: 用openssl生成服務(wù)器端私鑰:
openssl genrsa -out d:/privatekey.pem 1024
Step2: 用私鑰生成證書申請(qǐng)文件:

openssl  req  -new  -key  d:/privatekey.pem  -out  d:/certificaterequest.csr

Step3: 用私鑰和證書申請(qǐng)文件共同生成證書文件

openssl  x509  -req  -in  d:/certificaterequest.csr  -signkey  
d:/privatekey.pem   -out  d:/certificate.pem

2.使用node的https模塊創(chuàng)建服務(wù)器
Step1: 引入必須的模塊:
const https=require(“https”);
const fs=require(“fs”);
Step2:讀取服務(wù)器私鑰和證書文件,保存到服務(wù)器程序的變量中
let privatekey=fs.readFileSync(“d:/privatekey.pem”);
let certificate=fs.readFileSync(“d:/certificate.pem”);
Step3: 用https創(chuàng)建服務(wù)器端應(yīng)用程序,提供私鑰和證書,并定義處理請(qǐng)求的回調(diào)函數(shù)

https.createServer(
  {
    key: privatekey,
    cert: certificate
},
(req,res)=>{
  res.write(“…”)
  res.end();
}
).listen(443)

3.用https模塊向https的服務(wù)器發(fā)送請(qǐng)求
錯(cuò)誤: http模塊不支持向https服務(wù)器發(fā)送請(qǐng)求
正確:

var https=require(“https”);
https.get(“https://...”, res=>{
res.on(“data”,buf=>{
buf…
})
})

17.express

什么是: 基于node的http模塊和第三方的Connect框架的web框架
Connect框架: 專門將各種各樣的中間件函數(shù)粘合在一起,共同處理http請(qǐng)求中的req對(duì)象
何時(shí): 只要對(duì)req對(duì)象反復(fù)執(zhí)行多種操作時(shí),都要用connect組織多個(gè)中間件。
如何:

Step1: 安裝connect模塊: npm install connect –save

Step2: 引入connect模塊: var connect=require(“connect”)

Step3: 用connect模塊創(chuàng)建處理req對(duì)象的應(yīng)用程序?qū)嵗齰ar app=connect();

Step4: 向connect模塊的應(yīng)用程序?qū)嵗刑砑又虚g件函數(shù)

  app.use(function md1(req,res,next){
  //加工req對(duì)象
  … …
  next();
})

Step5: connect的應(yīng)用程序?qū)嵗仨氁湃隿reateServer中用于處理服務(wù)器接收到的req對(duì)象
http.createServer(app)
總結(jié): express是在connect基礎(chǔ)上的進(jìn)一步封裝和簡化,所以express也是采用中間件組合的方式,處理req對(duì)象
安裝express框架: 2種:

使用本地express模塊,進(jìn)能夠提供服務(wù)支持,需要自定義添加復(fù)雜的程序結(jié)構(gòu)

Step1: npm install –save express
Step2: 引入http和express
const http=require(“http”);
const express=require(“express”);
Step3: 創(chuàng)建express應(yīng)用實(shí)例對(duì)象:
let app=express();
Step4: 為app添加各種處理中間件函數(shù)
app.use(function md(req,res,next){ … …})
Step5: 將app和createServer相連
http.createServer(app).listen(端口號(hào));

使用腳手架, 簡化生成項(xiàng)目的結(jié)構(gòu):

Step1: 全局安裝express生成器:
npm install –g express-generator

Step2: 用生成器,生成項(xiàng)目腳手架代碼:
express 項(xiàng)目文件夾名 –e //-e 表示用EJS作為前端頁面模板
強(qiáng)調(diào): 只負(fù)責(zé)生成項(xiàng)目代碼,并不負(fù)責(zé)下載依賴包

Step3: 為腳手架代碼下載所有依賴包
cd 項(xiàng)目文件夾下
npm install //根據(jù)package.json中的依賴項(xiàng)

Step4: 用腳手架代碼啟動(dòng)nodejs服務(wù)器端應(yīng)用程序: npm start

express項(xiàng)目結(jié)構(gòu):

./bin/www.js express項(xiàng)目的啟動(dòng)文件

package.json中: npm start 時(shí) 自動(dòng)執(zhí)行 node ./bin/www

2./app.js 對(duì)express框架的實(shí)例對(duì)象的配置
要求: 對(duì)express實(shí)例對(duì)象app的所有配置必須放在一個(gè)獨(dú)立的文件模塊app.js中
然后,在主程序www.js中引入app.js模塊

3../routes/xxx.js 路由模塊
每個(gè)子功能,都應(yīng)該集中定義在一個(gè)路由模塊文件中
在app.js中引入路由文件模塊,并將路由文件模塊添加到app的中間件列表中,并設(shè)置上級(jí)路徑
在每個(gè)子路由模塊文件中,創(chuàng)建路由對(duì)象,為路由對(duì)象添加不同請(qǐng)求方法和不同子路徑下的處理函數(shù)
強(qiáng)調(diào): 子路由中的相對(duì)路徑,都是在上級(jí)路徑之下的相對(duì)路徑

改造腳手架項(xiàng)目結(jié)構(gòu):

補(bǔ)充缺失的模塊:
express-session 讓express可以處理session
connect-flash 強(qiáng)化自動(dòng)維護(hù)session的功能
passport 綜合的用戶驗(yàn)證解決方案

         ( 使用passport模塊,實(shí)現(xiàn)qq,微信登錄)

在app.js中添加對(duì)新模塊的引用:

為項(xiàng)目添加mongodb支持

Step1: 安裝mongoose模塊和promise模塊
mongoose: node js專用的簡化操作mongodb數(shù)據(jù)庫的模塊

Step2: 創(chuàng)建文件夾./config,在文件夾下添加config.js
在config.js中定義對(duì)象模塊,保存連接字符串
module.exports={
db:”mongodb://主機(jī)名或ip/數(shù)據(jù)庫名”}

Step3: 在./config文件夾下創(chuàng)建mongoose.js,保存創(chuàng)建連接對(duì)象的代碼:
var config=require("./config"),
mongoose=require("mongoose");
設(shè)置mongoose的promise屬性,使用當(dāng)前項(xiàng)目的promise模塊
mongoose.Promise=require(‘promise’);
var db=mongoose.connect(config.db) module.exports=db;

Step4: 根據(jù)業(yè)務(wù)需要,定義mongoose模型對(duì)象:
創(chuàng)建./models文件夾, 在models內(nèi)為每種業(yè)務(wù)對(duì)象創(chuàng)建專門的模型文件

3步:

引入mongoose,獲得Schema類型

用Schema創(chuàng)建UserSchema結(jié)構(gòu)

將UserSchema編譯為User模型,并拋出為User模塊
Step5: 回到mongoose.js中,在connect之后,引入U(xiǎn)ser模塊require("../models/user.model");
Step6: 回到app.js中,在路由中間件之前,先請(qǐng)求并初始化mongoose.jsrequire("./config/mongoose");

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94521.html

相關(guān)文章

  • 后端識(shí)點(diǎn)總結(jié)——NODE.JS基礎(chǔ)

    摘要:后端知識(shí)點(diǎn)總結(jié)基礎(chǔ)不是是一種軟件開發(fā)平臺(tái),它的競爭對(duì)象歷史第一次有一種語言可以通吃前后端網(wǎng)站阿里云鏡像版本年初年中年底最新版本功能強(qiáng)大可靠,適合大型企業(yè)級(jí)項(xiàng)目簡單易用適合互聯(lián)網(wǎng)項(xiàng)目易用適合平臺(tái)性能好適合服務(wù)器端密集型項(xiàng)目不適合密集型項(xiàng)目密集 后端知識(shí)點(diǎn)總結(jié)——NODE.JS基礎(chǔ) 1.Node.js Node.js不是JS,是一種軟件開發(fā)平臺(tái),它的競爭對(duì)象JSP/PHP/ASP.NET...

    Freeman 評(píng)論0 收藏0
  • 后端好書閱讀與推薦

    摘要:后端好書閱讀與推薦這一兩年來養(yǎng)成了買書看書的習(xí)慣,陸陸續(xù)續(xù)也買了幾十本書了,但是一直沒有養(yǎng)成一個(gè)天天看書的習(xí)慣。高級(jí)程序設(shè)計(jì)高級(jí)程序設(shè)計(jì)第版豆瓣有人可能會(huì)有疑問,后端為啥要學(xué)呢其實(shí)就是為了更好的使用做鋪墊。 后端好書閱讀與推薦 這一兩年來養(yǎng)成了買書看書的習(xí)慣,陸陸續(xù)續(xù)也買了幾十本書了,但是一直沒有養(yǎng)成一個(gè)天天看書的習(xí)慣。今天突然想要做個(gè)決定:每天至少花1-3小時(shí)用來看書。這里我準(zhǔn)備把這...

    clasnake 評(píng)論0 收藏0
  • 后端好書閱讀與推薦

    摘要:后端好書閱讀與推薦這一兩年來養(yǎng)成了買書看書的習(xí)慣,陸陸續(xù)續(xù)也買了幾十本書了,但是一直沒有養(yǎng)成一個(gè)天天看書的習(xí)慣。高級(jí)程序設(shè)計(jì)高級(jí)程序設(shè)計(jì)第版豆瓣有人可能會(huì)有疑問,后端為啥要學(xué)呢其實(shí)就是為了更好的使用做鋪墊。 后端好書閱讀與推薦 這一兩年來養(yǎng)成了買書看書的習(xí)慣,陸陸續(xù)續(xù)也買了幾十本書了,但是一直沒有養(yǎng)成一個(gè)天天看書的習(xí)慣。今天突然想要做個(gè)決定:每天至少花1-3小時(shí)用來看書。這里我準(zhǔn)備把這...

    Juven 評(píng)論0 收藏0
  • 前端架構(gòu)師親述:前端工程師成長之路的 N 問 及 回答

    摘要:問題回答者黃軼,目前就職于公司擔(dān)任前端架構(gòu)師,曾就職于滴滴和百度,畢業(yè)于北京科技大學(xué)。最后附上鏈接問題我目前是一名后端工程師,工作快五年了。 showImg(https://segmentfault.com/img/bVbuaiP?w=1240&h=620); 問題回答者:黃軼,目前就職于 Zoom 公司擔(dān)任前端架構(gòu)師,曾就職于滴滴和百度,畢業(yè)于北京科技大學(xué)。 1. 前端開發(fā) 問題 大...

    crossoverJie 評(píng)論0 收藏0
  • 前端面試識(shí)點(diǎn)目錄整理

    摘要:寫在前面金三銀四又到了一年一度的跳槽季相信大家都在準(zhǔn)備自己面試筆記我也針對(duì)自己工作中所掌握或了解的一些東西做了一個(gè)目錄總結(jié)方便自己復(fù)習(xí)詳細(xì)內(nèi)容會(huì)在之后一一對(duì)應(yīng)地補(bǔ)充上去有些在我的個(gè)人主頁筆記中也有相關(guān)記錄這里暫且放一個(gè)我的面試知識(shí)點(diǎn)目錄大家 寫在前面: 金三銀四, 又到了一年一度的跳槽季, 相信大家都在準(zhǔn)備自己面試筆記, 我也針對(duì)自己工作中所掌握或了解的一些東西做了一個(gè)目錄總結(jié),方便自...

    xzavier 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<