Node.js 知识整理之第三篇(Express中间件)

简介

  • 本篇博客主要记录了express中间件

Express 中间件

中间件格式

  • 中间件函数的形参数列表中,必须有 next参数,而路由处理参数中只包含req 和 res
  • 书写格式如下:
    const express = require('express')
    const app = express()
    app.get('/',(req,res,next)=>{
       next()
    })
    app.listen('8088',()=>{
        console.log('express server running at http://127.0.0.1:8088')
    })

next 函数的作用

  • next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或者路由
  • avatar

定义中间件

    const  express = require('express')
    const  app = express()
    //定义一个中间件
    const c1 = function (req,res,next){
        console.log('这是一个中间件函数')
        // 把流转关系,转交给下一个中间件或路由
        next()
    }
    app.listen('8088',()=>{
        console.log('express server running is http://127.0.0.1:8088')
    })

全局生效的中间件

  • 客户端发起的任何请求,到达服务器之后,都会触发中间件,叫做全局生效的中间件
  • 通过app.use(中间件函数),即可定义一个 全局生效的中间件,示例代码如下:
    const express = require('express')
    const app = express()
    //定义一个中间件
    const c1 = function (req, res, next) {
        console.log('这是一个中间件函数')
        // 把流转关系,转交给下一个中间件或路由
        next()
    }
    //将cl函数注册为全局生效的中间件
    app.use(c1)
    
    app.get('/', (req, res) => {
        console.log('调用了/这个路由')
        res.send('home page')
    })
    app.post('/user', (req, res) => {
        console.log('调用了/user这个路由')
        res.send('user page')
    })
    app.listen('8088', () => {
        console.log('express server running is http://127.0.0.1:8088')
    })

定义中间件简化形式

    const express = require('express')
    const app = express()
    // 定义全局中间件的简化形式
    app.use((req,res,next)=>{
        console.log('定义全局中间件的简化形式')
        next()
    })
    app.get('/', (req, res) => {
        console.log('调用了/这个路由')
        res.send('home page')
    })
    app.listen('8088', () => {
        console.log('express server running is http://127.0.0.1:8088')
    })

中间件的作用

  • 多个中间件之间,共享一份req 和 res ,基于这样的特性,我们可以在上游的中间件中,统一的为req 或 res对象添加自定义的属性和方法,供下游的中间件或者路由使用。
    const express = require('express')
    const app = express()
    // 定义全局中间件的简化形式
    app.use((req, res, next) => {
    //    获取请求到达服务器的时间
    const  time = Date.now()
        //为 req 对象 拦截自定义属性,从而把时间共享给后面的所有路由
        req.startTime = time
        next()
    })
    app.get('/', (req, res) => {
        res.send('home page' + req.startTime)
    })
    app.post('/user', (req, res) => {
        res.send('user page' +req.startTime)
    })
    app.listen('8088', () => {
        console.log('express server running is http://127.0.0.1:8088')
    })

定义多个全局中间件

  • 可以用app.use() 连续定义多个全局中间件,客户端请求到达服务器之后,会按照中间件的定义的先后顺序依次进行调用, 示例代码如下:
    /**
     *定义多个全局中间件
     * */
    const express = require('express')
    const app = express()
    //第一个全局中间件
    app.use(function (req, res, next) {
        console.log('第一个全局中间件')
        next()
    })
    //第二个全局中间件
    app.use(function (req, res, next) {
        console.log('第二个全局中间件')
        next()
    })
    //定义路由
    app.get('/', (req, res) => {
        res.send('home page')
    })
    app.listen('8088',()=>{
        console.log('express server running at http://127.0.0.1:8088')
    })

局部定义的中间件

  • 不使用 app.use() 定义的中间件叫做 局部生效的中间件,代码示例如下:
  /**
   *定义局部生效的中间件
   * */
  const express = require('express')
  const app = express()
  const ct = (req,res,next)=>{
      console.log('局部生效中间件函数')
    next()
  }
  //定义路由
  app.get('/',ct, (req, res) => {
      res.send('home page')
  })
  app.post('/user', (req, res) => {
      res.send('user page')
  })
  app.listen('8088',()=>{
      console.log('express server running at http://127.0.0.1:8088')
  })

定义多个局部中间件,代码示例如下:

    /**
     *定义多个局部中间件
     * */
    const express = require('express')
    const app = express()
    const ct1 = (req,res,next)=>{
        console.log('第一个局部中间件函数')
      next()
    }
    const ct2 = (req,res,next)=>{
        console.log('第二个局部中间件函数')
        next()
    }
    const ct3 = (req,res,next)=>{
        console.log('第三个局部中间件函数')
        next()
    }
    const ct4 = (req,res,next)=>{
        console.log('第四个局部中间件函数')
        next()
    }
    //定义路由
    app.get('/',ct1,ct2, (req, res) => {
        res.send('home page')
    })
    app.post('/user',[ct3,ct4], (req, res) => {
        res.send('user page')
    })
    app.listen('8088',()=>{
        console.log('express server running at http://127.0.0.1:8088')
    })

使用中间件的注意事项

  • 一定要在路由之前注册中间件
  • 客户端发送过来的请求,可以连续调用多个中间件进行处理
  • 执行完中间件的业务代码之后,不要忘记调用next()函数
  • 为了防止代码逻辑混乱,调用next()函数之后不要再写额外的代码
  • 连续调用多个中间件时,多个中间件之间,共享 req 和 res 对象

