express中間件分成三種 內置中間件 static 自定義中間件 第三方中間件 (body-parser) (攔截器) 全局自定義中間件 在請求介面時 有幾個介面都要驗證傳來的內容是否存在或者是否正確 不可能每個介面都寫一段驗證,所以這一段驗證可以提取出來,通過中間件實現 const expre ...
express中間件分成三種
內置中間件 static
自定義中間件 第三方中間件 (body-parser) (攔截器)全局自定義中間件
在請求介面時 有幾個介面都要驗證傳來的內容是否存在或者是否正確 不可能每個介面都寫一段驗證,所以這一段驗證可以提取出來,通過中間件實現
const express = require("express"); const app = express(); // test1介面 app.get("/test1",(req,res) => { res.send("test1 ok") }) // test2介面 app.get("/test2",(req,res) => { res.send("test2 ok") }) // 開啟伺服器 app.listen(2000,() => { console.log('開啟在2000埠'); })現在要做的是在請求test1和test2的時候 看請求中有沒有帶上需要的欄位 token app.use() 第一種中間件 可以說是攔截器 第一個參數是路徑 第二個參數是回調函數 回調函數中有req res next
const express = require("express"); const app = express(); app.use("/",(req,res,next)=>{ console.log("中間件") }) // test1介面 app.get("/test1",(req,res) => { console.log('test1'); res.send("test1 ok") }) // test2介面 app.get("/test2",(req,res) => { console.log('test2'); res.send("test2 ok") }) // 開啟伺服器 app.listen(2000,() => { console.log('開啟在2000埠'); })
現在在瀏覽器中請求/test1 沒有響應,在終端中列印出來
這個中間件的作用在於 請求/開頭的路徑時 優先走中間件的回調函數 中間件里的next()表示是否繼續往下執行 ,有next()就繼續往下走, 沒有next()就不往下走
const express = require("express"); const app = express(); app.use("/",(req,res,next)=>{ console.log("中間件") next() // 是否繼續往下執行 }) // test1介面 app.get("/test1",(req,res) => { console.log('test1'); res.send("test1 ok") }) // test2介面 app.get("/test2",(req,res) => { console.log('test2'); res.send("test2 ok") }) // 開啟伺服器 app.listen(2000,() => { console.log('開啟在2000埠'); })
頁面中
終端列印
簡單來說 在來到/test1介面之前 有個攔截器,這個攔截器中的路徑是/, 所有的介面都先走這個攔截器,在這個攔截器里做邏輯處理,允許它繼續往下走就加next() ,不允許往下走就不用加next(), 因此驗證上文提到的token,就可以在中間件里進行
const express = require("express"); const app = express(); app.use("/",(req,res,next)=>{ console.log("中間件") let {token} = req.query; if(token){ next() // 是否繼續往下執行 }else{ res.send("缺少token") } }) // test1介面 app.get("/test1",(req,res) => { console.log('test1'); res.send(`test1 token為${req.query.token}`) }) // test2介面 app.get("/test2",(req,res) => { console.log('test2'); res.send(`test2 token為${req.query.token}`) }) // 開啟伺服器 app.listen(2000,() => { console.log('開啟在2000埠'); })
瀏覽器中訪問/test1 不帶token欄位
現在帶上token欄位訪問/test2
這就實現了通過中間件做全局攔截,這種中間件屬於自定義攔截器.如果app.use()的第一個參數是 / 表示路徑,則第一個參數可以不寫,如下
app.use("/",(req,res,next)=>{ next() // 是否繼續往下執行 })
等同於
app.use((req,res,next)=>{ next() // 是否繼續往下執行 })
這也可以說為什麼body-parser是一個中間件
const bodyParser = require("body-parser"); app.use(bodyParser.urlencoded({extended:false})) app.use(bodyParser.json())在使用bodyParser.json()的時候也是在app.use()方法里跟了一個函數。 中間件的使用 在app.use()里 可以加上一個回調函數,在回調函數里做一些處理 需要註意的是在合適的時機 使用next()繼續執行後面的操作 為什麼說這一種是全局的 ,因為所有的介面都走這裡 接下來看局部中間件 局部中間件 第一個參數還是路徑 第二個參數是一個function 第三個參數還是function
const express = require("express"); const app = express(); app.get("/demo",(req,res,next) => { console.log('fun1'); },(req,res) => { console.log('fun2'); }) // 開啟伺服器 app.listen(2000,() => { console.log('開啟在2000埠'); })現在請求/demo介面 瀏覽器中沒有響應 因為第一個回調函數里沒有next() 不會走到第二個回調函數里 終端列印
在第一個回調函數中加上next()看看
const express = require("express"); const app = express(); app.get("/demo",(req,res,next) => { console.log('fun1'); next() },(req,res) => { res.send("fun2") console.log('fun2'); }) // 開啟伺服器 app.listen(2000,() => { console.log('開啟在2000埠'); })
瀏覽器中訪問/demo
終端列印
這種叫局部中間件,局部中間件是 在哪個介面里寫就只對哪個介面有用,局部中間件可以寫無數個 只要在合適的地方使用next()就可以一個接一個的往下執行,一般情況下使用局部中間件最多使用一兩個就夠了 使用多個局部中間件 代碼結構如下
app.get("/test",fun1,fun2,fun3,fun4,fun5..)
內置中間件 static 又叫靜態資源目錄 類似於apache的靜態目錄 指定目錄後把圖片 網頁 文件放進去 直接可以訪問到 在項目目錄新建一個文件夾 public 隨便起名,用作靜態資源目錄 只要是中間件都是用app.use()方法
app.use(express.static("./public"))
在public目錄下新建一個index.html文件 寫上內容
瀏覽器訪問/index.html
這樣是直接訪問靜態目錄,如果在public目錄下還有目錄,在瀏覽器中地址欄/後輸入public下的目錄的文件也可以訪問到 還有另一種寫法
app.use("/",express.static("./public"))訪問的地址不變 依然可以打開頁面,因為路徑名字是/時 第一個參數可以省去 如果想定義用戶輸入的路徑 就改第一個參數
app.use("/public/test/",express.static("./public"))
瀏覽器訪問時應該輸/public/test/index.html了
總結 在express中 無論是app.get 還是app.post app.use 只要方法里第一個參數有路徑 都會和瀏覽器訪問的路徑做對比 如果匹配上了就走當前的方法 如果在app.use 和 app.get app.post 的第一個參數中 有相同的路徑 ,當用戶訪問時會優先走到app.use()的方法里 因為app.use()是一個攔截器