• Node.js基础---Express中间件


    1. 概念

    1.什么是中间件

            中间件(Middleware),特指业务流程的中间处理环节

    2. Express 中间件的调用流程

            当一个请求到达 Express 的服务器后,可以连续调用多个中间件,从而对这次请求进行预处理

    3. Express 中间件格式

           Express 的中间件,本质上是一个 function 处理函数,Express 中间件格式如下

            中间件函数的形参列表中,必须包含 next 参数,而路由处理函数中只包含 req 和 res

    4. next 函数的作用

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

    2. 中间件函数

    1. 定义

    1. // 常量 mv 所指向的就是一个中间件函数
    2. const mv = function ( req, res, next) {
    3. console.log('中间件demo')
    4. // 注意: 在当前中间件的业务处理完毕后,必须调用 next() 函数
    5. // 表示把流转关系转交给下一个中间件或路由
    6. next()
    7. }

    2. 全局生效的中间件

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

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

    1. // 常量 mv 所指向的就是一个中间件函数
    2. const mv = function ( req, res, next) {
    3. console.log('中间件demo')
    4. next()
    5. }
    6. // 全局生效的中间件
    7. app.use(mv)

    3. 定义全局中间件的简化形式

    1. // 全局生效的中间件
    2. app.use(function (req, res, next){
    3. console.log('demo')
    4. next()
    5. })

    4. 中间件的作用

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

    5. 定义多个全局中间件

            可以使用 app.use() 连续定义多个全局中间件,客户端请求到达服务器后,会按照中间件定义的先后顺序依次进行调用

    6. 局部生效的中间件

            不使用 app.use() 定义的中间件,即局部生效的中间件

            只在当前路由生效

    1. const mv1 = function(req, res, next) {
    2. console.log('中间件函数')
    3. next()
    4. }
    5. // mv1 中间件只在当前路由生效
    6. app.get('/', mv1, function(req, res) {
    7. res,send('get')
    8. })
    9. // 此路由不生效
    10. app.get('/user', function(req, res) {
    11. res,send('get1')
    12. })

    7. 定义多个局部中间件

            两种等价方式定义

    1. app.get('/', mv1, mv2, function(req, res) { res,send('get') })
    2. app.get('/', [mv1, mv2], function(req, res) { res,send('get') })

    8. 中间件的5个使用注意事项

            ①  一定要在路由之前注册中间件

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

            ③  执行完中间件的业务代码,需要调用 next() 函数

            ④  防止代码逻辑混乱,调用完 next() 函数后不要再写额外代码 

            ⑤  连续多个中间件时,多个中间件之间,共享 req 和 res 对象

    3. 中间件的分类

            Express 官方把常见的中间件用法,分为了五大类

                    ①  应用级别的中间件

                    ②  路由级别的中间件

                    ③  错误级别的中间件

                    ④  Express 内置的中间件

                    ⑤  第三方的中间件

    1. 应用级别的中间件

            通过 app.use() 或 app.get() 或 app.post()绑定到app实例上的中间件,叫做应用级别的中间件        全局中间件和局部中间件

    1. // 应用级别的中间件 (全局中间件)
    2. app.use((req, res, next) => {
    3. next()
    4. })
    5. // 应用级别的中间件 (局部中间件)
    6. app.get('/', mv1, (req, res, next) => {
    7. res.send('局部')
    8. })

    2. 路由级别的中间件 

            绑定到 express.Router() 实例上的中间件,叫做路由级别的中间件,它的用法和应用级别中间件没有区别,区别在于,应用级别中间件是绑定在 app 实例上的,路由级别中间件绑定到 router 实例上的

    1. const app = express()
    2. const router = express.Router()
    3. // 路由级别的中间件
    4. router.use(function (req, res, next) {
    5. console.log('路由级别中间件')
    6. next()
    7. })
    8. app.use('/', router)

    3. 错误级别的中间件

            作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题

            格式:必须要有 4 个形参,从前到后分别是 (err, req, res, next)

    1. app.get('/', function(req, res) { // 路由
    2. throw new Error('错误!') // 抛出自定义错误
    3. res.send('get')
    4. })
    5. app.use(function (err, req, res, next) { // 错误级别的中间件
    6. console.log('发生了错误' + err.message) // 服务器打印错误消息
    7. res,send('Error' + err.message) // 向客户端响应错误信息相关内容
    8. })

            注意:错误级别的中间件,必须注册在所有路由之后

    4. Express内置的中间件

            Express 4.16.0版本后,Express 内置了3个常用的中间件

            ①  express.static 快速托管静态资源的内置中间件,例如:HTML文件,图片,css样式(无兼容性

            ②  express.json 解析JSON格式的请求体数据(有兼容性,在4.16.0+版本可用)

            ③  express.urlencoded 解析 URL-encoded 格式的请求体数据(有兼容性,在4.16.0+版本可用)

    1. // 配置解析 application/json 格式数据的内置中间件
    2. app.use(express.json())
    3. // 配置解析 application/x-www-form-urlencode 格式数据的内置中间件
    4. app.use(express.urlencoded({ extend: false }))

    5. 第三方的中间件

            非 Express 官方内置的,是第三方开发出来的中间件,叫第三方中间件,项目中可以按需下载并配置第三方中间件

            在 express@4.16.0 之前的版本中,经常使用 body-parser 第三方中间件来解析请求体数据:

            ①  运行 npm i body-parser 安装

            ②  使用 require 导入中间件

            ③  调用 app.use() 注册并使用中间件

            注意:Express 内置的 express.urlencoded 中间件,就是基于 body-parser 进一步封装的

    4.  自定义中间件

    1. 需求描述与实现步骤

            需求:手动模拟类似于 express.urlencoded 的中间件,解析POST提交到服务器的表单数据

            实现步骤:

                    ①   定义中间件

                    ②   监听 req 的 data 事件

                    ③   监听 req 的 end 事件

                    ④   使用 queryString 模块解析请求体数据

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

                    ⑥   将自定义中间件封装为模块

    2. 定义中间件

            使用 app.use() 定义全局生效的中间件

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

    3. 监听 req 的 data 事件

            获取客户端发送到服务器的数据

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

    1. // 定义变量 储存客户端发来的请求体数据
    2. let str = ''
    3. // 监听 req 对象的 data 事件
    4. req.on('data', (chunk) => {
    5. // 拼接请求体数据,隐式转换为字符串
    6. str += chunk
    7. })

    4. 监听 req 的 end 事件

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

            可以在 req 的 end 事件中,拿到并处理完整的请求体数据

    1. // 监听 req 对象的 end 事件
    2. req.on('end', () => {
    3. console.log(str) // 打印完整请求体数据
    4. // TOOD: 把字符串的请求体数据,解析成对象格式
    5. })

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

            Node.js 内置了一个 querystring 模块,专门用来处理查询字符串。通过这个模块提供的 parse(), 可以把查询字符串解析成对象的格式

    1. // 导入处理 querystring 的 Node.js 内置模块
    2. const qs = require('querystring')
    3. // 调用 qs.parse() 方法 把查询字符串解析为对象
    4. const body = qs.parse(str)

            注意:qs被弃用

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

            上游中间件和下游中间件及路由之间,共享同一份 req 和 res。可以将解析出来的数据,挂载为 req 的自定义属性,命名为 req.body,供下游使用

    1. req.on('end', () => {
    2. const body = qs.parse(srt) // 调用 qs.parse() 方法把查询字符串解析成对象
    3. req.body = body // 解析出来的请求体对象瓜子
    4. next() // 调用 next(),执行后续逻辑
    5. })

    7. 将自定义中间件封装为模块

            优化结构,封装为独立模块

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

  • 相关阅读:
    AOSP10 替换系统launcher
    Unity Golang项目教程-创建项目
    Linux重装系统过程(多图)
    FPGA信号处理系列文章——相关与卷积
    什么是阿里云轻量应用服务器?
    C#10新特性-lambda 表达式和方法组的改进
    IDEA插件开发(10)---Components
    数学建模学习(109):几行代码训练几十种机器学习模型
    【网站架构】如何长久运行升级?高可用部署只是基础,巡检、监控、应用数据备份、日志、灰度发布
    uni-app 在已有的数据对象中动态添加更多的数据对象
  • 原文地址:https://blog.csdn.net/Anorry/article/details/136376797