中间件的分类

  • 注意:除了错误级别的中间件,其他的中间件必须在路由之前配置
应用级别的中间件
  • 通过 app.use()或者app.get()或app.post() 绑定在app示例上的中间件,叫做应用级别的中间件
路由级别的中间件
  • 绑定到 express.Router() 实例上的中间件,叫做路由级别的中间件,它的用法和应用级别的中间件没有任何区别,只不过,应用级别的中间件绑定在app实例上,路由级别的中间件绑定在router实例上
错误级别的中间件
  • 作用: 专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题
  • 格式: 错误级别中间件中的function处理函数中,必须有4个形参,形参顺序从前到后,分别是(err,req,res,next).
  • 注意: 错误级别的中间件,必须注册在所有路由之后
  • 代码实例如下:
/**
 * 错误级别中间件
 * **/
const  express = require('express')
const app = express()
//1.定义路由
app.get('/',(req,res)=>{
//   人为制造错误
    throw  new Error('服务器内部出现error')
    res.send('home page')
})
//2.定义错误级别的中间件,捕获整个项目中的异常错误,从而防止程序的崩溃
app.use((err,req,res,next)=>{
    //2.1 在服务器中打印错误
    console.log('发生了错误'+err.message)
    //2.2 向客户端响应错误相关的内容
    res.send('Error'+err.message)
})
//调用 app.listen 方法,指定端口号,启动web服务器
app.listen('8088',()=>{
    console.log('express server running at http://127.0.0.1:8088')
})
Express的内置中间件
  1. express.static 快速托管静态资源的内部中间件,例如:HTML文件,图片,CSS样式等(无兼容性)
  2. express.json 解析JSON格式的请求体数据,(有兼容性,仅在4.16.0+ 版本中使用)
  3. express.urlencoded 解析 URL-encoded 格式的请求体数据(有兼容性,仅在4.16.0+ 版本中使用)
/**
 * 内置中间件的使用 express.json()和express.urlencoded({extended:false})
 * **/
const  express = require('express')
const app = express()
//注意:除了错误级别的中间件,其他的中间件必须在路由之前配置
// 通过express.json 这个中间件。解析表单中json 格式的数据
// 通过express.urlencoded()这个中间件,来解析表单中url-encoded 格式的数据(解析 x-www-form-urlencoded 格式的表单数据)
app.use(express.json())
app.use(express.urlencoded({extended:false}))

app.post('/user',(req,res)=>{
    //在服务器中,可以使用 req.body 这个属性,来接收客户端发送过来的请求体数据
    //默认情况下,如果不配置解析表单数据的中间件,则req.body 默认等于 undefined
    console.log(req.body)
    res.send('ok')
})
app.post('/book',(req,res)=>{
    //在服务器中,可以使用 req.body 这个属性,来接收客户端发送过来的请求体数据 和url-encoded 格式的数据

    console.log(req.body)
    res.send('bookok')
})
//调用 app.listen 方法,指定端口号,启动web服务器
app.listen('8088',()=>{
    console.log('express server running at http://127.0.0.1:8088')
})

第三方的中间件
  • 非Express 官方内置的,而是由第三方提供出来的中间件,叫做第三方中间件,在项目中大家可以按需下载并配置第三方中间件,从而提高项目的开发效率
  • 例如使用body-parser 第三方中间件解析请求体数据
  • 输入 npm install body-parser 安装中间件
  • 使用require导入中间件
  • 调用 app.use ()注册并使用中间件
  • 使用方法如下:
    const  express = require('express')
    const app = express()
    //1导入解析数据的中间件body-parser
    const parser = require('body-parser')
    // 2.使用app.use 注册中间件
    app.use(parser.urlencoded({extended:false}))
    
    app.post('/book',(req,res)=>{
        //,如果不配置解析表单数据的中间件,则req.body 默认等于 undefined
        console.log(req.body)
        res.send('ok1')
    })
    //调用 app.listen 方法,指定端口号,启动web服务器
    app.listen('8088',()=>{
        console.log('express server running at http://127.0.0.1:8088')
    })

自定义中间件

  • 在文件目录下创建两个js文件,自定义模块化拆分.js 和 conmon-body-parser.js
  • 在 自定义模块化拆分.js 文件中导入封装的中间件
const express = require('express')
const app = express()
// 1.导入之间封装的中间件
const custbodyparser =require('./conmon-body-parser')
// 2.将自定义的中间件,注册为全局可用的中间件
app.use(custbodyparser)
app.post('/book', (req, res) => {
    res.send(req.body)
})
app.listen('8088', () => {
    console.log('express server running at http://127.0.0.1:8088')
})
  • 在conmon-body-parser.js文件中进行封装中间件
// 导入node.js 内置的 querystring 模块
const qs = require('querystring')
const bodyparser = (req, res, next) => {
    // 1.定义一个str字符串,专门用来存储客户端发送过来的请求数据
    let str = ''
    // 2.监听req 的data事件
    req.on('data', (chunk) => {
        str += chunk
    })
    // 3.监听req的 end事件
    req.on('end', () => {
        //在 str中存放的是完整的请求体数据
        console.log(str)
        //    todo:把字符串格式的请求体数据,解析成对象格式
        const body = qs.parse(str)
        console.log(body)
        req.body = body
        next()
    })
}
module.exports=bodyparser

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值