Egg
在Koa的基础上,阿里封装了一个企业级的NodeJS框架——egg.js。将Koa的行为进一步分离成controller,service,model三层,并规范了路由的写法——约定式路由。
约定式路由
实现约定式路由的核心方法是load函数,通过fs遍历约定文件夹( controller,service,model… )下的文件,导出文件的内容,生成一个对象挂载到Egg的实例上。
load
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const fs = require("fs"); const path = require("path"); function load(dir, cb) { const url = path.resolve(__dirname, dir); const files = fs.readdirSync(url, { encoding: "ascii" }); files.forEach((filename) => { filename = filename.replace(".js", ""); const file = require(url + "/" + filename); cb(filename, file); }); }
|
initRouter
处理routes下面的文件,约定每一个文件为一个路由,其中的每一个是对应的子路由,这里对路由简单书写,实际可能会更复杂一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function initRouter(app) { const router = new Router(); load("routes", (filename, routes) => { const prefix = filename === "index" ? "" : `/${filename}`; routes = typeof routes == "function" ? routes(app) : routes; Object.keys(routes).forEach((key) => { const [method, path] = key.split(" "); router[method](prefix + path, async (ctx) => { app.ctx = ctx; await routes[key](app); }); }); }); return router; }
module.exports = (app) => ({ "get /": app.$controller.home.index, "get /detail": app.$controller.home.detail, });
|
MVC分离
controller,service,model同理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| const { load } = require("./router-loader");
function initController(app) { const controllers = {};
load("controller", (filename, controller) => { controllers[filename] = controller(app); }); return controllers; }
module.exports = { initController };
module.exports = (app) => ({ index: async (ctx) => { const name = await app.$service.user.getName(); app.ctx.body = "ctrl user" + name; }, detail: (ctx) => { app.ctx.body = "Home Detail"; }, });
const { load } = require("./router-loader");
function initService() { const services = {}; load("service", (filename, service) => { services[filename] = service; }); return services; }
module.exports = { initService };
|
Egg类
本质上是对Koa的扩展,实现MVC结构。
- model层即数据库实体层与数据库中的表一一对应;
- controller层负责前后端交互,接受前端请求,调用service层,接收service层返回的数据,最后返回具体的页面和数据到客户端;
- service层即业务逻辑层,完成业务的功能设计。 主要是针对具体的问题的操作,把一些数据层的操作进行组合,间接与数据库打交道(提供操作数据库的方法) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const { initController } = require("./ctrl-loader"); const Koa = require("./lib/application"); const { initRouter } = require("./router-loader"); const { initService } = require("./service-loader"); const { loadConfig } = require("./config-loader"); class Egg { constructor(conf) { this.$app = new Koa(conf); loadConfig(this); this.$controller = initController(this); this.$service = initService(); this.$router = initRouter(this); console.log(this.$router.stack); this.$app.use(this.$router.routes()); } start(...arg) { this.$app.listen(...arg); } }
module.exports = Egg;
|