WEB开发: Node.js路由之由浅入深(三)自动配置路由 - 全栈工程师入门

前面我们一起学习了Node.js路由的两个进阶,

(1)WEB开发: Node.js路由之由浅入深(一) - 全栈工程师入门

(2)WEB开发: Node.js路由之由浅入深(二)自动路由 - 全栈工程师入门

在第二进阶中,我们已经通过将路由结构模块化,实现了比较方便的而路由方法。

一、进阶分析

但是,你会发现这个文件需要手工去编写:

bash 复制代码
/project
  /routes
    routesConfig.js

对,就是这个routesConfig.js,每次新增或者删除、修改路由的控制文件,可能都要更改这个文件。

它的内容是这样的:

javascript 复制代码
// routesConfig.js
module.exports = [
    { method: 'get', path: '/auth/login', controller: 'authController', action: 'login' },
    { method: 'get', path: '/user/:id', controller: 'userController', action: 'getUserById' },
    { method: 'post', path: '/product', controller: 'productController', action: 'createProduct' },
    { method: 'post', path: '/auth/login', controller: 'authController', action: 'login' }
    // 更多路由...
];

/*
@method: 对应来自 访问端 的RESTful API 方法 
@path: 定义来自访问端的路径
@controller 根据method 和 path  来定位使用什么控制器
@action 定义使用控制器中的什么函数
*/

仔细观察你会发现,这里面的内容,和我们控制器以及控制器内的配置是存在对应关系的,也就是

method: 这个是api进来的请求方式

controller: 这个是我们控制器的文件名

action: 这个是我们控制器内的函数名

唯一一个没有对应关系的是 path。

那么搞清楚这个关系,就好办了。

二、更改控制器

既然path和控制器的文件名、内容都无关,那么我们是否可以将这个关系写到控制器内,然后通过自动读取文件夹、解析文件内容的方式,来自动生成这个routesConfig.js文件呢?

答案当然是可以的。

所以我们只需要修改下面两部分:

第一部分,修改控制器的写法,比如userController.js的写法,改成这样:

bash 复制代码
// userController.js
module.exports = {
    get: {
        getUserById: {
            path: '/user/:id',
            fn: (req, res) => {
                const userId = req.params.id;
                res.send(`User ID: ${userId}`);
            },
        }
    },
    post: {
        getUserById: {
            path: '/user/:id',
            fn: (req, res) => {
                const userId = req.params.id;
                res.send(`User ID: ${userId}`);
            }
        },
    }
    // 更多方法...
};

看到了吗 ,我们把控制器分成了 get 和post 两类,当然你也可以加put delete。

然后我们这里面加入了 path。 也就是说当你写控制器的时候,你就顺手将path 写进去了,不需要去写其他的文件。fn就是我们之前的action。

所以这个路由的get调用就是: 控制器.get.getUserById.fn() ,路径就是: 控制器.get.getUserById.path

三、更改app.js

所以我们需要更改一下app.js 的动态路由方法,改动后如下:

bash 复制代码
// 动态加载路由
routesConfig.forEach(route => {
    const controller = require(`./controllers/${route.controller}`);  // 动态加载控制器
    app[route.method](route.path, controller[route.method][route.action].fn);  // 将路由与控制器方法绑定

    console.log('for review route:', route.method, route.path, controller[route.method][route.action].fn)

});

看到了吗,route.path, controller[route.method][route.action].fn 对应了我上面的解释。

四、自动生成路由配置

到这里,整个路由逻辑完成了,但是我们需要自动生成路由配置文件,而不是手写。

所以我们需要增加一个routesConfigMake 的脚本: rcMake.js:

javascript 复制代码
const fs = require('fs');
const path = require('path');

