说明
- 下面文章是对该系列前面2篇及项目中经验的总结,重新开始写的
- 实现了Mar类,贯穿Router层、Controller层、Service层
- 基本骨架的搭建
初始
- 使用Koa创建一个简单的服务器,一般会使用如下
const koa = require('koa');
const app = new koa();
const Router = require('koa-router');
const router =new Router();
const handleIndex = async ctx => {ctx.body = 'Hello World';
};
const handleListen = async port => {console.log(`[Mar]Server is running at http://localhost:${port}`);
}
router.get('/', handleIndex);
app.use(router.routes());
app.listen(3000, handleListen(3000));
原则
借助Egg的Controller,Service的引用,有了以下灵感:
- 自定义一个类(Mar),在创建实例(app)的时候,会将Controller、Service方法挂载到app上
- 即Mar类是,集中管理各层的初始化及存放通用方法
- Controller层,主要用于联系路由层和Service层
- Service层在操作数据之后,给Controller层提供服务.
设计Mar类
根据上述的原则,我们设计Mar类的初始如下:
const koa = require('koa');class Mar {constructor(conf) {const router = new Router();const controller = new Controller();const service = new Service();this.koa = new koa(conf); // 相当于appthis.router = router.initRouter();this.controller = controller.initController();this.service = service.initService();// this.koa.use(router.routes());}listen(port) {this.koa.listen(port, async () => {console.log(`[mar]Server is running at http://localhost:${port}`);})}
}class Router {constructor(conf) {}initRouter() {console.log('initRouter');}
}class Controller {constructor(conf) {}initController() {console.log('initController');}
}
class Service {constructor(conf) {}initService() {console.log('initService');}
}module.exports = Mar
说明:
1.现在都写在一个Mar里面,后期代码肯定很多,会分开写,然后将模块引入.
2.init函数仅用于测试,后期会根据需求更改
3.此时Mar类的引用如下.
// index.js
const Mar = require('./mar');
const mar = new Mar();
mar.listen(3000);
命令行运行: node index.js
,结果如下
改进Mar类
- 上面测试代码跑通
- 开始逐步完善原则
- Router层负责联系,路由和路由处理事件
- Controller负责路由处理事件
- Service负责处理复杂的方法,然后提供给Controller层
- Mar贯通各个类,负责存储通用方法,并将参数传递给各个层,相当于一个粘合剂贯穿整个流程
[注: 在contructor中,使用this相当于指向实例]
- 改进Mar类如下:
const koa = require('koa');class Mar {constructor(conf) {this.koa = new koa(conf); // 相当于appthis.service = new Service(this);this.controller = new Controller(this.service);this.router = new Router(this.controller);}listen(port) {this.koa.listen(port, async () => {console.log(`[mar]Server is running at http://localhost:${port}`);})}
}class Router {constructor(controller) {console.log('Router:', controller.test());}
}
class Controller {constructor(service) {console.log('controller:', service.test());}test() {return 'Controller for Router'}
}
class Service {constructor(app) {console.log('Service:', app);}test() {return 'Service for Controller'}
}module.exports = Mar
运行后输出如下:
说明:
- 可以看到在Service层,使用(暂时还未写)外面的服务
- 在Controller层使用Service层的服务
- 在Router层使用Controller层的服务
进一步改进Mar类
- 引用分层的目的,是为了使开发更有规范,便于以后自己和他人的阅读.
- 最终目的是提高开发效率,分为近期的和长久的
- 一些通用的功能,就必须提取出来,放在Mar类里面
- 上面在在传递服务给相邻层的时候,并未传入通用方法,因此改变如下
const koa = require('koa');class Mar {constructor(conf) {this.koa = new koa(conf); // 相当于appthis.service = new Service(this); this.controller = new Controller(this);this.router = new Router(this);}listen(port) {this.koa.listen(port, async () => {console.log(`[mar]Server is running at http://localhost:${port}`);})}
}class Router {constructor(app) {const { controller } = app;console.log('Router:', controller.test());}
}
class Controller {constructor(app) {const { service } = app;console.log('controller:', service.test());}test() {return 'Controller for Router'}
}
class Service {constructor(app) {console.log('Service:', app);}test() {return 'Service for Controller'}
}module.exports = Mar
- 注意: 由于引用了分层,故在Router层尽量的不要使用Service方法.
总结
- 这一篇主要实现了一个基本骨架
- 下一篇将会实现Router层和Controller层、Controller层和Service层的具体业务实现