中间件(middleware)就是一个方法,一般情况下需携带next参数,express进行路由配置时的回调函数,但中间件在使用时,一般都是使用use方法。
一,中间件的作用。
- 多个中间件之间,共享同一份req和res。基于这样的特性,我们可以在上游中间件中,统一为req或res对象添加自定义的属性或方法,提供给下游的中间件使用。
- 客户端发起任何请求,到达服务器后,都会触发的中间件,叫全局生效的中间件。
二,注意事项。
- 要在路由之前注册中间件。
- 可以连续调用多个中间件处理请求。
- 执行完中间件后,不要忘记调用next()函数。
- 防止代码混乱,next()后不要写额外代码了。
- 连续调用多个中间件时,多个中间件之间,共享req和res。
- 中间件可以绑定到reter实例上(路由级别),与app中(应用级别)没有任何区别
三,定义全局中间件。
代码语言:javascript复制const express=require('express')
const app=express();
// 这是全局中间件 简单的使用,直接app.use中写函数
app.use((req,res,next)=>{
//为req 对象,挂载自定义属性,从而把时间共享给后面的所有路由
const time=Date.now();
req.startTime=time;
next();
})
app.get('/',(req,res)=>{
//多个中间件之间,共享req和res对象,
//获取到上游中间件中的startTime属性
res.send('home=' req.startTime)
})
app.get('/user',(req,res)=>{
res.send('user' req.startTime)
})
app.listen(1212,()=>{
console.log('启动成功')
})
四,定义局部中间件。
代码语言:javascript复制const express=require('express')
const app=express();
// 1,定义中间件函数
const mw=(req,res,next)=>{
console.log('调用了局部生效的中间件1')
next();
}
const mw2=(req,res,next)=>{
console.log('调用了局部生效的中间件2')
next();
}
// 2,创建路由
app.get('/',mw,(req,res)=>{
res.send('home=')
})
// 可以调用多个局部路由中间件, 也可以用 [mw,mw2] 包起来
app.get('/user',mw,mw2,(req,res)=>{
res.send('user')
})
app.listen(1212,()=>{
console.log('启动成功')
})
五,错误级别的中间件。
作用: 捕获整个项目中 的异常错误,防止程序崩溃。
注意点:
- 错误级别中间件有四个参数,(err,req,res,next)。
- 必须注册在所有路由之后。
const express=require('express')
const app=express();
//创建路由
app.get('/',(req,res)=>{
//制造错误
throw new Error('服务错误')
res.send('home=')
})
//定义错误级别的中间件,
app.use((err,req,res,next)=>{
console.log('发生了错误=' err);
res.send('Error' err.message)
})
app.listen(1212,()=>{
console.log('启动成功')
})
六,Express内置的中间件。
Express中内置了三个中间件。
- express.static 快速托管静态资源的内置中间件,如:html,img,css等(无兼容性)
const express=require('express');
const app=express();
//在这里,调用express.static()方法,快速对外提供静态资源
app.use(express.static('./public'))
// 同时托管多个静态资源目录,可以多次调用 express.static
// express.static()函数会根据目录的添加顺序找查所需文件
app.use(express.static('./static'))
//可以加一个前缀
app.use(express.static('/zhang','./static'))
app.listen(1212,()=>{
console.log('启动成功')
})
- express.json 解析json格式的请求数据(仅在4.16.0 版本中可以使用)
- express.urlencoded 解析URL-encoded格式的请求体数据(仅在4.16.0 版本中可以使用)
const express=require('express')
const app=express();
// 注意,除了错误级别的中间件,其他中间件,必须在路由之前进行配置
// 通过 express.json 中间件,解析表单中的json格式数据
app.use(express.json())
// 通过 express.urlencoded()中间件,来解析表单中的url-encoded 格式的数据
app.use(express.urlencoded({extended:false}))
// 创建路由
app.post('/',(req,res)=>{
//在服务器,可以使用req.body这个属性,来接收客户端发送过来的请求体数据
// 默认情况下,如果不配置解析表单数据的中间件(express.json()),则req.body默认等于undefined
console.log(req.body)
res.send('ok')
})
app.post('/book',(req,res)=>{
// 默认情况下,如果不配置解析表单数据的中间件(express.urlencoded({extended:false})),则req.body默认等于{}
console.log(req.body)
res.send('ok')
})
app.listen(1212,()=>{
console.log('启动成功')
})
注意:除了错误级别的中间件,其他中间件,必须在路由之前进行配置。
七,自定义中间件。
代码语言:javascript复制const express=require('express')
// 导入node。js 内置的querystrin模块
const qs= require('querystring')
const app=express();
//自定义解析表单数据的中间件
app.use((req,res,next)=>{
// 1,定义str字符串,存储客户端发送过来的请求数据
let str=''
//2,监听 req的data事件
req.on('data',(chunk)=>{
str =chunk;
})
//2,监听 req 的end 事件
req.on('end',()=>{
// 在str中存放的是完整的请求数据
console.log(str)
// 解析成对象格式
const body= qs.parse(str);
console.log(body)
//将解析出来的数据,挂载到body属性上给下游使用
req.body=body;
next();
})
})
// 创建路由
app.post('/',(req,res)=>{
res.send(req.body)
})
app.listen(1212,()=>{
console.log('启动成功')
})