express中間件原理(app.use())

1.什么是中間件

中間件就是一個(gè)請(qǐng)求處理方法,用其把用戶(hù)從請(qǐng)求到響應(yīng)的整個(gè)過(guò)程分發(fā)到多個(gè)中間件去處理鲁纠,這樣做的目的是提高代碼的靈活性妖枚,動(dòng)態(tài)可擴(kuò)展的魄衅。簡(jiǎn)單的理解就是:將收到的請(qǐng)求進(jìn)行逐層過(guò)濾峭竣。

2.express中的中間件

請(qǐng)求處理的過(guò)程是:當(dāng)服務(wù)器接收到請(qǐng)求之后,如果服務(wù)器寫(xiě)了多個(gè)中間件晃虫,則按照順序依次匹配皆撩,直到匹配到符合要求的中間件,然后進(jìn)行處理哲银。需要注意的是:同一個(gè)請(qǐng)求所經(jīng)過(guò)的中間件都是同一個(gè)請(qǐng)求對(duì)象和響應(yīng)對(duì)象

中間件分類(lèi):

  1. 應(yīng)用程序級(jí)別中間件

    • 全匹配(不關(guān)心任何請(qǐng)求路徑和請(qǐng)求方法毅访,當(dāng)用戶(hù)請(qǐng)求的時(shí)候如果分發(fā)到該中間件則直接進(jìn)行處理請(qǐng)求操作)

      app.use(function (req,res,next) {
        console.log('全匹配');
        next();
      })
      

      當(dāng)請(qǐng)求經(jīng)過(guò)這個(gè)中間件的時(shí)候,不關(guān)心請(qǐng)求路徑和方法盘榨,直接進(jìn)入該中間件進(jìn)行處理喻粹。其中next是一個(gè)方法,用于調(diào)用下一個(gè)符合條件的中間件草巡。如果不寫(xiě)next守呜,則會(huì)在當(dāng)前中間件停留下來(lái),不會(huì)再去匹配其他中間件山憨。

    • 路徑以/xx/開(kāi)頭的匹配(模糊匹配)

      app.use('/a',function (req,res,next) {
        console.log(3333);
      })
      

      只有以/a/開(kāi)頭的路徑才可以匹配成功并處理查乒,比如:/a/b是可以匹配成功的,但是/ab/b不能匹配成功

  2. 路由級(jí)別中間件(精確匹配)

    必須與請(qǐng)求路徑和請(qǐng)求方法一致才匹配成功

    app.get('/a',(req,res) => {
      console.log(1111);
      res.send('index.html');
    })
    

next使用:

  • 沒(méi)有參數(shù)

查看以下場(chǎng)景:

app.use(function (req,res,next) {
  console.log('全匹配');
  next();
})

app.use('/a',function (req,res,next) {
  console.log(3333);
  next();
})

app.get('/a',(req,res) => {
  console.log(1111);
  res.render('index.html');
})

app.get('/',(req,res) => {
  console.log('2222');
  res.render('index.html',{
    name: 'chen'
  })
})

app.get('/',(req,res) => {
  console.log('44444');
})

瀏覽器輸入url127.0.0.1:3000/依次遍歷每個(gè)中間件郁竟,匹配到第一個(gè)完全匹配的中間件玛迄,打印出全匹配之后,調(diào)用了next棚亩,然后繼續(xù)去匹配符合要求的中間件蓖议,遇到第二個(gè)全匹配中間件不符合以/a/開(kāi)頭的路徑,則直接掠過(guò)讥蟆,繼續(xù)匹配第三個(gè)勒虾,由于是精確匹配,仍然匹配不成功瘸彤,當(dāng)遇到最后一個(gè)中間件的時(shí)候修然,匹配成功,輸出2222质况,可以看出next查找的條件一直都是瀏覽器請(qǐng)求對(duì)象愕宋,也即需要符合127.0.0.1:3000/這個(gè)請(qǐng)求。

再來(lái)另一個(gè)場(chǎng)景:

app.get('/a',(req,res,next) => {
  console.log(1111);
  next();
})
app.get('/a',(req,res) => {
  res.send('ok');
})

當(dāng)訪問(wèn)/a時(shí)结榄,匹配到第一個(gè)中間件輸出1111中贝,遇到next,匹配到第二個(gè)中間件潭陪,返回客戶(hù)端ok雄妥,可以看出,請(qǐng)求匹配中間件是逐一匹配的過(guò)程依溯,而不是后者覆蓋前者的一個(gè)過(guò)程老厌。

  • 帶有參數(shù)

    app.use(function (req,res,next) {
      console.log('全匹配');
      let err = '出錯(cuò)了';
      next(err);
    })
    
    app.use('/a',function (req,res,next) {
      console.log(3333);
      next();
    })
    
    # 帶有四個(gè)參數(shù),且這四個(gè)參數(shù)必須寫(xiě)全
    app.use(function (err,req,res,next) {
      console.log(err);// 出錯(cuò)了
    })
    

    當(dāng)訪問(wèn)/a路徑的時(shí)候黎炉,匹配到第一個(gè)中間件枝秤,遇到next,并且?guī)в袇?shù)慷嗜,則不會(huì)再去匹配其他的中間件淀弹,直接去帶有四個(gè)參數(shù)的中間件去匹配,可以用于統(tǒng)一處理錯(cuò)誤響應(yīng)

