• Nodejs -- Express 自定义中间件并进行封装


    自定义中间件

    1 需求描述与实现步骤

    自己手动模拟一个类似于express.urlencoded这样的中间件,来解析POST提交到服务器的表单数据。

    1. 定义中间件
    2. 监听req的data事件
    3. 监听req的end事件
    4. 使用querystring模块解析请求体数据
    5. 将解析出来的数据对象挂载为req.body
    6. 将自定义中间件封装为模块

    2 定义中间件

    使用app.use()来定义全局生效的中间件,代码如下:

    app.use((req, res, next) => {
        // 中间件的业务逻辑
    	next()
    })
    
    • 1
    • 2
    • 3
    • 4

    3 监听req的data事件

    在中间件中,需要监听req对象的data事件,来获取客户端发送到服务器的数据。

    如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以dta事件可能会触发多次,每一次触发dta事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接

    // 1. 定义一个 str 字符串,专门用来存储客户端发送过来的请求体数据
    let str = ''
    
    // 2. 监听 req 的data事件
    req.on('data', (chunk) => {
        str += chunk
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4 监听req的end事件

    请求体数据接收完毕之后,会自动触发req的end事件。

    因此,我们可以在req的end事件中,拿到并处理完整的请求体数据。示例代码如下:

    // 3. 监听 req 对象的 end 事件
    req.on('end', () => {
        // 在str中存放的就是完整的请求体数据
        console.log(str)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5 使用querystring模块解析请求体数据

    Node.js内置了一个querystring模块,专门用来处理查询字符串。通过这个模块提供的parse()函数,可以轻松把查询字符串,解析成对象的格式。示例代码如下:

    const qs = require('querystring')
    
    const body = qs.parse(str)
    
    • 1
    • 2
    • 3

    6 将解析出来的数据对象挂载为req.body

    上游的中间件和下游的中间件及路由之间,共享同一份req和res。因此,我们可以将解析出来的数据,挂载为req的自定义属性,命茗为req.body, 供下游使用。示例代码如下:

    // 3. 监听 req 对象的 end 事件
    req.on('end', () => {
        // 在str中存放的就是完整的请求体数据
        const body = qs.parse(str)
        req.body = body
        console.log("中间件", req.body)
        next()
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    7 自定义中间件

    为了优化代码的结构,我们可以把自定义的中间件函数,封装为独立的模块,示例代码如下:

    //custom-body-parser.js 模块中的代码
    const qs = require('querystring')
    function bodyParser(req,res,next){/*省略其它代码*/}
    module.exports = bodyParser//向外导出解析请求体数据的中间件函数
    
    // ------------------分隔线----------------------
    //1,导入自定义的中间件模块
    const myBodyParser = require('custom-body-parser')
    //2,注册自定义的中间件模块
    app.use(myBodyParser)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    8 最终代码

    index.js

    // 导入express
    const express = require('express')
    const bodyParser = require('./custom-body-parser')
    
    // 创建web服务器
    const app = express()
    
    // 解析表单数据的中间件
    app.use(bodyParser)
    
    app.post('/user', (req, res) => {
        console.log("路由接口:", req.body)
        res.send(req.body)
    })
    
    // 启动服务器
    app.listen(80, () => {
        console.log('express server running at http://127.0.0.1')
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    custom-body-parser.js

    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中存放的就是完整的请求体数据
            req.body = qs.parse(str)
            console.log("中间件", req.body)
            next()
        })
    }
    
    module.exports = bodyParser
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

  • 相关阅读:
    Grafana+Prometheus+Windows_exporter+Mysql_exporter
    ABAP bgRFC
    QT下TCP协议实现数据网络传输
    面试记录1
    第28节-PhotoShop基础课程-蒙版
    启动两个线程,用另一个线程以通知的终止另一个线程
    嵌入式分享合集4
    Maven Eclipse
    Qt 子线程中无限递归的信号槽导致主线程槽失效的原因和解决办法
    C-DS二叉树_另一棵树的子树
  • 原文地址:https://blog.csdn.net/qq_46311811/article/details/128088151