1.中间件
自定义中间件
内置中间件
第三方中间件
2.如何使用中间件
1)中间件函数
a.有两个参数 :callback(req,res) 路由的回调函数
b.有三个参数:callback(req,res,next) 中间件函数
app.use(path,callback)
使用中间件,必须使用use方法,而且在使用中间件件是,一般需要携带next参数
关于use方法:
1)path参数是可选的,默认: /
2)若传递了path参数,后续参数为中间件方法,基本格式为:
(req,res,next)=>{}
use的使用情形类似于all方法,能够匹配一切http 请求方法;
它的路径作用不同于get或post等路由配置中 path的作用,如下:
use的path路径匹配原则:
/ 匹配 /,/about,/admin,/a/b/c(所以use中的path / 可以匹配一切url路径)
/apple 匹配 /apple,/apple/1,/apple/1/2
3)由于中间件的功能是为下面的路由 提供一种统一的解决方案,所以一般use中间件都会放置在路由的上面。
重要:切记!!!在使用中间件处理完毕数据后,一定要调用next方法,否则后续代码或路由都无法执行或匹配。
3.自定义中间件
1)自定义解析post参数的中间件
//post参数解析中间件
function bodyParser(req,res,next){
let arr = [];
req.on("data", chunk => {
arr.push(chunk);//将读取到的数据存储到数组中
});
req.on('end', () => {
//post 数据读取完毕
let data = Buffer.concat(arr).toString();
// console.log(qs.parse(data));
req.body = qs.parse(data);//将读取到的post参数数据存储到request对象中body属性中
next();//注意,一定要数据读取完毕之后,在顺延(转发)
})
}
//自定义post参数解析中间件
app.use(bodyParser);
2)自定义错误处理的中间件
//错误处理中间件
app.use((req,res,next)=>{
// res.status(404)
// res.statusCode=404;//node原生
// res.statusMessage='error';
res.status(404).send({
msg:"页面未找到"
});
});
4.内置中间件
express.static能够指定指定目录为静态资源目录
app.use(express.static(‘目录名称’));
//使用内置中间件
//挂载静态资源
app.use(express.static('public'));//指定public目录中内容为静态资源
//虚拟目录 api/
// app.use('/api',express.static('public'));
app.use(express.json());//能够处理post请求中的json数据
app.use(express.urlencoded());//能够处理post请求中的urlencodeed格式的数据
5.第三方中间件
1)nodemon
服务端代码一旦进行了修改,就需要重新将代码部署到服务器,这个操作非常频繁,可以通过nodemon来进行一个自动化配置和部署(热更新)
npm i nodemon -D
在项目根目录下新建文件nomon.json,将如下代码拷贝进去:
{
"restartable": "rs",
"ignore": [
".git",
".svn",
"node_modules/**/node_modules"
],
"verbose": true,
"execMap": {
"js": "node --harmony"
},
"watch": [],
"env": {
"NODE_ENV": "development"
},
"ext": "js json"
}
图形验证码的中间件,使用该中间件,可以生产一个图形验证码
安装:
npm install --save svg-captcha
使用:
const svgCaptcha =require('svg-captcha');//引入svg-captcha模块
//生产验证码路由
app.get('/code',(req,res)=>{
// var captcha = svgCaptcha.create({
// size:6, //验证码字符的个数 默认4
// noise:3 , //干扰线的个数 默认1
// color:"#000", //字符的颜色
// background:"#cc9966" //背景色
// });//初始化
let captcha=svgCaptcha.createMathExpr({
mathMin:1,
mathMax:90
});//计算类型
console.log(captcha.text);//文本内容
res.type('svg');
res.status(200).send(captcha.data);//将生成的验证码发送给客户端
})
用于服务器端设置favicon视觉提示,其实就是浏览器标签标题栏上的小图标
安装:
npm install serve-favicon --save
使用:
const favicon=require(‘serve-favicon’);//引入模块
app.use(favicon(path.join(__dirname,‘public’,‘youjiuye.ico’)));
multer是一个node.js中间件,用于处理多部分/表单数据,主要用于上传文件
安装:
npm install --save multer
使用:
方式1:通过form表达上传
<!--HTML布局代码 -->
<form action="http://localhost:3000/uploadImg" method="post" enctype="multipart/form-data">
<input type="file" name="avatar">
<input type="submit" value="提交">
</form>
//接口代码
//接收上传的图片
app.post('/uploadImg', upload.single('avatar'), function (req, res, next) {
// console.log(req.file);
let {
originalname,filename}=req.file;//解析文件的名称
fs.renameSync(`./uploads/${
filename}`,`./uploads/${
originalname}`);//将文件重命名
res.send({
msg: "图片上传成功" });
})
方式2:通过ajax上传
HTML代码:
<input type="file" name="avatar">
<button>提交</button>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
Js代码
<script>
let fileObj = null;//保存要上传的文件数据
$(':file').change(function () {
// console.log(this.files);
fileObj = this.files[0];//
});
$('button').click(function () {
let formData=new FormData();
formData.append("avatar",fileObj);
// console.log(formData.get('avatar'));
$.ajax({
url: 'http://localhost:3000/uploadImg',
type: "post",
data: formData,
contentType: false,//改变上传的数据处理格式
processData: false,//改变上传的数据处理格式,参考jQuery手册
success(data) {
console.log(data);
},
error(err) {
console.log(err);
}
});
});
</script>
原先代码中使用app来进行路由的匹配和分发功能,但是它有一个弊端,不方便进行模块化的封装,若项目工程比较大,这时候推荐使用路由级别的路由。express.Router()
1)定义模块路由
const express=require('express');
const router=express.Router();//获取一个路由实例
//跟路由
router.get('/',(req,res)=>{
res.send('index页面的根路径');
});
//商品列表
router.get('/goodslist',(req,res)=>{
res.send('index页面商品列表');
})
module.exports=router;
注意:一定要定义完毕之后导出这个路由
2)在入口文件中引用定义的各个路由模块
const indexRouter=require('./router/indexRouter');//引用indexRouter
const userRouter=require('./router/userRouter');
const goodsRouter=require('./router/googsRouter');
//设置各个页面路由
app.get('/',(req,res)=>{
res.redirect('/index');//重定向到index页面
})
app.use('/index',indexRouter);
app.use('/user',userRouter);
app.use('/goods',goodsRouter);
//...
说明:在使用路由级别的路由的时候,在入口文件中应该使用use方法(像使用中间件一样去使用路由)去使用。
注意 :app.use()中配置的path是一个一级路由,也就是说,对应的router中的路由均为二级甚至是三级路由
例如:
app.use(‘/index’,indexRouter);
访问IndexRouter中/main路由,则需要写成: /index/main