中间件的分类 讲解

19 阅读5分钟

1. 全局中间件

const express = require("express");
const { allRouter } = require("./router");
const fs = require("fs");

// 1. 创建一个服务器
const server = express();

/**
 *  后续新增功能: 将每一次请求, 记录到 隔壁的 index.txt 文件
 *
 *      因为每一次请求进入到对应的 静态资源 或者 接口处理后, 就不会再触发后续的代码了
 *
 *      所以当前的全局中间件, 必须书写在 1.1 和 1.2 之前
 * 
 * 
 *      每一个自定义的中间件, 进入后请求到此暂时中断, 需要我们指定是否继续向下运行
 *      如果需要向下运行, 那么需要借助当前函数的第三个形参, 这个形参是一个函数, 当你调用之后, 就会向下运行到下一个环节     注意  第三个形参 在中间介代码末尾运行
 */
 
    1. 全局中间件
        server.use((req, res, next) => {
            fs.appendFile(
                "./index.txt",                      // req.url 浏览器中发起请求的地址 ,有html,js等
                `时间: ${new Date()} ---> 请求地址: ${req.url} \n`,
                () => next()
            );
        });

// 1.1 引入静态资源
server.use("/static", express.static("./client"));

// 1.2 配置接口处理
server.use("/api", allRouter);

// 2. 给服务器添加一个端口号
server.listen(8080, () => console.log("服务器启动成功"));

/**
 *  中间件的分类
 *
 *          1. 全局中间件
 *              服务器.use(参数1, 参数2)
 *                  参数1: 是表示以什么路径开头
 *                  参数2: 如果路径的开头符合 参数1 的要求, 那么执行参数2 的代码
 *
 *              参数1 可以不传递
 *
 *          2. 路由中间件
 *              路由表.use(参数1, 参数2)
 *                  参数1: 是表示以什么路径开头
 *                  参数2: 如果路径的开头符合 参数1 的要求, 那么执行参数2 的代码
 *
 *              参数1 可以不传递
 *
 *          3. 请求中间件
 *              在 请求的处理函数前, 在书写一个 函数
 *
 *
 *          4. 全局错误处理中间件
 */
 
 
 

路由中间件

 // 内部存储购物车相关的路由分表
    const express = require("express");
    const { cartList, cartAddItem, cartDelItem } = require("../controller/cart");

    // 1. 创建一张路由分表
    const cartRouter = express.Router();

// 1.1 因为当前的 购物车接口全都需要登陆过才能使用, 所以我们将 token 的校验, 添加到 路由中间件中
        cartRouter.use((req, res, next) => {
        //req.headers  就是请求头
        if (req.headers.authorization === "10086") {
            /**
             *  当前 分支能够执行, 说明按照我们目前的约定 token 一定没有问题
             *  那么我们就不再做其他的处理, 让请求继续向下运行即可
            */
       
            next()
        } else if (req.headers.authorization === "10010") {
            res.send({
                code: 0,
                msg: "token 过期, 请重新登陆获取最新的 token",
            });
        } else if (req.headers.authorization === undefined) {
            res.send({
                code: 0,
                msg: "您没有传递 token, 请正确传递 token",
            });
        } else {
            res.send({
                code: 0,
                msg: "token 不正确",
            });
        }

    });

    // 2. 向路由分表上添加一些接口
    cartRouter.get("/list", cartList);
    cartRouter.get("/addItem", cartAddItem);
    cartRouter.get("/delItem", cartDelItem);


    // 3. 导出当前路由分表, 给路由总表使用
    exports.cartRouter = cartRouter;

请求中间介

const express = require("express");
const { cartList, cartAddItem, cartDelItem } = require("../controller/cart");

// 创建一个 路由分表表
const Router = express.Router();

// 路由中间件
Router.use((req, res, next) => {
    if (req.headers.authorization === "10086") {
        next();
    } else if (req.headers.authorization === "10010") {
        res.send({
            code: 0,
            msg: "token 过期",
        });
    } else if (req.headers.authorization === undefined) {
        res.send({
            code: 0,
            msg: "您没有传递 token",
        });
    } else {
        res.send({
            code: 0,
            msg: "token 不正确",
        });
    }
});

