更新时间: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 这个第三方中间件进一步封装出来的。