中間件是什麼呢? 中間件就是客戶端http請求發起傳送到伺服器和伺服器返迴響應之間的一些處理函數。 為什麼要使用中間件? 通過中間件,可以對數據進行操作使得我們能方便地操作請求數據編寫伺服器響應。如body-parse中間件對post請求的參數進行處理讓我們可以通過res.body快速獲取請求參數, ...
中間件是什麼呢?
中間件就是客戶端http請求發起傳送到伺服器和伺服器返迴響應之間的一些處理函數。
為什麼要使用中間件?
通過中間件,可以對數據進行操作使得我們能方便地操作請求數據編寫伺服器響應。如body-parse中間件對post請求的參數進行處理讓我們可以通過res.body快速獲取請求參數,express-session中間件可以讓我們對數據進行保存,express.static是express內置中間件,可以讓我們快速處理靜態資源,express.Router路由中間件等等 中間件如何使用? Express中,對中間件進行了幾種分類: 1.不關心請求路徑和請求方法的中間件,通過app.use函數實現 app.use(function(req,res,next){}) 客戶端發起的任意請求都會經過這個中間件函數進行處理 next指下一個滿足路徑條件的中間件,如果有執行next,那麼這個中間件執行完後就會執行下一個滿足條件的中間件,如果沒有next,就會忽略後面所有中間件 以下麵代碼為例(設伺服器ip為127.0.0.1,後面所有例子都以該ip為例)var express = require('express') var app = express() app.use(function(req,res) { res.end('404 NOT FOUND') } app.listen(3000,function(){ console.log('running...'); }
所有對該伺服器的請求最終都會返回404 NOT FOUND,無論是路徑是什麼
2.關心請求路徑的中間件,通過app.use函數實現 app.use(路徑,function(req,res,next){}) 客戶端發起的以第一個參數開頭的路徑才會進入該中間件 以下代碼為例var express = require('express') var app = express() app.use('/public',function(req,res,next) { res.end('you are public'); } app.listen(3000,function(){ console.log('running...') }
只要客戶端訪問該伺服器的地址是以public開頭(即127.0.0.1:3000/public/xxx),那麼就會返回you are public 字元串
3.嚴格匹配路徑的中間件,通過app.get/app.post等實現 也就是我們所說的伺服器路由 app.get(路徑,函數) app.post(路徑,函數) 只有嚴格匹配請求方式和請求路徑的請求才會進入該中間件 以下麵代碼為例
var express = require('express') var app = express()
// 中間件1 app.get('/get/puclic',function(req,res){ res.end('get!'); } // 中間件2 app.post('/post/public',function(req,res) { res.end('post!'); } app.listen(3000,function(){ console.log('running...'); }
客戶端只有通過get方式訪問127.0.0.1:3000/get/public時才會進入中間件1,只有通過post方式訪問127.0.0.1:3000/post/public時才會進入中間件2,只有這兩者完全匹配才會進入對應的中間件
中間件的執行機制: 1.中間件的第一次執行是同步的,當一個請求發出到達伺服器後,則按照順序匹配所有中間件,當找到一個匹配時,則進入該中間件 2.如果該中間件最後沒有執行next函數,則該請求在此中間件終止,不再進入後面的中間件;如果有,則會直接進入後面匹配的中間件中(此時不再是按順序!) 3.重覆1-2步 如果把客戶端發起請求和伺服器發出響應比作自來水的進入水庫和輸出水庫,那麼中間件就是水庫里對水分別進行過濾沉澱消毒的各個小廠房,而中間件的函數的next參數就相當於每個小廠房的門,只有這個門打開了,處理完的請求的數據才能繼續向後面的中間件發送,直至響應發出。
以下麵的代碼為例進一步說明中間件的執行順序
var express = require('express'); var app = express()
//中間件1 app.use(function(req,res) { console.log('非嚴格'); })
//中間件2 app.use('/public',function(req,res,next) { console.log('半嚴格');
next(); })
//中間件3 app.get('/public',function(req,res) { console.log('嚴格 get'); })
//中間件4 app.post('/public',function(req,res) { console.log('嚴格 post'); })
//中間件5
app.get('/public',function(req,res) { console.log('嚴格 get'); })
app.listen(3000,function() { console.log('running...') })
此時客戶端訪問/public,那麼首先會進入中間件1,因為有執行next函數,所以直接尋找後面能夠匹配的中間件,進入中間件2,中間有執行next函數,所以進入中間件3,但是中間件3沒有next函數,所以不再執行,所以輸出的語句是‘非嚴格’ '半嚴格' '嚴格 get'
如果是下麵代碼,請求/public後結果又是怎樣呢?
var express = require('express'); var app = express() app.use('/img',function(req,res) { console.log('半嚴格'); }) app.get('/public',function(req,res) { console.log('嚴格 get'); }) app.post('/public',function(req,res) { console.log('嚴格 post'); })
app.listen(3000,function() { console.log('running...') })
結果是輸出'嚴格 get',請求到達伺服器後,從上往下逐漸匹配,匹配到第二個中間件,進入執行,但是該中間件沒有執行next函數,所以終止
綜上所述,我們可以知道,第三方中間件的安裝執行是有講究的
對於一些封裝請求數據方便我們操作以及處理靜態資源的中間件我們應該放在路由中間件(即有發出伺服器響應的中間件)之前編寫,否則在編寫路由時就無法使用封裝好的數據。而對於返回404頁面的路由可以放在所有中間件後面,這樣無法找到的頁面則會自動匹配到最後一個返回404頁面 中間件的使用是靈活多變的,本文章只是簡單概述其概念及其執行機制,更多技巧仍需讀者自行體會