什么是中间件?
1 中间可以进行一些条件的判断,如果符合条件就继续执行下面的程序,否则就阻断,被拦截了,下面的程序也就不再执行[一般中间件放在get post 这个路由接口前面执行];
2 中间件就是一个函数,通过它可以执行不同的功能。我们也可以单独封装一个中间件,然后引入
3 分类:
应用程序中间件
路由中间件
异常处理中间件
内置中间件
第三方中间件
1 应用程序中间件
get请求测试:http://localhost:3356/better?name=sh&age=25
const express = require('express');
var app = express();
app.use('/',(req,res,next)=>{
console.log("a");
next();
})
app.use('/',(req,res,next)=>{
console.log('b');
next();
})
app.get('/better',(req,res)=>{
console.log('c');
res.send({
code:1,
success:200,
data:req.query
})
})
app.listen(3356);
本地打印结果:
a
b
c
get请求返回的结果:json格式
{
"code":1,
"success":200,
"data":{
"name":"sh",
"age":"25"
}
}
中间件的一些写法形式:
1 常规形式:
如上所示
2 代理参数的中间件接口(如果你需要取出数据可以通过req.params进行提取)
官方文档:
An object containing properties mapped to the named route “parameters”.
For example, if you have the route /user/:name,
then the “name” property is available as req.params.name. This object defaults to {}.
翻译:包含映射到指定的路线“参数”属性的对象。
例如,如果你有route/user/:name,那么“name”属性可作为req.params.name。
该对象默认为{}。
请求地址:
http://localhost:3356/add/name/ss/age/25 【GET请求】
const express = require('express');
var app = express();
app.use('/add/name/:name/age/:age',(req,res,next)=>{
console.log("a");
console.log(req.params);
next();
})
// 这个中间件接口指向localhost 如果设置的和访问的接口不同,将会直接跳过
app.use('/',(req,res,next)=>{
console.log('b');
next();
})
app.get('/add/name/:name/age/:age',(req,res)=>{
console.log('c');
res.send({
code:1,
success:200,
data:req.params
})
})
app.listen(3356);
执行结果:
a
{ name: 'ss', age: '25' }
b
c
get请求返回的结果:{
"code": 1,
"success": 200,
"data": {
"name": "ss",
"age": "25"
}
}
3 组合方式
http://localhost:2500/good
const express = require('express');
var app = express();
app.use('/',(req,res,next)=>{
console.log("a"),
next();
},(req,res,next)=>{
console.log('b');
next();
})
app.get('/good',(req,res)=>{
console.log("c");
res.send('OK');
})
app.listen(2500);
打印结果:
a
b
c
get请求返回信息: ok
2 路由中间件
1 准备: 需要下载express 以及自己需要的第三方的中间件(这里需要接受post数据,因此使用了body-parser第三方中间件)
express 和 第三方的中间件可以自行通过npm 或者 yarn 进行安装
为了更好的演示效果,本次将路由中间件单独独立出来,放在routers.js中
user.js
const express = require('express');
const userRouter = require('./routers');
const bodyParser = require('body-parser');
var app = express();
// extended设置了false 表示不采用第三方qs来处理 使用querystring来进行数据的解析,这是URL-encode解析器
app.use(bodyParser.urlencoded({extended:false}));
// 添加json解析器
app.use(bodyParser.json());
app.use('/good',userRouter);
app.listen(3356);
routers.js
const express = require('express');
var router = express.Router();
router.use('',(req,res,next)=>{
console.log("验证");
next();
})
router.use('/',(req,res,next)=>{
console.log(req)
console.log(req.body);
if(req.body.name==="wanghao"){
// res.send(req.body);
next();
}
})
router.get('/name',(req,res)=>{
console.log("aa");
res.send({
result:"success"
});
})
module.exports = router;
测试工具:
insomnia
对于上面数据如何进行接收:存在两种方式,这两种方式基于你请求的方式get or post
1 如果是get请求,你可以直接使用req.query进行获取
http://localhost:3356/good/name?name=wh&age=12
const express = require('express');
var router = express.Router();
router.use('',(req,res,next)=>{
console.log("验证");
next();
})
router.use('/',(req,res,next)=>{
console.log(req.query);
if(req.query.name==="wh"){
next();
}
})
router.get('/name',(req,res)=>{
console.log(req.query);
console.log("aa");
res.send({
result:"success"
});
})
module.exports = router;
本地打印结果:
//入口打印结果
验证
//中间判断层打印结果
{ name: 'wh', age: '12' }
//get路由接口打印结果
aa
{ name: 'wh', age: '12' }
get请求返回的结果:
{
"result": "success"
}
if(req.query.name==="wh"){
next();
}
})
router.get(’/name’,(req,res)=>{
console.log(req.query);
console.log(“aa”);
res.send({
result:“success”
});
})
module.exports = router;
本地打印结果:
//入口打印结果
验证
//中间判断层打印结果
{ name: ‘wh’, age: ‘12’ }
//get路由接口打印结果
aa
{ name: ‘wh’, age: ‘12’ }
get请求返回的结果:
{
“result”: “success”
}
2 如果是post请求,你需要安装第三方的中间件 body-parser 使用req.body进行解析数据
执行文件
const express = require('express');
const userRouter = require('./routers');
const bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
app.use('/good',userRouter);
app.listen(3356);
封装的路由中间件
const express = require('express');
var router = express.Router();
router.use('',(req,res,next)=>{
console.log("验证");
next();
})
router.use('/',(req,res,next)=>{
console.log(req.body);
if(req.body.name==="wh"){
next();
}
})
router.post('/name',(req,res)=>{
console.log(req.body);
res.send({
result:"success"
});
})
module.exports = router;
执行打印结果:
验证
{ name: 'wh', age: '22' }
{ name: 'wh', age: '22' }
post请求返回结果:
{
result:"success"
}
3 如果有一个路由中间件出现问题,会发现post请求无返回结果
总结:
1 通过以上两个请求测试,可以发现,get和post请求时对数据的解析方式不同,get使用req.query可以直接解析, post 需要使用req.body(这里还需要写在第三方的中间件body-parser)
2 通过第三点,我们可以看出,如果中间件出现不符合条件的数据就会停止继续执行下面的程序,因此,我们可以用中间件进行一些验证信息的判断(比如登录的用户名和密码等)
3 要注意,中间件是可以接受任何请求方式发送过来的数据,仅仅是解析数据的形式存在不同而已
3 异常处理中间件
错误优先原则
模拟测试:通过访问一个get请求抛发一个错误信息,这个信息一旦被隐藏处理中间件捕获,就会报错,并且显示出你设置的信息
router.js
const express = require('express');
var router = express.Router();
router.get('/r3',(req,res)=>{
throw new Error('error message');
})
module.exports = router;
app.js
const express = require('express');
const router = require('./routers');
var app = express();
app.use('/user',router);
//错误优先原则 异常处理中间件
app.use((err,req,res,next)=>{
console.log(err.stack);
res.status(200).send('something is wrong');
next();
})
app.listen(2300)
通过get请求访问:
http://localhost:2300/user/r3
由于异常处理中间件会捕获到,因此会显示错误提示信息,这个状态码可以自行设置,本例设置的为200
4 内置中间件
exprss.static 静态资源的设置,html 图片等
express.json 解析传入的数据请求,为json格式
5 第三方中间件
https://www.expressjs.com.cn/resources/middleware.html
6 封装一个中间件
b.js
const express = require('express');
//引入封装好的中间件
const middle = require('./a');
var app = express();
// 使用封装的中间件,并且设置一个接口
app.use('/:name/age/:age',middle());
app.get('',(req,res)=>{
console.log('aaa');
})
app.listen(2500);
a.js 利用模块封装的一个中间件
module.exports = function(){
return function(req,res,next){
console.log(req.params);
res.send(req.params);
next()
}
}
get请求测试
http://localhost:2500/wh/age/21
get请求返回结果:
{"name":"wh","age":"21"}
本地打印结果
{ name: 'wh', age: '21' }