express中间件

news2025/4/7 5:12:31

文章目录

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

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 = body
	next()
})

并且将 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 = body
		next()
	})
})
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.coloradmin.cn/o/155739.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于vgg16和pytorch框架进行cifar10数据集的图像分类

vgg16网络模型的实现 这里只讲怎么实现 百度搜到vgg16的网络模型图,用pytorch框架进行实现 图是这样,用pytorch实现就行,pyotrch不太熟悉的话可以去看小土堆的视频 命名mode.py 也可以使用其他名字,在后面的train.py里面改一下也…

【C语言进阶】内存函数和结构体内存对齐

目录一.strerror函数1.错误码变量errno2.strerror函数的使用3.perror函数二.memcpy函数1.函数介绍2.模拟实现三.memmove函数1.函数介绍2.模拟实现四.结构体的内存对齐一.strerror函数 1.错误码变量errno 规定: C语言库函数如果出现运行错误,会将对应错误信息的错误…

联邦学习 (FL) 中常见的3种模型聚合方法的 Tensorflow 示例

联合学习 (FL) 是一种出色的 ML 方法,它使多个设备(例如物联网 (IoT) 设备)或计算机能够在模型训练完成时进行协作,而无需共享它们的数据。 “客户端”是 FL 中使用的计算机和设备,它们可以彼此完全分离并且拥有各自不…

基于Java springmvc+mybatis酒店信息管理系统设计和实现

基于Java springmvcmybatis酒店信息管理系统设计和实现 博主介绍:5年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取…

程序员接私活的几个平台和建议,避免掉坑!

大家对于程序员接私活这件事的看法,褒贬不一。但是你如果确实用钱,价格又合适,那就大胆去接。 如果不那么缺钱,那么接私活之前先考虑清楚,如果自己将空余时间用在接私活所产生的价值是不是大于提升自己。如果是的话&a…

2022年 大学生工程训练比赛[物料搬运]

本人和团结参加了2022年大学生工程训练(简称工训赛)校赛选拔,准备了几个月的时间和花费了较多的资金,由于疫情等多种情况,很遗憾未能参加湖南省省赛,过了这么久还是写个博客记录参赛准备和调试过程。 目录 一、比赛要求 二、整体…

第十章面向对象编程(高级部分)

10.1 类变量和类方法(关键字static) 10.1.31类变量快速入门 思考: 如果,设计一个 int count 表示总人数,我们在创建一个小孩时,就把 count 加 1,并且 count 是所有对象共享的就 ok 了! package com.hspedu.static_;public class ChildGame {…

MS【1】:Metric

文章目录前言1. Dice Loss1.1. Dice coefficient1.2. F1 score - Dice1.3. Dice Loss2. Sensitivity & Specificity2.1. Sensitivity2.2. Specificity3. Hausdorff distance3.1. 概念3.2. 单向 Hausdorff distance3.3. 双向 Hausdorff distance3.4. 部分 Hausdorff distanc…

使用ResNet18实现CIFAR100数据集的训练

如果对你有用的话,希望能够点赞支持一下,这样我就能有更多的动力更新更多的学习笔记了。😄😄 使用ResNet进行CIFAR-10数据集进行测试,这里使用的是将CIFAR-10数据集的分辨率扩大到32X32,因为算力相关的…

二、数据仓库模型设计

数据仓库模型设计一、数据模型二、关系模型三、维度模型1、事实表(1)事务事实表(2)周期快照事实表(3)累计快照事实表(4)无事实的事实表2、维度表3、维度模型类型(1&#…

LVGL学习笔记16 - 进度条Bar

目录 1. Parts 2. 模式 2.1 LV_BAR_MODE_SYMMETRICAL:对称模式 2.2 LV_BAR_MODE_RANGE:范围模式 3. 动画 4. 样式 4.1 方向 4.2 渐变色 4.3 增加边框 4.4 滚动条方向 进度条有一个背景和一个指示器组成,通过lv_bar_create创建对象。…

mysql多表查询

一、关联查询(联合查询) 1.1 什么是关联查询 关联查询:两个或者多个表,一起查询。 前提条件: 这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段&#x…

初识IL2CPP

在Unity中进行打包时,有两种打包方式选择:Mono和IL2CPP Mono和IL2Cpp是Unity的脚本后处理方式,通过脚本后处理实现Unity的跨平台 1.Mono (1). Mono组成组件: C#编辑器,CLI虚拟机,以及核心类别程序库 (2).跨平台过程 Mo…

【Linux】多线程概念

目录🌈前言🌸1、Linux线程概念🍡1.1、概念🍢1.2、线程的优点🍧1.3、线程的缺点🍨1.4、线程的异常和用途🌺2、Linux下进程 vs 线程🌈前言 这篇文章给大家带来线程的学习!…

PID算法入门(一)

1.简介 PID是Proportional(比例), Integral(积分), Differential(微分)的首字母缩写,他是一种结合比例,积分,微分三个环节于一体的闭环控制算法. 2.PID各环节 2.1比例环节 成比例地反应控制系统的偏差信号,即输出&a…

Codeforces Round #843 (Div. 2) A1 —— D

题目地址:Dashboard - Codeforces Round #843 (Div. 2) - Codeforces一个不知名大学生,江湖人称菜狗 original author: jacky Li Email : 3435673055qq.com Time of completion:2023.1.11 Last edited: 2023.1.11 目录 ​编辑 A1. Gardener…

读论文——day61 目标检测模型的决策依据与可信度分析

目标检测模型的决策依据与可信度分析本文贡献及原文1 相关工作(略看)1.3 目标检测模型2 背景知识(LIME)2.2 LIME3 目标检测决策依据及可信度分析3.1 决策依据3.2 对目标检测模型的预测进行可信度评价4 基于 LIME 的目标检测模型解…

(第四章)OpenGL超级宝典学习:必要的数学知识

必要的数学知识 前言 在本章当中,作者着重介绍了几个和3D图形学重要的数学知识,线性代数基础好的同学可以直接绕过本章,说实话这篇博客写到这里,我是非常犹豫的,本章节的内容可以说是很基础,但是相当…

SSM框架01_Spring

有一个效应叫知识诅咒:自己一旦知道了某事,就无法想象这件事在未知者眼中的样子。00-Spring课程介绍01-初识Spring今天所学的Spring其实是Spring家族中的Spring Framework;Spring Fra是Spring家族中其他框架的底层基础,学好Spring可以为其他S…

Morse1题解

原理摩尔斯电码和电报简单说一下电报和摩尔斯电码的原理最简单的电报模型就是一个电源,一个开关和一个电磁铁当需要长距离使用时候,需要用到继电器按下开关,电磁铁会吸引磁铁长按开关,电磁铁就会闭合一段时间,留下一划…