Express 中间件 Middleware
概念:与污水处理类似,污水到净水,中间经过多道处理流程,这样的中间处理环节,就叫做中间件
1 express中间件的调用流程
当请求到达express服务器,中间件1、中间件2、中间件3。。。处理完毕响应到客户端
2 中间件格式
本质就是一个function处理函数
const express = require('express')
const app = express()
app.get('/',function(req,res,next) {}) //function 里面多了一个形参next
app.listen(80,()=>{})
2.1 next函数的作用
实现多个中间件连续调用的关键,next函数表示传递给下一个中间件或路由
2.2定义中间件
const express = require('express')
const app = express()
const mw = function(req,res,next) {
console.log('这是最简单的中间件函数')
next()
}
//将mw注册为全局生效的中间件
app.use(mw)
app.listen(80,()=>{
console.log('http://127.0.0.1')
})
2.3全局生效的中间件
通过app.use(中间件函数),即可定义一个全局生效的中间件,通过next() 传递下去
,中间件仅仅是多了一个next
app.use((req,res,next)=>{
console.log('这是一个最简单的中间件函数')
next() // 这个next是关键
})
2.4 中间件的作用
多个中间件之间共享同一份req与res ,这样可以在上游的中间件中,为req或res对象添加自定义的属性或方法,供下游的中间件或路由使用
const express = require('express')
const app = express()
app.use((req,res,next)=> {
console.log('调用了第1个中间件')
})
app.use((req,res,next)=> {
console.log('调用了第2个中间件')
})
//定义一个路由
app.get('/get',(req,res)=>{
res.send('User page.')})
app.listen(80,()=> {
console.log('http://127.0.0.1')
})
2.5 局部生效的中间件
不使用app.use() 叫做局部生效的中间件
const mw = function(req,res,next){
console.log('随便意思一下')
next()
}
app.get('/',mw,function(req,res) { // 这就是局部生效的中间件,中间函数可以写任意多个,按顺序依次执行
=---------app.get('/',[mw1,mw2,mw3,mw4],function(req,res) { // 这就是局部生效的中间件,中间函数可以写任意多个,按顺序依次执行
res.send('Home page')
})
2.6 中间件使用注意事项
1 先写中间件后路由
2 重点!!! 不要忘记next() ,调用完next()后在中间件中不要再写代码
3 多个中间件 req和res是共享的
2.7 中间件的使用
应用、路由、错误、内置、第三方
2.7.1 应用级别中间件
绑定到app实例上就是应用级中间件
2.7.2路由级别的中间件
express.Router()实例上的中间件
const app = express()
const router = express.Router()
router.use((req,res,next)=>{
console.log('意思意思')
next()
})
app.use('/',router)
2.7.3 错误级别中间件
用于捕获异常错误,必须有4个形参,分别是 (err,req,res,next)
const express = require('express')
const app = express()
//定义一个路由
app.get('/',(req,res)=>{
throw new Error('服务器内部发生了错误!')
res.send('home page')
})
//定义错误级别中间件,防止错误引发崩溃,错误级别的中间件注册再所有路由之后!!
app.use((err,req,res,next)=> {
console.log('发生了错误!'+err.message)
res.send('Error:'+err.message)
})
app.listen(80,()=> {
console.log('http://127.0.0.1')
})
2.7.4 express内置中间件
express.static 托管静态资源//任何版本都可以使用
express.json 解析Json格式的请求
app.use(express.json())
示例:
const express = require('express')
const app = express()
app.use(express.json()) // 解析了json数据 req.body 可以访问到数据了
app.post('/user',(req,res)=>{
//在服务器,可以通过req.body来接收客户端发送过来的请求数据,需要配置中间件
res.send('ok')})
app.listen(80,function(){
console.log('http://127.0.0.1')
})
---------------------------------------------------------------
express.urlencoded 解析URL-encoded格式的请求数据
app.use(express.urlencoded({extended:false})) //固定写法 配置解析application/x-www-form-urlencoded 格式数据的中间件
示例:
const express = require('express')
const app = express()
app.use(express.urlencoded({extended:false})) //固定写法,这样就可以解析urlencoded格式数据
app.post('/user',(req,res)=>{
//在服务器,可以通过req.body来接收客户端发送过来的请求数据,需要配置中间件
console.log(req.body)
res.send('ok')
})
app.listen(80,function(){
console.log('http://127.0.0.1')
})
3 自定义中间件
手写一个express.urlencoded 这样的中间件
3.1实现步骤:定义中间件、监听req的data事件、监听req的end事件、使用querystring模块解析请求体数据、将解析出来的数据对象挂载为req.body、将自定义中间件封装为模块
3.2代码
const express = require('express')
const app = express()
const qs = require('querystring') //内置,一会调用qs.parse()
// 模拟接收数据
app.use((req,res,next) => {
//定义一个str字符串
let str = ''
//监听req的data事件
req.on('data',(chunk)=>{
str+= chunk
})
//监听req的end事件
req.on('end',()=>{
//str中是完整的请求体数据
const body = qs.parse(str) //3.3解析
req.body= body //3.4 将body 挂载到req
})
})
app.listen(80,function(){
console.log('http://127.0.0.1')
})