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

1.什么是中间件

中间件就是一个请求处理方法,用其把用户从请求到响应的整个过程分发到多个中间件去处理,这样做的目的是提高代码的灵活性,动态可扩展的。简单的理解就是:将收到的请求进行逐层过滤。

2.express中的中间件

请求处理的过程是:当服务器接收到请求之后,如果服务器写了多个中间件,则按照顺序依次匹配,直到匹配到符合要求的中间件,然后进行处理。需要注意的是:同一个请求所经过的中间件都是同一个请求对象和响应对象

中间件分类:

  1. 应用程序级别中间件

    • 全匹配(不关心任何请求路径和请求方法,当用户请求的时候如果分发到该中间件则直接进行处理请求操作)

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

      当请求经过这个中间件的时候,不关心请求路径和方法,直接进入该中间件进行处理。其中next是一个方法,用于调用下一个符合条件的中间件。如果不写next,则会在当前中间件停留下来,不会再去匹配其他中间件。

    • 路径以/xx/开头的匹配(模糊匹配)

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

      只有以/a/开头的路径才可以匹配成功并处理,比如:/a/b是可以匹配成功的,但是/ab/b不能匹配成功

  2. 路由级别中间件(精确匹配)

    必须与请求路径和请求方法一致才匹配成功

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

next使用:

  • 没有参数

查看以下场景:

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/依次遍历每个中间件,匹配到第一个完全匹配的中间件,打印出全匹配之后,调用了next,然后继续去匹配符合要求的中间件,遇到第二个全匹配中间件不符合以/a/开头的路径,则直接掠过,继续匹配第三个,由于是精确匹配,仍然匹配不成功,当遇到最后一个中间件的时候,匹配成功,输出2222,可以看出next查找的条件一直都是浏览器请求对象,也即需要符合127.0.0.1:3000/这个请求。

再来另一个场景:

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

当访问/a时,匹配到第一个中间件输出1111,遇到next,匹配到第二个中间件,返回客户端ok,可以看出,请求匹配中间件是逐一匹配的过程,而不是后者覆盖前者的一个过程。

  • 带有参数

    app.use(function (req,res,next) {
      console.log('全匹配');
      let err = '出错了';
      next(err);
    })
    
    app.use('/a',function (req,res,next) {
      console.log(3333);
      next();
    })
    
    # 带有四个参数,且这四个参数必须写全
    app.use(function (err,req,res,next) {
      console.log(err);// 出错了
    })
    

    当访问/a路径的时候,匹配到第一个中间件,遇到next,并且带有参数,则不会再去匹配其他的中间件,直接去带有四个参数的中间件去匹配,可以用于统一处理错误响应

使用第三方插件的原理:

由于:同一个请求所经过的中间件都是同一个请求对象和响应对象,所以当一个中间件在请求对象上添加其他内容之后,其他被匹配成功的中间件可以访问到这个新增的内容,例如:

# 访问'/'
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
})

以上代码就展示了当匹配到第一个中间件的时候,在请求对象上新增了body属性,然后调用第二个匹配的中间件的时候,可以访问到新增的属性内容。而第三方插件也就是这种方式,修改请求对象并返回相应的内容,当访问其他中间件的时候,就可以访问到第三方插件新增的内容,比如:body-parser插件

# 假设已经下载好了body-parser插件
# 引入包
const bodyParser = require('body-parser');
# 将body-parser函数作为参数传递到app.use中
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

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

当将bodyParser作为函数传入中间件时,此时会对请求对象进行添加body属性等操作,添加完成之后,务必会调用next,然后继续匹配下一个中间件,此时在精确匹配中间件中就可以使用body属性了。

从以上一系列的使用过程中,可以看出,中间件书写顺序还是影响请求响应的。

3.总结

中间件作为请求的一种过滤手段,其中express中的中间件中主要依赖于next连接多个中间件,同时由于:同一个请求所经过的中间件都是同一个请求对象和响应对象,使得多个中间件之间可以进行通信。

实际应用:

  • 采用中间件根据需求配置插件
  • 对统一请求进行过滤之后再处理请求
  • 对于出错响应可以进行统一处理操作
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,273评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,349评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,709评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,520评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,515评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,158评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,755评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,660评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,203评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,287评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,427评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,122评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,801评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,272评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,393评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,808评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,440评论 2 359

推荐阅读更多精彩内容