1.中间件概念

所谓中间件,特指业务流程中间处理环节

2.全局生效中间件
  • 客户端发起的的任何请求,到达服务器之后,都会触发的的中间件

  • 通过调用 app.use(中间件函数),即可定一个全局中间件

// 导入需要的模块
  const express = require('express')
  const app = express()
  
  // // 定义一个简单中间件函数
  // const kw = (req,res,next)=> {
  //     console.log('这是最简单中间件');
  //     // 把流转关系传给下一个中间件或者路由
  //     next()
  // }
  
  // // 全局生效中间件
  // app.use(kw)
  
  // 简化
  // 第一个中间件
  app.use((req,res,next)=>{
      console.log('这是最简单中间件');
      next()
  })
  // 第二个中间件
  app.use((req,res,next)=>{
      console.log('这是最简单中间件3333');
      next()
  })
  
  app.get('/',(req,res)=>{
      console.log('调用了/这个路由');
      res.send('fdff')
  })
  
  app.listen(3000,()=>{
      console.log('完成');
  })
3.中间件作用

多个中间件之间,共享一份 req , res, 基于这样特性,我们可以在上游中间件中,统一为 req, res对象添加自定义属性方法,供下游中间件或路由器进行使用

4.局部生效的中间件
  • 不使用 app.use() 定义的中间件,叫做局部中间件
    const express = require('express')
    const app = express()
    
    // 中间件
    const mv1 = (req,res,next) => {
        console.log('这是中间件数');
        next()
    }
    
    app.get('/',(req,res)=>{
        res.send('ggjg')
    })
    
    app.get('/user',mv1,(req,res)=>{
        res.send('ffddf')
    })
    
    app.listen(3000,()=>{
        console.log('完成');
    })
5.中间件注意事项
  • 一定要在路由之前注册中间件

  • 客户端发送过来的请求,可以连续调用多个中间件进行处理

  • 执行完中间件的业务代码之后,不要忘记调用 next() 函数

  • 为了防止代码逻辑混乱,调用 next() 函数后不要再写额外的代码

  • 连续调用多个中间件时,多个中间件之间,共享 reqres 对象

6.中间件分类
  • 应用级别的中间件

    • 通过 app.use()app.get()app.post() ,绑定到 app 实例上的中间件,叫做应用级别的中间件
  • 路由级别的中间件

    • 绑定到 express.Router() 实例上的中间件,叫做路由级别的中间件
  • 错误级别的中间件

    • 注意:错误级别中间件必须注册在所有路由之后
    const express = require('express')
    const app = express()
    app.get('/',(req,res)=>{
     throw new Error('服务器内部发生错误')
     res.send('fsaf')
    })
    // 错误级别中间件,放在所有路由最后面
    app.use((err,req,res,next)=>{
     console.log('发生了错误'+err.message);
     res.send(err.message)
    })
    app.listen(3000,()=>{
     console.log('完成');
    })
    
  • Express 内置的中间件

    • express.static 快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS` 样式等(无兼容性)
    • express.json解析JSON格式的请求体数据(**有兼容性**,仅在4.16.0+` 版本中可用)
    const express = require('express')
    const app = express()
    app.use(express.json())
    app.post('/user',(req,res)=>{
     // req.body接收客户端请求体
     res.send(req.body)
    })
    app.listen(3000,()=>{
     console.log('完成');
    })
    
    • express.urlencoded解析URL-encoded格式的请求体数据(**有兼容性**,仅在4.16.0+` 版本中可用),用法同上
  • 第三方的中间件

7.自定义中间件
  • 自己手动模拟一个类似于 express.urlencoded 这样的中间件
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 4. 导入 Node 内置模块 querystring
const qs = require('querystring')
// 解析表单数据的中间件
app.use((req,res,next)=>{
    // 定义中间价具体的业务逻辑
// 1. 定义一个 str 字符串,专门用来存储客户端发送过来的请求体数据
    let str = ''
// 2. 监听 req 的 data 事件
    req.on('data',rem =>{
        str+=rem
    })
// 3. 监听 req 的 end 事件
    req.on('end',()=>{
        // 5. 调用 qs.parse() 方法,将查询字符串解析成对象
        const arr = qs.parse(str)
        req.body=arr
        next()
    })
})
    app.post('/user',(req,res)=>{
        // 6. 将解析出来的数据对象挂载为 req.body 属性
        res.send(req.body)
    })
// 调用 app.listen方法,指定端口号并启动 web 服务器
app.listen(3000,()=>{
    console.log('完成');
})
  • 在上面基础上封装

    服务器

    // 导入 express 模块
    const express = require('express')
    // 创建 express 的服务器实例
    const app = express()
    // 4. 导入 Node 内置模块 querystring
    // 导入中间件模块
    const arr = require('./封装中间件')
    // 全局中间件
    app.use(arr)
    app.post('/user', (req, res) => {
        // 6. 将解析出来的数据对象挂载为 req.body 属性
        res.send(req.body)
    })
    // 调用 app.listen方法,指定端口号并启动 web 服务器
    app.listen(3000, () => {
        console.log('完成');
    })
    

中间件

const qs = require('querystring')
// 解析表单数据的中间件
module.exports=((req, res, next) => {
    // 定义中间价具体的业务逻辑
    // 1. 定义一个 str 字符串,专门用来存储客户端发送过来的请求体数据
    let str = ''
    // 2. 监听 req 的 data 事件
    req.on('data', rem => {
        str += rem
    })
    // 3. 监听 req 的 end 事件
    req.on('end', () => {
        // 5. 调用 qs.parse() 方法,将查询字符串解析成对象
        const arr = qs.parse(str)
        req.body = arr
        next()
    })
})