Nodejs 让express的路由支持module, controller, action格式

Nodejs 让express的路由支持module, controller, action格式

很多mvc框架都有controller和action的概念,很多后端程序员也比较熟悉,我一般是这样解决的

router.js

var siteController = require('./site.js');
var routingTable={
  default:{site:siteController}
};

var dispatch = function(module,controller,action,req,res, next) { if (module[controller]){ if (module[controller][action]){ var index = 0; var handles = module[controller][action]; var next_handle = function(err){ if (err){ next(err); } else{ var handle = handles[index++]; if(!handle){ next(err); } else{ handle(req,res, next_handle); } } };

        next_handle();
    }
    else{
        next();
    }
}
else{
    next();
}

};

exports.route = function(module, controller, action, req, res, next){ if(routingTable[module]){ dispatch(routingTable[module], controller, action, req, res, next); } else{ next(); } };

site.js

var index_filter = function(req,res, next){};
var index = function(req, res, next){
  res.render('index', {});
};
module.exports = {
  index:[index_filter, index]
};

app.js

var router = require(’./roter.js’); // Routes app.get(’/’, function(req, res, next){ router.route(‘default’, ‘site’, ‘index’, req, res, next); });

app.all('/:controller', function(req, res, next){
     router.route('default', req.params.controller, 'index', req, res, next);
});

app.all(’/:controller/:action’, function(req, res, next){ router.route(‘default’, req.params.controller, req.params.action, req, res, next); });

app.get(’/:controller/:action/:id’, function(req, res, next){ router.route(‘default’, req.params.controller, req.params.action, req,res, next); });

app.all(’/:module/:controller/:action’, function(req, res, next){ router.route(req.params.module, req.params.controller, req.params.action, req, res, next); });


5 回复

Nodejs 让express的路由支持module, controller, action格式

很多MVC框架都有Controller和Action的概念,这在后端编程中非常常见。为了在Express应用中实现类似的功能,我们可以设计一个路由分发机制,使得路由可以按照module, controller, action的格式进行处理。

示例代码

首先,我们定义一个路由文件router.js来管理路由分发逻辑:

// router.js
var siteController = require('./site.js');
var routingTable = {
  default: { site: siteController }
};

var dispatch = function(module, controller, action, req, res, next) {
    if (module[controller]) {
        if (module[controller][action]) {
            var index = 0;
            var handles = module[controller][action];
            var next_handle = function(err) {
                if (err) {
                    next(err);
                } else {
                    var handle = handles[index++];
                    if (!handle) {
                        next(err);
                    } else {
                        handle(req, res, next_handle);
                    }
                }
            };
            next_handle();
        } else {
            next();
        }
    } else {
        next();
    }
};

exports.route = function(module, controller, action, req, res, next) {
    if (routingTable[module]) {
        dispatch(routingTable[module], controller, action, req, res, next);
    } else {
        next();
    }
};

接下来,在site.js中定义具体的Controller和Action,并且可以包含中间件:

// site.js
var index_filter = function(req, res, next) {
    console.log("Index filter executed");
    next();
};

var index = function(req, res, next) {
    res.render('index', {});
};

module.exports = {
    index: [index_filter, index] // 这里可以包含多个中间件
};

最后,在主应用文件app.js中配置路由:

// app.js
var express = require('express');
var router = require('./router.js');
var app = express();

// 定义默认路由
app.get('/', function(req, res, next) {
    router.route('default', 'site', 'index', req, res, next);
});

// 定义通用路由
app.all('/:controller', function(req, res, next) {
    router.route('default', req.params.controller, 'index', req, res, next);
});

app.all('/:controller/:action', function(req, res, next) {
    router.route('default', req.params.controller, req.params.action, req, res, next);
});

app.get('/:controller/:action/:id', function(req, res, next) {
    router.route('default', req.params.controller, req.params.action, req, res, next);
});

app.all('/:module/:controller/:action', function(req, res, next) {
    router.route(req.params.module, req.params.controller, req.params.action, req, res, next);
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. 路由分发:在router.js中,我们定义了一个dispatch函数,用于根据传入的module, controller, action调用相应的处理函数。
  2. Controller 和 Action:在site.js中,我们定义了具体的Controller(例如site)以及其下的Action(例如index),并且可以包含中间件(如index_filter)。
  3. 路由配置:在app.js中,我们配置了各种路由模式,如根路径、通用路径等,并通过router.route方法将请求转发给对应的Controller和Action进行处理。

这种方式可以让我们更加灵活地管理和扩展路由,同时也保持了代码的清晰性和可维护性。


赞一个

欠缺一些项目测试的经验。

欠缺一些项目测试的经验。

根据你提供的代码示例,我们可以创建一个简单的 Express 应用程序,使其支持 module, controller, action 的路由结构。下面是实现这一功能的具体步骤:

  1. 定义路由表:我们首先需要定义路由表来映射模块到控制器。
  2. 创建调度函数:该函数负责处理请求并调用相应的控制器方法。
  3. 设置控制器:每个控制器可以包含多个方法以及中间件。

示例代码

1. 路由表 (router.js)

const express = require('express');
const app = express();

const siteController = require('./controllers/site');

const routingTable = {
  default: {
    site: siteController
  }
};

const dispatch = (module, controller, action, req, res, next) => {
  if (module[controller]) {
    if (module[controller][action]) {
      const handlers = module[controller][action];
      let i = 0;

      const nextHandler = () => {
        if (i >= handlers.length) return next();
        
        const handler = handlers[i++];
        handler(req, res, nextHandler);
      };
      
      nextHandler();
    } else {
      next();
    }
  } else {
    next();
  }
};

const route = (module, controller, action, req, res, next) => {
  if (routingTable[module]) {
    dispatch(routingTable[module], controller, action, req, res, next);
  } else {
    next();
  }
};

app.use((req, res, next) => {
  route(req.params.module, req.params.controller, req.params.action, req, res, next);
});

module.exports = route;

2. 控制器 (controllers/site.js)

const indexFilter = (req, res, next) => {
  console.log("Index Filter Executed");
  next();
};

const indexAction = (req, res) => {
  res.send("Site Index Page");
};

module.exports = {
  index: [indexFilter, indexAction]
};

3. 主应用文件 (app.js)

const express = require('express');
const app = express();
const route = require('./router');

app.set('views', './views');
app.set('view engine', 'ejs');

app.get('/', (req, res, next) => {
  route('default', 'site', 'index', req, res, next);
});

app.all('/:controller', (req, res, next) => {
  route('default', req.params.controller, 'index', req, res, next);
});

app.all('/:controller/:action', (req, res, next) => {
  route('default', req.params.controller, req.params.action, req, res, next);
});

app.get('/:controller/:action/:id', (req, res, next) => {
  route('default', req.params.controller, req.params.action, req, res, next);
});

app.all('/:module/:controller/:action', (req, res, next) => {
  route(req.params.module, req.params.controller, req.params.action, req, res, next);
});

app.listen(3000, () => {
  console.log('App is running on http://localhost:3000');
});

解释

  • 路由表 (routingTable) 定义了模块到控制器的映射关系。
  • 调度函数 (dispatch) 负责调用控制器中的方法,并允许使用中间件。
  • 主应用文件 (app.js) 设置了不同类型的路由,并将请求传递给路由处理函数 (route)。

这种方式可以使你的 Express 应用更接近传统的 MVC 模式,使得路由更加清晰和易于维护。

回到顶部