切换主题
十、中间件的概念
1、Express中间件的格式
Express的中间件,本质上就是一个function处理函数
js
const express=require('express')
const app=express()
app.get('/',function(req,res,next)=>{
next()
})
app.listen(3000)
注意:中间件函数的形参列表中,必须包含next参数,而路由处理函数中只包含req和res
2、next函数的作用
next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由
3、Expres中间件的初体验
1、格式:
js
const md=function(req,res,next){
console.log("这是一个中间件")
next()
}
2、全局生效的中间件
客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件
通过调用app.use(中间件函数),即可定义一个全局生效的中间件
js
const md=function(req,res,next){
console.log("这是一个中间件")
next()
}
app.use(md)
3、定义全局中间件的简化形式
js
//全局生效的中间件
app.use(function(req,res,next){
console.log("这是一个最简单的中间件函数")
next()
})
4、中间件的作用
多个中间件之间,共享同一份reqheres。基于这样的特性,我们可以在上游的中间件中,同意为req或res对象添加自定义的属性或方法,公下游的中间件或路由进行使用
js
const express = require('express')
const app=express()
// 注册全局中间件
app.use((req,res,next)=>{
const time=Date.now()
// 为req对象,挂载自定义属性,从而把时间共享给后面的所有路由
req.startTime = time
next()
})
app.get('/',(req,res)=>{
res.send("homePage"+req.startTime)
})
app.post('/user',(req,res)=>{
res.send("userPage"+req.startTime)
})
app.listen(80,()=>{
console.log("服务器启动了");
})
5、定义多个全局中间件
可以使用app.use()连续定义多个全局中间件,客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用
js
app.use((req,res,next)=>{
console.log("调用第一个全局中间件")
next()
})
app.use((req,res,next)=>{
console.log("调用第二个全局中间件")
next()
})
app.get('/user',(req,res)=>{
res.send("homePage")
})
6、局部生效的中间件
不适用app.use()定义的中间件,叫做局部生效的中间件
js
//定义中间件函数md
const md=(req,res,next)=>{
console.log("这是中间件函数")
next()
}
app.get('/',md,(req,res)=>{
res.send("homepage")
})
app.get('/user',(req,res)=>{
res.send("userpage")
})
7、定义多个局部中间件
js
const md1=(req,res,next)=>{
console.log("这是第一个中间件函数")
next()
}
const md2=(req,res,next)=>{
console.log("这是第二个中间件函数")
next()
}
app.get('/',md1,md2,(req,res)=>{res.send("homepage")})
//等价于
//app.get('/',[md1,md2],(req,res)=>{res.send("homepage")})
8、了解中间件的5个注意事项
- 一定要在路由之前注册中间件
- 客户端发送过来的请求,可以连续调用多个中间件进行处理
- 执行完中间件的业务的代码之后,不要忘记调用next()函数
- 为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
- 连续调用多个中间件时,多个中间件之间,共享req和res对象
4、中间件的分类
中间件分5大类
- 应用级别的中间件
- 路由级别的中间件
- 错误级别的中间件
- Express内置的中间件
- 第三方的中间件
1、引用级别的中间件
通过app.use或app.get()或app.post()绑定到app实例上的中间件,叫做应用级别的中间件
js
app.use((req,res,next)=>{
next()
})
app.get('/',md,(req,res)=>{
res.send('homepage')
})
2、路由级别的中间件
js
router.use((req,res,next)=>{
next()
})
3、错误级别的中间件
错误级别中间件的作用,专门用来捕获整个项目发生的异常错误,从而防止项目异常崩溃的问题
格式:错误级别中间件的function处理函数中,必须有4个形参,形参顺序从前到后,分别为(err,req,res,next)
js
app.use((err,req,res,next)=>{
res.send(err.message)
})
注意:错误级别的中间件和其他中间件不一样,必须放在所有路由之后
4、Express内置的中间件
内置3个常用的中间件
express.static快速托管静态资源的内置中间件
express.json解析JSON格式的请求体数据(仅在4.16.0+版本中可用)
express.urlencoded解析URI-encoded格式的请求体数据(仅在4.16.0+版本中可用)
js
app.use(express.json())
app.use(express.urlencoded({extended:false}))
5、第三方中间件
5、自定义中间件
js
const express=require('express')
const app=express()
app.use((req,res,next)=>{
let str=""
req.on("data",(chunk)=>{
str+=chunk
})
req.on("end",()=>{
console.log(str);
})
next()
})
app.post('/user',(req,res)=>{
res.send("post请求")
})
app.listen(8080,()=>{
console.log("服务器运行了!");
})
1、使用querystring模块解析请求体数据
querystring模块的parse()函数,可以轻松把查询字符串解析为对象的格式
js
const qs=require('querystring')
const body=qs.parse(str)
2、将解析出来的数据对象挂载为req.body
上游的中间件和下游的中间件及路由之间,共享同一份req和res。因此,我们可以将解析出来的数据,挂载为req的自定义属性,命名为req.body,供下游使用
js
app.use((req, res, next) => {
let str = ""
req.on("data", (chunk) => {
str += chunk
})
req.on("end", () => {
const body = qs.parse(str)
req.body = body
next()
})
})
app.post('/user', (req, res) => {
console.log(req.body);
res.send(req.body)
})
3、拆分中间件
js
//md1.js
const qs = require('querystring')
const md1=(req, res, next) => {
let str = ""
req.on("data", (chunk) => {
str += chunk
})
req.on("end", () => {
const body = qs.parse(str)
req.body = body
next()
})
}
module.exports=md1
js
//test.js
const md1 = require('./拆分')
app.use(md1)