// 向路由分表上添加一些接口    请求中间介
        Router.get(
            "/list",
            (req, res, next) => {
                /**
                 *  1. 判断用户有没有传递 用户ID, 并且去数据库查询有没有对应的ID
                 *
                 *      在 express 框架中, 一个接口的请求报文中的参数, 会被 express 解析到 req.query 中
                 *
                 *      但是注意, 只有 get 请求会被解析, post 请求 不会被解析, post 需要我们像以前写原生服务器一样, 自己解析
                 */
                // console.log(req.query);

                if (req.query.userid === undefined) {
                    return res.send({
                        code: 0,
                        msg: "参数不够",
                    });
                }

                next();
            },
            cartList
                          
          );
                          
                Router.get(
                    "/addItem",
                    (req, res, next) => {
                        // 1. 判断用户有没有传递 用户ID 和 商品ID
                        const { userid, goodsid } = req.query;

                        if (!userid || !goodsid) {
                            return res.send({
                                code: 0,
                                msg: "参数不够",
                            });
                        }

                        next();
                    },
                    cartAddItem
                );
      Router.get(
                "/delItem",
                (req, res, next) => {
                    // 1. 判断用户有没有传递 用户ID 和 商品ID
                    const { userid, goodsid } = req.query;

                    if (!userid || !goodsid) {
                        return res.send({
                            code: 0,
                            msg: "参数不够",
                        });
                    }

                    next();
                },
                cartDelItem
            );


exports.cartRouter = Router;


全局错误处理中间件

    const express = require("express");
    const { allRouter } = require("./router");
    const fs = require("fs");

    // 创建服务器
    const server = express();

    // 全局中间件
    server.use((req, res, next) => {
        fs.appendFile(
            "./index.txt",
            `时间: ${new Date()} ---> 请求地址: ${req.url} \n`,
            () => next()
        );
    });

    // 配置静态资源
    server.use("/static", express.static("./client"));

    // 配置接口处理
    server.use("/api", allRouter);

    // 全局错误处理中间件有一个固定的位置, 一定是在服务器文件的最后
    server.use((err, req, res, next) => {
        /**
         *  当前中间件只是为了将我们的错误 放在一个统一处理的地方
         *
         *      错误:
         *          token 过期
         *          token 不正确
         *          token 没有传递
         *          参数 不够
         *          参数 传递的不正确
         *          ......
         *
         *      我们可以给这些预估的错误 约定一个编号
         *          将来在其他位置的时候遇到了某一个错误
         *          我们直接将当前的请求跳转到 这个错误处理中间件
         *          并且根据错误的编号, 做出不同的反馈
         *
         *      这里我们和我们项目的所有后端开发人员做一个约定
         *          编号:
         *              token 过期              1
         *              token 不正确            2
         *              token 没有传递          3
         *              参数 不够               4
         *              参数 传递的不正确        5
         *              ......
         */

        if (err === 1) {
            res.send({
                code: 0,
                msg: "token 过期",
            });
        } else if (err === 2) {
            res.send({
                code: 0,
                msg: "token 不正确",
            });
        } else if (err === 3) {
            res.send({
                code: 0,
                msg: "您没有传递 token",
            });
        } else if (err === 4) {
            res.send({
                code: 0,
                msg: "参数不够",
            });
        } else if (err === 5) {
            res.send({
                code: 0,
                msg: "参数不正确",
            });
        }
    });

    // 配置端口号
    server.listen(8080, () => console.log("服务器启动成功"));

处理页面 联动全局错误处理中间件

    exports.cartListMid = (req, res, next) => {
        /**
         *  1. 判断用户有没有传递 用户ID, 并且去数据库查询有没有对应的ID
         *
         *      在 express 框架中, 一个接口的请求报文中的参数, 会被 express 解析到 req.query 中
         *
         *      但是注意, 只有 get 请求会被解析, post 请求 不会被解析, post 需要我们像以前写原生服务器一样, 自己解析
         */

        if (req.query.userid === undefined) return next(4);

        next();
    };
    
    
   参数 不够 4
             exports.cartAddItemMid = (req, res, next) => {
                // 1. 判断用户有没有传递 用户ID 和 商品ID
                const { userid, goodsid } = req.query;

                if (!userid || !goodsid) return next(4);

                next();
            };

                exports.cartDelItemMid = (req, res, next) => {
                    // 1. 判断用户有没有传递 用户ID 和 商品ID
                    const { userid, goodsid } = req.query;

                    if (!userid || !goodsid) return next(4);

                    next();
                };