• Node: Express的中间件的使用


    一、简介

    Express框架为开发者提供了一个中间件功能,这个中间件在服务的请求-响应过程提供一个可以修改内容的机会。中间件的完整结构是这样的,它必须是一个函数,可以访问的参数有错误对象err、请求对象req、响应对象res、以及另一个中间件next函数。next函数的作用是可以将当前中间件的控制权进行转交向下传递。大致结构如下:

    // 中间件完整的结构
    // 1、是一个函数
    // 2、可选参数:err、req、res、 next, 注意:err/req/res均为对象、 next为函数,也是下一个中间件
    function middleware(err, req, res, next) {
        //中间件负责的工作可以包括以下几种:
        //1、异常处理
        //2、功能函数,处理一下业务功能,然后转交控制权
        //3、响应请求----->结束响应----->当做路由的处理函数
    }

    二、应用

    对中间件结构有了初步了解后,现在可以简单使用一下中间件这个功能。例如,对所有发送的HTTP请求,验证其参数的合法性。如果验证成功,则继续后续的请求操作。代码如下:

    //导入express框架
    const express = require('express');
    
    //创建express服务实例
    const app = express();
    
    //定义一个验证参数的中间件
    function valid_name_middleware(req, res, next)  {
        let {name} = req.query;
        if (!name || !name.length) {
            res.json({
                message:'缺少name参数'
            })
        }else{
            next(); //转交控制权
        }
    }
    
    //1、这里首先会验证所有的HTTP请求
    app.all('*', valid_name_middleware);
    
    //2、如果合法,接着才会进行get请求
    app.get('/demo', (req, res) => {
        res.json({
            message: 'response success for demo'
        })
    })
    
    //监听
    app.listen(3000, ()=>{
        console.log('服务器启动了!');
    });

    三、类型

    1、应用级别的中间件

    在全局作用域上起作用,处于最顶层结构上,在app实例化时就立马注册使用它。使用app.use----api去加载。

    //导入express框架
    const express = require('express');
    
    //创建express服务实例
    const app = express();
    
    //自定义一个logger中间件
    function logger_middleware(req, res, next) {
        console.log('请求来了!');
        next();
    }
    
    //注册到app全局的级别上
    app.use(logger_middleware);
    
    //监听
    app.listen(3000, ()=>{
        console.log('服务器启动了!');
    });
    //终端结果如下:
    [nodemon] restarting due to changes...
    [nodemon] starting `node src/app.js`
    服务器启动了!
    请求来了! 

    2、系统内置的中间件

    express.static是express内置的中间件之一,基于serve-static,它负责处理应用中的静态资源的。还有express.json()express.static()express.Router()express.urlencoded()

    //导入express框架
    const express = require('express');
    
    //创建express服务实例
    const app = express();
    
    //加载一个 public 的中间件
    //express.static(root, [options]):参数 root 指提供静态资源的根目录路径
    //可选的 options 参数可参考官方文档:http://www.expressjs.com.cn/4x/api.html#express.static
    app.use(express.static('public',{
    
    }))
    
    //监听
    app.listen(3000, ()=>{
        console.log('服务器启动了!');
    });

    3、第三方提供中间件

    cookie-parser和multiparty都是第三方提供的中间件,cookie-parser是用来解析cookie的,multiparty则是用来进行表单或图片等资源上传的。

    //导入express框架
    const express = require('express');
    
    //创建express服务实例
    const app = express();
    
    //加载第三方解析cookie的中间件:cookie-parser
    //先安装"cookie-parser":  npm install cookie-parser -D
    //然后使用use加载 cookie 解析中间件
    var cookieParser = require('cookie-parser');
    app.use(cookieParser());
    
    //加载第三方上传资源的中间件:multiparty
    //先安装"multiparty":  npm install multiparty -D
    const multiparty = require('multiparty');
    app.post('/upload', (req, res) => {
        let form = new multiparty.Form()
        form.uploadDir = './images';//指定图片的文件夹
        form.parse(req,function(err,fields,files){
           //获取提交的数据以及图片上传成功返回的图片信息 field是表单数据,files为图片信息
        })
    })
    
    //监听
    app.listen(3000, ()=>{
        console.log('服务器启动了!');
    });

    4、路由级别的中间件

    在前面介绍路由时,对路由进行拆分后统一到应用顶层进行注册时,用到的方式就是将路由作为中间件使用。也是使用use()函数。

    //导入express框架
    const express = require('express');
    
    //创建express服务实例
    const app = express();
    
    //导入路由
    const userRouter = require('./user.router')
    
    //注册路由,将路由当做中间件,放在应用级别上
    app.use(userRouter);
    
    //也可以给userRouter配一个父级别的路由, 相当于起了一个命令空间的作用
    app.use('/user', userRouter);
    
    //此时,访问"http://127.0.0.1:3000/information" 和 "http://127.0.0.1:3000/user/information"都可以请求成功
    
    //监听
    app.listen(3000, ()=>{
        console.log('服务器启动了!');
    });

    上面的路由作为中间件放在了应用级别上,此时还可以在路由内部定义中间件,需要修改user.router.js文件如下:

    //导入express框架
    const express = require('express');
    
    //定义一个路由
    const router = express.Router();
    
    /*
    
    //第一个场景:在路由内部定义一个中间件
    router.use(function(req, res, next){
        console.log('logger from inner router');
        next();
    })
    //发起get请求
    router.get('/information', (req, res) => {
        res.json({
            message:"from router user !"
        })    
    })
    
    */
    
    //第二个场景:针对单个路由,支持中间件栈,也就是一个数组,依次执行
    function valid_login_parms_middleware(req, res, next) {
        let{username, password} = req.query;
        if (!username || !password) {
            res.json({
                message:"参数校验失败!"
            })
        }
        else{
            //将内容传递给next
            req.result = {
                username,
                password
            }
            next(); //转交控制权
        }
    }
    //发起get请求
    //第2个参数是数组,可以放很多个中间件,依次执行
    router.get('/login', [valid_login_parms_middleware], (req, res) => {
        let {result} = req;
        res.json({
            result,
            message:"from router user ! login success!"
        })    
    })
    
    
    //将路由暴露出来
    module.exports = router;

    第一种场景Postman运行的结果还是一样,不过在get请求响应之前,路由内部定义的中间件会先执行,然后由next函数转交控制权给get请求。

    //终端结果如下:
    [nodemon] restarting due to changes...
    [nodemon] starting `node src/app.js`
    服务器启动了!
    logger from inner router

    第二个场景Postman运行的结果如下:

     5、异常处理的中间件

    中间件的参数中有一个err对象可以访问,因此,开发者可以定制一个处理异常的中间件,将请求错误的日志可视化展现出来,提高开发效率。注意,处理异常的中间件必须注册到所有路由的底部,这样才能监听异常。

    //导入express框架
    const express = require('express');
    
    //创建express服务实例
    const app = express();
    
    //发送一个get请求,抛出异常
    app.get('/user', (req, res) => {
        throw new Error('测试接口异常!')
    })
    
    //监听
    app.listen(3000, ()=>{
        console.log('服务器启动了!');
    }); 

    这个方式抛出的这个日志很复杂,非常不利于查找原因,截图如下:

    此时修改这个文件,定制一个异常处理的中间件,此时抛出来的日志相当明显,非常清新,修改和截图如下:

    //导入express框架
    const express = require('express');
    
    //创建express服务实例
    const app = express();
    
    //发送一个get请求
    app.get('/user', (req, res) => {
        throw new Error('测试接口异常!')
    })
    
    //定义一个异常处理的中间件
    function error_handle_middleware(err, req, res, next) {
        let {message} = err;
        if (err) {
            res.status(500)
            res.json({
                message:`${message || '服务器异常'}`
            })
        }else{
            //    
        }
    }
    
    //err为空时,这个是最后处理不了一般的错误时,报404。
    function not_found_handler(err, res, next) {
        res.json({
            message:'api不存在!'
        })
    }
    
    app.use(error_handle_middleware);
    app.use(not_found_handler);
    
    //监听
    app.listen(3000, ()=>{
        console.log('服务器启动了!');
    });

  • 相关阅读:
    Python中的BeautifulSoup模块
    requests模块
    requests模块
    python中让输出不换行
    python中让输出不换行
    我为Dexposed续一秒——论ART上运行时 Method AOP实现
    Python2中的urllib、urllib2和 Python3中的urllib、requests
    Python2中的urllib、urllib2和 Python3中的urllib、requests
    Fidder抓包软件的使用
    Fidder抓包软件的使用
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/12119902.html
Copyright © 2020-2023  润新知