更新时间:2022-10-13 来源:黑马程序员 浏览量:
中间件(Middleware ),特指业务流程的中间处理环节。例如工厂要排放生产中产生的污水,就必须要先将污水净化以达到排放标准你,处理污水的时候,经过的三个处理环节,就可以叫做中间件。
Express 的中间件,本质上就是一个 function 处理函数, 中间件函数的形参列表中,必须包含 next 参数。而路由处理函数中只包含 req 和 resExpress ,中间件的格式如下:
next 函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。Express中间件从到响应的流程如下:
下面我们来看Express中间件的几种常规操作。
可以通过如下的方式,定义一个最简单的中间件函数:
//常量mw所指向的,就是一个中间件函数
const mw = function (req, res, next){
console.log('这是一个最简单的中间件函数')
//注意:在当前中间件的业务处理完毕后,必须调用 next()函数
//表示把流转关系转交给下一个中间件或路由
next()
}
客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。 通过调用app.use(中间件函数),即可定义一个全局生效的中间件,全局生效中间件的示例代码如下:
//常量mw所指向的,就是一个中间件函数
const mw = function (req, res, next) {
console.log('这是一个最简单的中间件函数’)
next()
}
//全局生效的中间件
app.use(mw)
3. 定义全局中间件的简化形式
定义全局中间件的简化形式可以参考如下代码:
//全局生效的中间件
app.use(function (req, res, next) {
console.log(’这是一个最简单的中间件函数’)
next()
})
多个中间件之间,共享同一份req和res。基于这样的特性,我们可以在上游的中间件中,统一为req 或res 对象添加自定义的属性或方法,供下游的中间件或路由进行使用。
可以使用app.use() 连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用,示例代码如下:
app.use(function(req,res,next){//第1个全局中间件
console.log('调用了第1个全局中间件')
next()
})
app.use(function(req,res,next){//第2个全局中间件
console.log('调用了第2个全局中间件')
next()
1})
app.get('/user',(req,res)=>{//请求这个路由,会依次触发上述两个全局中间件
res.send('Home page.')
})
不使用app.use() 定义的中间件,叫做局部生效的中间件,示例代码如下:
//定义中间件函数mw1
const mw1 = function(req, res, next) (
cosole.log('这是中间件函数')
next()
}
//mN1
这个中间件只在“当前路由中生效”,这种用法属于“局部生效的中间件”
app.get('/',mwi,function(req,res){
res.send('Home page.')
})
//mw1这个中间件不会影响下面这个路由!+
app.get('/user',
function(req, res) { res.send('User page.') })
可以在路由中,通过如下两种等价的方式,使用多个局部中间件:
//以下两种写法是“完全等价“的,可根据自己的喜好,选择任意一种方式进行使用
apg.get('/',mw1,mw2,(req,res)=>{res.send('Home page.')})
app.get('/',[mw1,mw2],(req,res)=>{ res.send('Home page.') })
注意:一定要在路由之前注册中间件,客户端发送过来的请求,可以连续调用多个中间件进行处理。执行完中间件的业务代码之后,不要忘记调用next() 函数。为了防止代码逻辑混乱,调用next() 函数后不要再写额外的代码。连续调用多个中间件时,多个中间件之间,共享req 和res 对象。
为了方便大家理解和记忆中间件的使用,Express 官方把常见的中间件用法,分成了5 大类,分别是:
①应用级别的中间件
②路由级别的中间件
③错误级别的中间件
④Express 内置的中间件
⑤第三方的中间件
通过app.use() 或app.get() 或app.post() ,绑定到app 实例上的中间件,叫做应用级别的中间件,代码示例如下:
//应用级别的中间件(全局中间件)
app.use((req,res,next)=>{
next()
})
//应用级别的中间件(局部中间件)
app.get('/',mwi,(req, res) =>{
res.send('Home page.')
})
绑定到express.Router() 实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到app
实例上,路由级别中间件绑定到router 实例上,代码示例如下:
var app = express()
var router = express.Router(
//路由级别的中间件
router.use(function (req, res, next) (
console.log('Time:', Date.now())
next()
})
app.use('/', router)
错误级别中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。
格式:错误级别中间件的function 处理函数中,必须有4 个形参,形参顺序从前到后,分别是(err, req, res, next)。
app.get('/', function (req, res){ // 1.路由
throw new
Error('服务器内部发生了错误!') // 1.1抛出一个自定义的错误
res.send('Home
Page.')
})
app.use(function(err,req,res,next){ // 2.错误级别的中间件
console.log('发生了错误:'+err.message) //2.1在服务器打印错误消息
res.send('Error!'+
err.message) //2.2向客户端响应错误相关的内容
})
注意:错误级别的中间件,必须注册在所有路由之后!
自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-ww-form-urlencoded 格式数据的内置中间件
app.us(express.urlencoded({ extended:false }))
非Express 官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中,大家可以按需下载并配置第三方中间件,从而提高项目的开发效率。
例如:在express@4.16.0 之前的版本中,经常使用body-parser 这个第三方中间件,来解析请求体数据。使用步骤如下:
①运行npm install body-parser安装中间件
②使用require导入中间件
③调用app.use() 注册并使用中间件
注意:Express 内置的express.urlencoded中间件,就是基于body-parser 这个第三方中间件进一步封装出来的。