const rcMake = () => {
    // 定义 controllers 目录
    const controllersDir = path.join(__dirname, 'controllers');

    // 获取 controllers 目录下的所有文件(同步方法)
    let files;
    try {
        files = fs.readdirSync(controllersDir);
    } catch (err) {
        console.error('无法读取 controllers 目录:', err);
        return;
    }

    // 用于保存所有路由信息的数组
    const routes = [];

    // 逐一处理每个文件
    files.forEach(file => {
        const filePath = path.join(controllersDir, file);
        const fileName = path.basename(file, '.js'); // 去掉文件扩展名

        // 只处理 .js 文件
        if (path.extname(file) === '.js') {
            let controller;
            try {
                controller = require(filePath);
            } catch (err) {
                console.error(`无法加载文件 ${file}:`, err);
                return;
            }

            // 遍历 controller 中的 HTTP 方法(get, post 等)
            Object.keys(controller).forEach(method => {
                const methodRoutes = controller[method];

                // 遍历每个方法的路由
                Object.keys(methodRoutes).forEach(action => {
                    const route = methodRoutes[action];
                    routes.push({
                        method: method,
                        path: route.path,
                        controller: fileName,
                        action: action
                    });
                });
            });
        }
    });

    // 生成 routes.js 文件的内容
    const routesContent = `// routes.js\nmodule.exports = ${JSON.stringify(routes, null, 2)};\n`;

    // 将生成的内容写入 routes.js 文件(同步方法)
    try {
        fs.writeFileSync(path.join(__dirname, '/routers/routesConfig.js'), routesContent);
        console.log('routesConfig.js 文件已生成');
    } catch (err) {
        console.error('写入 routesConfig.js 文件失败:', err);
    }
};

module.exports = rcMake;

这个脚本放在和app.js 中 ,在app.js的最开始调用,自动将我们控制器内的配置写在这个配置文件中,执行后生成routesConfig.js文件,内容如下:

javascript 复制代码
// routes.js
module.exports = [
  {
    "method": "get",
    "path": "/auth/login",
    "controller": "authController",
    "action": "login"
  },
  {
    "method": "post",
    "path": "/auth/login",
    "controller": "authController",
    "action": "login"
  },
  {
    "method": "get",
    "path": "/product",
    "controller": "productController",
    "action": "createProduct"
  },
  {
    "method": "post",
    "path": "product",
    "controller": "productController",
    "action": "createProduct"
  },
  {
    "method": "get",
    "path": "/user/:id",
    "controller": "userController",
    "action": "getUserById"
  },
  {
    "method": "post",
    "path": "/user/:id",
    "controller": "userController",
    "action": "getUserById"
  }
];

请注意,这时候你必须所有的控制器都按照我前面提到的方式来改写,这里包括了 get 和post 两类,其他自己可以加。,app.js 会自动调用这个配置的。

五、更新app.js

最后,app.js 需要加上这个脚本:

javascript 复制代码
const express = require('express');
const app = express();

//加上脚本 自动生成路由配置文件
const rcMake = require('./rcMake.js')
rcMake()

const routesConfig = require('./routers/routesConfig');  // 导入路由配置文件


// 动态加载路由
routesConfig.forEach(route => {
    const controller = require(`./controllers/${route.controller}`);  // 动态加载控制器
    app[route.method](route.path, controller[route.method][route.action].fn);  // 将路由与控制器方法绑定

    console.log('for review route:', route.method, route.path, controller[route.method][route.action].fn)

});

// 启动服务
const port = 3000;
app.listen(port, () => {
    console.log(`Server is running on port ${port}`);
});

好了,这样,你的工作就只需要关注在写控制器上,而无需关注路由配置,因为路由配置都自动化了。这样多方便?

需要完整的项目文件,请给我留言。

相关推荐
IT瘾君1 小时前
JavaWeb:Html&Css
前端·html
264玫瑰资源库2 小时前
问道数码兽 怀旧剧情回合手游源码搭建教程(反查重优化版)
java·开发语言·前端·游戏
喝拿铁写前端2 小时前
从圣经Babel到现代编译器:没开玩笑,普通程序员也能写出自己的编译器!
前端·架构·前端框架
HED2 小时前
VUE项目发版后用户访问的仍然是旧页面?原因和解决方案都在这啦!
前端·vue.js
拉不动的猪3 小时前
前端自做埋点,我们应该要注意的几个问题
前端·javascript·面试
王景程3 小时前
如何测试短信接口
java·服务器·前端
安冬的码畜日常3 小时前
【AI 加持下的 Python 编程实战 2_10】DIY 拓展:从扫雷小游戏开发再探问题分解与 AI 代码调试能力(中)
开发语言·前端·人工智能·ai·扫雷游戏·ai辅助编程·辅助编程
小杨升级打怪中3 小时前
前端面经-JS篇(三)--事件、性能优化、防抖与节流
前端·javascript·xss
清风细雨_林木木3 小时前
Vue开发网站会有“#”原因是前端路由使用了 Hash 模式
前端·vue.js·哈希算法
鸿蒙布道师4 小时前
OpenAI为何觊觎Chrome?AI时代浏览器争夺战背后的深层逻辑
前端·人工智能·chrome·深度学习·opencv·自然语言处理·chatgpt