在其他的开发语言比如C#的中,中间件是指业务处理中使用到的组件或者模型。
在Node.js的Express中,就是指在业务处理流程中系统使用到的“组件”,不过,这个“组件”指的是函数而已。
当我们使用Express开发了一个网站,服务器接收到一个来自客户端浏览器的请求之后,最简单的情形就是经过一个函数处理后就返回结果,而普遍存在的场景却是需要连续调用多个处理函数(中间件,middleware)后才能给客户端返回结果。
比如,做提取来自客户端的基础信息(IP地址、访问时间、请求的源地址等)、安全检测、记录日志、通讯处理及消息传递等等,这些处理需求对于一个稍微大一点的网站几乎是必须的,这些就可以写成中间件,我们在开发过程中就可以很方便地使用它们从而对来自浏览器端的请求逐一做想要的预处理。
在Node.js的Express中,多个中间件之间,共享同一份的req(request)和res(response),并且在前面使用的中间件中,可以为req和res添加自定义的属性或者方法,以便让后面的中间件进行使用。
1、Express中间件的格式:(app为Web服务器的实例对象)
app.post(‘路由请求’,(req,res,next)=>{//处理//移交给下一个中间件或者路由next()})
2、在Express中,中间件分局部生效的中间件和全局生效的中间件。
①局部生效的中间件
const ztb_mw1=function(req,res,next){console.log(‘局部生效的中间件1’)next()}const ztb_mw2=function(req,res,next){console.log(‘局部生效的中间件2’)next()}app.post(‘/ZTB’,ztb_mw1,ztb_mw2,function(req,res){res.send(‘这是经过两个中间件处理后的结果’)}
上面的等价形式:
app.post(‘/ZTB’,[ztb_mw1,ztb_mw2],(req,res)=>{res.send(‘这是经过两个局部生效的中间件处理后的结果’)}
②全局生效的中间件
app.use(function(req,res,next){console.log(‘这是全局生效的中间件1’)next()})app.use(function(req,res,next){console.log(‘这是全局生效的中间件2’)next()})app.post(‘/ZTB’,(req,res)=>{res.send(‘这是经过两个全局中间件处理后的结果’)}
3、中间件分为5大类:
①处理一般应用的中间件:
通过app.post()、app.get()或者app.use()绑定到app实例上的中间件。
②处理路由的中间件:
绑定在router实例上的中间件,router为路由实例对象
③处理错误的中间件
处理错误的中间件,有4个参数,分别是err,req,res,next,这个中间件必须注册在所有的路由之后。
④Express的内置中间件
比如express.json、express.urlencoded等,其中express.json用于解析JSON格式的请求体数据(在Express 4.16版本之后),express.urlencoded用于解析URL-encoded格式的请求体数据。
⑤第三方的中间件
这个有很多,使用类同于express的内置组件。
4、定义中间的注意事项:
①一定要在路由之前注册中间件;
②对于同样的请求,可以连续调用多个中间件
③执行完中间件,最后一定要调用next()函数
④连续调用的多个中间件之间共享同一份的req和res对象
主文件ZTB_Main.js代码:
//导入express模块const express=require('express')//创建Web服务器const app=express()//配置解析application/json格式的数据的中间件app.use(express.json())//配置解析application/x-www-form-urlencoded格式数据的中间件app.use(express.urlencoded({extended:false}))//导入自定义的路由模块//自定义模块必须加上路径名,文件后缀可以省略,内置模块和下载的第三方模块不需要加const ZTB_router=require('./ZTB_router.js')//导入中间件模块const ZTB_mw=require('./ZTB_mw.js')//注册中间件app.use(ZTB_mw.ZTB_mw1)app.use(ZTB_mw.ZTB_mw2)//注册一个局部路由模块app.use('/ZTB/update',ZTB_mw.ZTB_mw3,ZTB_router)//注册全局路由模块app.use('/ZTB',ZTB_router)//启动web服务器app.listen(9019,()=>{console.log('Web服务器正在运行......http://127.0.0.1:9019')})
中间件文件ZTB_mw.js代码:
//导入expressvar express=require('express')function ZTB_mw1(req,res,next){console.log('获取客户端的信息')next()}function ZTB_mw2(req,res,next){console.log('安全检测')next()}function ZTB_mw3(req,res,next){console.log('日志处理')next()}//对外共享中间件module.exports={ZTB_mw1,ZTB_mw2,ZTB_mw3}
路由文件ZTB_router.js代码:
//导入expressvar express=require('express')//创建路由对象var router=express.Router()router.get('/add',function(req,res){//处理增加//返回结果console.log('增加操作')res.send('增加操作')})router.post('/del',function(req,res){//处理删除//返回结果console.log('删除操作')res.send('删除操作')})router.post('/update',function(req,res){//处理删除//返回结果console.log('更新操作')res.send('更新操作')})//对外导出路由对象module.exports=router
结果: