简介
Express 中间件
中间件格式
- 中间件函数的形参数列表中,必须有 next参数,而路由处理参数中只包含req 和 res
- 书写格式如下:
const express = require('express')
const app = express()
app.get('/',(req,res,next)=>{
next()
})
app.listen('8088',()=>{
console.log('express server running at http://127.0.0.1:8088')
})
next 函数的作用
- next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或者路由
定义中间件
const express = require('express')
const app = express()
const c1 = function (req,res,next){
console.log('这是一个中间件函数')
next()
}
app.listen('8088',()=>{
console.log('express server running is http://127.0.0.1:8088')
})
全局生效的中间件
- 客户端发起的任何请求,到达服务器之后,都会触发中间件,叫做全局生效的中间件
- 通过app.use(中间件函数),即可定义一个 全局生效的中间件,示例代码如下:
const express = require('express')
const app = express()
const c1 = function (req, res, next) {
console.log('这是一个中间件函数')
next()
}
app.use(c1)
app.get('/', (req, res) => {
console.log('调用了/这个路由')
res.send('home page')
})
app.post('/user', (req, res) => {
console.log('调用了/user这个路由')
res.send('user page')
})
app.listen('8088', () => {
console.log('express server running is http://127.0.0.1:8088')
})
定义中间件简化形式
const express = require('express')
const app = express()
app.use((req,res,next)=>{
console.log('定义全局中间件的简化形式')
next()
})
app.get('/', (req, res) => {
console.log('调用了/这个路由')
res.send('home page')
})
app.listen('8088', () => {
console.log('express server running is http://127.0.0.1:8088')
})
中间件的作用
- 多个中间件之间,共享一份req 和 res ,基于这样的特性,我们可以在上游的中间件中,统一的为req 或 res对象添加自定义的属性和方法,供下游的中间件或者路由使用。
const express = require('express')
const app = express()
app.use((req, res, next) => {
const time = Date.now()
req.startTime = time
next()
})
app.get('/', (req, res) => {
res.send('home page' + req.startTime)
})
app.post('/user', (req, res) => {
res.send('user page' +req.startTime)
})
app.listen('8088', () => {
console.log('express server running is http://127.0.0.1:8088')
})
定义多个全局中间件
- 可以用app.use() 连续定义多个全局中间件,客户端请求到达服务器之后,会按照中间件的定义的先后顺序依次进行调用, 示例代码如下:
/**
*定义多个全局中间件
* */
const express = require('express')
const app = express()
//第一个全局中间件
app.use(function (req, res, next) {
console.log('第一个全局中间件')
next()
})
//第二个全局中间件
app.use(function (req, res, next) {
console.log('第二个全局中间件')
next()
})
//定义路由
app.get('/', (req, res) => {
res.send('home page')
})
app.listen('8088',()=>{
console.log('express server running at http://127.0.0.1:8088')
})
局部定义的中间件
- 不使用 app.use() 定义的中间件叫做 局部生效的中间件,代码示例如下:
const express = require('express')
const app = express()
const ct = (req,res,next)=>{
console.log('局部生效中间件函数')
next()
}
app.get('/',ct, (req, res) => {
res.send('home page')
})
app.post('/user', (req, res) => {
res.send('user page')
})
app.listen('8088',()=>{
console.log('express server running at http://127.0.0.1:8088')
})
定义多个局部中间件,代码示例如下:
const express = require('express')
const app = express()
const ct1 = (req,res,next)=>{
console.log('第一个局部中间件函数')
next()
}
const ct2 = (req,res,next)=>{
console.log('第二个局部中间件函数')
next()
}
const ct3 = (req,res,next)=>{
console.log('第三个局部中间件函数')
next()
}
const ct4 = (req,res,next)=>{
console.log('第四个局部中间件函数')
next()
}
app.get('/',ct1,ct2, (req, res) => {
res.send('home page')
})
app.post('/user',[ct3,ct4], (req, res) => {
res.send('user page')
})
app.listen('8088',()=>{
console.log('express server running at http://127.0.0.1:8088')
})
使用中间件的注意事项
- 一定要在路由之前注册中间件
- 客户端发送过来的请求,可以连续调用多个中间件进行处理
- 执行完中间件的业务代码之后,不要忘记调用next()函数
- 为了防止代码逻辑混乱,调用next()函数之后不要再写额外的代码
- 连续调用多个中间件时,多个中间件之间,共享 req 和 res 对象
中间件的分类
- 注意:除了错误级别的中间件,其他的中间件必须在路由之前配置
应用级别的中间件
- 通过 app.use()或者app.get()或app.post() 绑定在app示例上的中间件,叫做应用级别的中间件
路由级别的中间件
- 绑定到 express.Router() 实例上的中间件,叫做路由级别的中间件,它的用法和应用级别的中间件没有任何区别,只不过,应用级别的中间件绑定在app实例上,路由级别的中间件绑定在router实例上
错误级别的中间件
- 作用: 专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题
- 格式: 错误级别中间件中的function处理函数中,必须有4个形参,形参顺序从前到后,分别是(err,req,res,next).
- 注意: 错误级别的中间件,必须注册在所有路由之后
- 代码实例如下:
const express = require('express')
const app = express()
app.get('/',(req,res)=>{
throw new Error('服务器内部出现error')
res.send('home page')
})
app.use((err,req,res,next)=>{
console.log('发生了错误'+err.message)
res.send('Error'+err.message)
})
app.listen('8088',()=>{
console.log('express server running at http://127.0.0.1:8088')
})
Express的内置中间件
- express.static 快速托管静态资源的内部中间件,例如:HTML文件,图片,CSS样式等(无兼容性)
- express.json 解析JSON格式的请求体数据,(有兼容性,仅在4.16.0+ 版本中使用)
- express.urlencoded 解析 URL-encoded 格式的请求体数据(有兼容性,仅在4.16.0+ 版本中使用)
const express = require('express')
const app = express()
app.use(express.json())
app.use(express.urlencoded({extended:false}))
app.post('/user',(req,res)=>{
console.log(req.body)
res.send('ok')
})
app.post('/book',(req,res)=>{
console.log(req.body)
res.send('bookok')
})
app.listen('8088',()=>{
console.log('express server running at http://127.0.0.1:8088')
})
第三方的中间件
- 非Express 官方内置的,而是由第三方提供出来的中间件,叫做第三方中间件,在项目中大家可以按需下载并配置第三方中间件,从而提高项目的开发效率
- 例如使用body-parser 第三方中间件解析请求体数据
- 输入 npm install body-parser 安装中间件
- 使用require导入中间件
- 调用 app.use ()注册并使用中间件
- 使用方法如下:
const express = require('express')
const app = express()
const parser = require('body-parser')
app.use(parser.urlencoded({extended:false}))
app.post('/book',(req,res)=>{
console.log(req.body)
res.send('ok1')
})
app.listen('8088',()=>{
console.log('express server running at http://127.0.0.1:8088')
})
自定义中间件
- 在文件目录下创建两个js文件,自定义模块化拆分.js 和 conmon-body-parser.js
- 在 自定义模块化拆分.js 文件中导入封装的中间件
const express = require('express')
const app = express()
const custbodyparser =require('./conmon-body-parser')
app.use(custbodyparser)
app.post('/book', (req, res) => {
res.send(req.body)
})
app.listen('8088', () => {
console.log('express server running at http://127.0.0.1:8088')
})
- 在conmon-body-parser.js文件中进行封装中间件
const qs = require('querystring')
const bodyparser = (req, res, next) => {
let str = ''
req.on('data', (chunk) => {
str += chunk
})
req.on('end', () => {
console.log(str)
const body = qs.parse(str)
console.log(body)
req.body = body
next()
})
}
module.exports=bodyparser