在nodejs中的express服务器中,中间件是非常重要的。客户端每次发送请求携带数据到服务器的时候,中间会层层处理然后才会到达路由中,最后在路由中才会将经过层层处理过后的数据响应给客户端,在这中间的处理就是由中间件处理的。
中间件概念:中间件就是特指在业务流程中的中间处理环节。
生活中中间件的实例
Express中间件的调用流程
当一个请求到达Express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。
Express中间件的格式
Express中间件,本质上就是一个function处理函数,Express中间件格式如下
注意:中间件函数的参数列表中,必须包含next参数。而路由处理函数中只包含req和res参数。因此中间件函数和路由处理函数之间的区别就是多了一个next参数。
next参数的作用
next参数实质上也是一个function函数。
next函数的主要作用:将数据和流转关系转交给下一个中间件或者路由上。因此如果没有调用next函数,数据就不会向下传递,后面的中间件和路由就也不会执行。所以next函数是实现多个中间件连续调用的关键。
定义一个最简单的中间件
//定以常量,接收中间件函数
const mw=(req,res,next)=>{
console.log('这是一个最简单的中间件');
//调用next函数,让流转关系转到下一个中间件或者路由
next();
}
全局生效中间件
概念:客户端发送的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效中间件。
通过调用app.use(中间件函数)方法,即可定义一个全局生效的中间件。
//定以常量,接收中间件函数
const mw=(req,res,next)=>{
console.log('这是一个最简单的中间件');
//调用next函数,让流转关系转到下一个中间件或者路由
next();
}
//注册全局生效的中间件,app是实例化的服务器
app.use(mw)
定义全局生效的中间件的简化方式
//注册全局生效的中间件,app是实例化的服务器
app.use((req,res,next)=>{
console.log('这是一个最简单的中间件');
//调用next函数,让流转关系转到下一个中间件或者路由
next();
})
中间件的实际开发作用
中间件和路由共享一个req和res参数,因此可以对客户端传递过来的数据进行处理然后在路由中将数据响应回客户端。
理解实例:
app.use((req,res,next)=>{
//获取到请求到达服务器的时间
const time=Date.now();
//为req挂载自定义属性,将时间赋值给这个自定义属性,后面的路由以及中间件都可以访问这个数据
req.startTime=time;
next();
})
定义多个全局中间件:就是多次调用app.use()方法,客服端的请求到达服务器过后,按照中间件的注册先后顺序依次调用。
局部生效的中间件
不使用app.use()方法注册,而是将定义的中间件写在路由的第二个参数的位置,然后这个中间件只对该路由有作用。
const mw=(req,res,next)=>{
console.log('这是一个简单的中间件');
next();
}
app.get('/','mw',(req,res)=>{
res.send('ok');
})
同时使用多个中间件
就是将定义的中间件从第二个参数的位置填写依次类推,或者使用数组的方式将需要用到的中间件包起来放在第二个参数的位置。
const mw=(req,res,next)=>{
console.log('这是一个简单的中间件');
next();
}
const mw1=(req,res,next)=>{
console.log('这是第二个中间件');
next();
}
app.get('/',mw,mw1,(req,res)=>{
res.send('ok');
})
中间件的五个注意事项
- 一定要在路由之前注册中间件(错误级别中间件除外)
- 客户端发过来请求,可以连续调用多个中间件进行处理
- 执行完中间件的业务代码之后,不要忘记调用next函数
- 为了防止代码逻辑混乱,调用next函数后不要再写额外的代码
- 连续调用多个中间件时,多个中间件之间,共享req和res。
中间件的分类
Express官方把常见的中间件分为了五类,分别是:
1.应用级别中间件
2.路由级别中间件
3.错误级别中间件
4.Express内置的中间件
5.第三方中间件
应用级别中间件
通过app.use或app.post或app.get,绑定到实例化服务器(app)上的中间件,称为应用级别中间件。
//全局生效的应用级别中间件
app.use((req,res,next)=>{
console.log('这是一个简单的中间件');
next();
})
//局部生效的应用级别中间件
const mw=(req,res,next)=>{
console.log('这是一个简单的中间件 ');
next();
}
app.get('/',mw,(req,res)=>{
res.send('ok')
})
路由级别的中间件
就是绑定到通过 express.router()实例化的路上的中间件,称为路由级别中间件
//实例化一个路由
const router=express.Router();
//将中间件绑定到路由上
router.use((req,res,next)=>{
console.log('这是一个路由级别的中间件');
next();
})
//注册路由
app.use('/',router)
错误级别中间件
再三声明,错误级别中间件要写在所有路由后面,其他中间件写在路由前面。
作用:专门用来捕获整个项目发生的异常错误,从而防止项目异常崩溃问题 。
格式:错误级别中间件中的function函数中,必须有四个参数 ,参数顺序分别为(err,req,res,next)
app.get('/',(req,res)=>{
//自定义一个错误
throw new Error('服务器内部发生了错误');
res.send('ok')
})
app.use((err,req,res,next)=>{
console.log('发生了错误'+err.message);
//将错误响应给客户端
res.send('Error!'+err.message);
})
内置中间件
自 Express 4.16.0
版本开始,Express
内置了 3 个常用的中间件,极大的提高了 Express
项目的开发效率和体验
-
express.static
快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS
样式等(无兼容性) -
express.json
解析JSON
格式的请求体数据(有兼容性,仅在4.16.0+
版本中可用) -
express.urlencoded
解析URL-encoded
格式的请求体数据(有兼容性,仅在4.16.0+
版本中可用)
//配置解析application/json格式数据的内置中间件
app.use(express.json());
//配置解析application/x-www-form-urlencoded格式数据的内置中间件
app.use(express.urlencoded({extended:false}));
第三方中间件
概念:非 Express
官方内置,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中,大家可以按需下载并配置第三方中间件,从而提高项目的开发效率
例如:在 express@4.16.0
之前的版本中,经常使用 body-parser
这个第三方中间件,来解析请求体数据。使用步骤如下
-
运行
npm install body-parser
安装中间件 -
使用
require
导入中间件 -
调用
app.use()
注册并使用中间件
注意:Express
内置的 express.urlencoded
中间件,就是基于 body-parser
这个第三方中间件进一步封装出来的
const express = require('express')
const app = express()
// 1. 导入解析表单数据的中间件 body-parser
const bodyParser = require('body-parser')
// 通过 express.urlencoded() 这个中间件,来解析表单中的 url-encoded 格式的数据
// app.use(express.urlencoded({ extended: false }))
// 2. 使用 app.use() 注册中间件
app.use(bodyParser.urlencoded({ extended: false }))
app.post('/book', (req, res) => {
console.log(req.body)
res.send(req.body)
})
app.listen(3000, () => {
console.log('running……')
})