express中间件

news/2024/11/8 9:36:22/

文章目录

    • 中间件
    • 定义一个最简单的中间件
    • 自定义中间件
    • 中间件的五个使用注意事项

Express 基于 Connect 构建而成,因此,它也保持了重用中间件来完成基础任务的想法。这就意味着,通过 Express 的 API 方便地构建 Web 应用地同时,又不失构建于 HTTP 模块之上高可用中间件地生态系统。

中间件

由于 Express 是构建于 Connect 之上地,所以,当创建 Express 服务器时可以使用 Connect 兼容地中间件。比如,要托管 image/ 目录下的图片,就可以像这样使用 static 中间件

app.use(express.static(__dirname + '/images'))

注意了,在引入了 Express 之后就可以直接使用 Connect 的中间件了。不需要 require(‘connect’)或者把 connect 作为项目依赖添加到 package.json 文件中。

定义一个最简单的中间件

Express 中间件本质上就是一个 function 处理函数,其具体结构如下:

在这里插入图片描述
这个 next() 函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或者路由。

// 定义一个最简单的中间件
const mw = (req,res,next)=>{console.log('这是最简单的一个中间件')// 把流转关系,转交给下一个中间件或者是路由next()
}

自定义中间件

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

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

首先我们定义一个全局中间件

const express = require('express')
const app = express()
// 这是解析表单数据的中间件
app.use((req, res, next) => {//定义中间件具体的业务逻辑
})
app.listen(80,()=>{console.log('Express server running at http://127.0.0.1')
})

第二步我们来编写监听 req 的 data 事件的代码
在中间件中,需要监听 req 对象的 data 事件,来获取客户端发送到服务器的数据。
如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以 data 事件可能会触发多次,每一次触发
data 事件时,获取到数据只是完整数据的一部分,需要手动对接受到的数据进行拼接。
代码如下:

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

第三步我们来编写监听 req 的 end 事件的代码
当请求体数据接收完毕之后,会自动触发 req 的 end 事件。
因此,我们可以在 req 的 end 事件中,拿到并处理完整的请求体数据。
代码如下:

// 3、监听 req 的 end 事件
req.on('end', () => {//在 str 中存储的就是完整的请求体数据console.log(str)// TODO: 把字符串格式的请求体数据,解析成对象格式
})

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

//导入 querystring 模块
const qs = require('querystring')req.on('end', () => {const body = qs.parse(str)console.log(body)
})

第四步将解析出来的数据对象挂载为 req.body
上游的中间件和下游的中间件以及路由之间,共享用一份 req 和 res。因此,我们可以将解析出来的数据挂在为 req 的自定义属性,命名为 req.body ,供下游使用。
在 end 中写进代码:

req.on('end', () => {const body = qs.parse(str)console.log(body)req.body = bodynext()
})

并且将 res.send('ok') 更改成 res.send(req.body)

最后一步将自定义中间件封装为模块
为了优化代码的结构,我们可以把自定义的中间件函数,封装为独立的模块。
先定义一个常量将 res.use() 内的内容封装起来,然后再向外导入
代码如下:

const bodyParser = ((req, res, next) => {//...
})
module.exports = bodyParser

完整代码

// 导入 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 中存储的就是完整的请求体数据// TODO: 把字符串格式的请求体数据,解析成对象格式const body = qs.parse(str)req.body = bodynext()})
})
module.exports = bodyParser

至此,自定义一个中间件已经全部完成,现在只需要在 test.js 中进行导入就可使用。
测试代码如下:

const express = require('express')
const app = express()
//导入自己封装好的中间件模块
const customBody = require('./类urlencoded的中间件')
//将自定义的2中间件函数,注册成为全局可用的中间件
app.use(customBody)
app.post('/book',(req,res)=>{res.send(req.body)
})
app.listen(80,()=>{console.log('Express server running at http://127.0.0.1')
})

中间件的五个使用注意事项

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

http://www.ppmy.cn/news/11417.html

相关文章

(十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置

前言 本节内容我们主要介绍一下在jenkins中如何集成sonar qube代码质量检查工具,sonar qube可以在流水化项目集成部署前对我们的代码质量检查。开始本节内容前我们需要先搭建好sonar qube服务,关于sonar qube服务的搭建可参考作者往期博客内容&#xff…

set 方法是坏味道?

1 满天Setter public void approve(final long bookId) {...book.setReviewStatus(ReviewStatus.APPROVED);... }对作品进行审核:通过 bookId,找到对应的作品,接下来,将审核状态设置成审核通过。setter 往往是缺乏封装的一种做法…

Android Studio实现一个新闻APP系统源码,仿网易,搜狐等新闻客户端,本科毕业设计必备项目

DavidTGNewsProject ##【Android】最新主流新闻app功能实现。仿网易,搜狐等新闻客户端 完整代码下载地址:Android Studio实现一个新闻APP系统源码 先给大家看一下效果图: 这个项目总体来说虽然不是特别难,但是确实非常常用的功能。是业余时间…

Linux设备树简析

1. 前言 限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。 2. 设备树的来源 在 Linux 中,每个设备驱动,管理一组设备数据,类似面向对象编程中类和其实例对象的关系。一段时…

OMNet++安装pydev

菜单栏->Help->Install New SoftWare->Add 输入 Pydev http://pydev.sourceforge.net/pydev_update_site/5.2.0链接为下载5.2.0版本&#xff0c;若jdk<1.8安装5.2.0之前的版本。\color{blue}{链接为下载5.2.0版本&#xff0c;若jdk<1.8安装5.2.0之前的版本。}链…

电力系统机组组合优化调度(IEEE14节点、IEEE30节点、IEEE118节点)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f4dd;目前更新&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;电力系统相关知识&#xff0c;期刊论文&…

4.R语言【rehsape2包】介绍、melt( )、cast( )函数、其他使用技巧

b站课程视频链接&#xff1a; https://www.bilibili.com/video/BV19x411X7C6?p1 腾讯课堂(最新&#xff0c;但是要花钱&#xff0c;我花99&#x1f622;&#x1f622;元买了&#xff0c;感觉讲的没问题&#xff0c;就是知识点结构有点乱&#xff0c;有点废话&#xff09;&…

caoz的梦呓:谈谈信息不对称与To B业务的难点【推荐】

一、谈谈信息不对称 一直以来&#xff0c;大部分商业行为获利的一个重要基础是信息不对称。互联网时代一个巨大的谎言是&#xff0c;信息是公开透明的&#xff0c;但是很遗憾&#xff0c;这不是真的。 第一&#xff0c;一些非常具有价值的信息资源&#xff0c;并不在互联网流…