使用第三方插件的原理:

由于:同一個(gè)請(qǐng)求所經(jīng)過(guò)的中間件都是同一個(gè)請(qǐng)求對(duì)象和響應(yīng)對(duì)象庆械,所以當(dāng)一個(gè)中間件在請(qǐng)求對(duì)象上添加其他內(nèi)容之后薇溃,其他被匹配成功的中間件可以訪問(wèn)到這個(gè)新增的內(nèi)容,例如:

# 訪問(wèn)'/'
app.use(function (req,res,next) {
  console.log(111);
  req.body = {
    name: 'chen'
  }
  next()
})

app.use('/',function (req,res,next) {
  console.log(req.body.name);// chen
})

以上代碼就展示了當(dāng)匹配到第一個(gè)中間件的時(shí)候缭乘,在請(qǐng)求對(duì)象上新增了body屬性沐序,然后調(diào)用第二個(gè)匹配的中間件的時(shí)候,可以訪問(wèn)到新增的屬性?xún)?nèi)容堕绩。而第三方插件也就是這種方式策幼,修改請(qǐng)求對(duì)象并返回相應(yīng)的內(nèi)容,當(dāng)訪問(wèn)其他中間件的時(shí)候奴紧,就可以訪問(wèn)到第三方插件新增的內(nèi)容特姐,比如:body-parser插件

# 假設(shè)已經(jīng)下載好了body-parser插件
# 引入包
const bodyParser = require('body-parser');
# 將body-parser函數(shù)作為參數(shù)傳遞到app.use中
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

app.get('/',(req,res)=> {
    console.log(req.body);
})

當(dāng)將bodyParser作為函數(shù)傳入中間件時(shí),此時(shí)會(huì)對(duì)請(qǐng)求對(duì)象進(jìn)行添加body屬性等操作黍氮,添加完成之后唐含,務(wù)必會(huì)調(diào)用next,然后繼續(xù)匹配下一個(gè)中間件沫浆,此時(shí)在精確匹配中間件中就可以使用body屬性了觉壶。

從以上一系列的使用過(guò)程中,可以看出件缸,中間件書(shū)寫(xiě)順序還是影響請(qǐng)求響應(yīng)的铜靶。

3.總結(jié)

中間件作為請(qǐng)求的一種過(guò)濾手段,其中express中的中間件中主要依賴(lài)于next連接多個(gè)中間件他炊,同時(shí)由于:同一個(gè)請(qǐng)求所經(jīng)過(guò)的中間件都是同一個(gè)請(qǐng)求對(duì)象和響應(yīng)對(duì)象争剿,使得多個(gè)中間件之間可以進(jìn)行通信。

實(shí)際應(yīng)用:

  • 采用中間件根據(jù)需求配置插件
  • 對(duì)統(tǒng)一請(qǐng)求進(jìn)行過(guò)濾之后再處理請(qǐng)求
  • 對(duì)于出錯(cuò)響應(yīng)可以進(jìn)行統(tǒng)一處理操作
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末痊末,一起剝皮案震驚了整個(gè)濱河市蚕苇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凿叠,老刑警劉巖涩笤,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嚼吞,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蹬碧,警方通過(guò)查閱死者的電腦和手機(jī)舱禽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)恩沽,“玉大人誊稚,你說(shuō)我怎么就攤上這事÷扌模” “怎么了里伯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)渤闷。 經(jīng)常有香客問(wèn)我疾瓮,道長(zhǎng),這世上最難降的妖魔是什么飒箭? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任爷贫,我火速辦了婚禮,結(jié)果婚禮上补憾,老公的妹妹穿的比我還像新娘漫萄。我一直安慰自己,他們只是感情好盈匾,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布腾务。 她就那樣靜靜地躺著,像睡著了一般削饵。 火紅的嫁衣襯著肌膚如雪岩瘦。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,696評(píng)論 1 312
  • 那天窿撬,我揣著相機(jī)與錄音启昧,去河邊找鬼。 笑死劈伴,一個(gè)胖子當(dāng)著我的面吹牛密末,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播跛璧,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼严里,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了追城?” 一聲冷哼從身側(cè)響起刹碾,我...
    開(kāi)封第一講書(shū)人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎座柱,沒(méi)想到半個(gè)月后迷帜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體物舒,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年戏锹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了冠胯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡景用,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出惭蹂,到底是詐尸還是另有隱情伞插,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布盾碗,位于F島的核電站媚污,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏廷雅。R本人自食惡果不足惜耗美,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望航缀。 院中可真熱鬧商架,春花似錦、人聲如沸芥玉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)灿巧。三九已至赶袄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抠藕,已是汗流浹背饿肺。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盾似,地道東北人敬辣。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像零院,于是被迫代替她去往敵國(guó)和親购岗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容