1.约定大于配置(convention over configuration)
- 预设默认的配置
- 根据自定的约定生成配置
- 只有特殊的需要配置
- 目的就是为了简化配置,只做少量的约定生成代码逻辑
2.egg的mvc架构
- controller:与view,model,和serive交互的控制层,可以做数据库db操作
- service:通用业务逻辑层,短信/邮箱,图片上传等方法封装,或者访问数据库
- model:数据库持久化操作
- view:视图层,一般egg只提供服务多,不做html输出
- router:通过路由统一分发不同的controller控制层。
3. 结构目录

3.自己实现架构图

- jgg统一管理程序入口总线,包括koa实例化和启动,jgg-loader 加载出来的所有模块功能
- jgg-loader实现通过文件夹遍历,加载文件夹下所有类,键值与方法映射
- 通过jgg实例$app传入 所有模块,实现数据共享
4.具体代码实现
const jgg = require("./jgg")
const app = new jgg()
app.start(3000)
const koa = require('koa')
const {initRoute,initController,initService,initConfig,initSchedule} = require('./jgg-loader')
class jgg {
constructor(conf){
this.$app = new koa(conf)
initConfig(this)
initSchedule(this)
this.$service = initService(this)
this.$ctrl = initController(this)
this.$app.use(initRoute(this).routes())
}
start(port){
this.$app.listen(port, () => {
console.log("服务器启动了,端口",port)
})
}
}
module.exports = jgg
const fs = require('fs')
const path = require('path')
const Router = require('koa-router')
function load(dir,cb) {
console.log("dir",dir)
const url = path.resolve(__dirname,dir)
const files = fs.readdirSync(url)
files.forEach( filename => {
filename = filename.replace('.js', '')
const file = require(url + '/' + filename)
cb(filename, file)
})
}
function initRoute(app) {
const router = new Router()
load("routes", (filename,fileObj) => {
console.log(filename,fileObj)
if(typeof fileObj === 'function') {
fileObj = fileObj(app)
}
let prefix = filename === 'index' ? '': "/" + filename
Object.keys(fileObj).forEach( key => {
let [method,path] = key.split(" ")
console.log(`正在映射地址 ${method.toLocaleUpperCase()} ${prefix}${path}`)
console.log("fileObj ",fileObj)
let func = fileObj[key]
router[method](prefix + path,async ctx => {
app.ctx = ctx
await func(app)
})
})
})
return router;
}
function initController(app) {
let controllers = []
load("controllers", (filename,fileObj) => {
controllers[filename] = fileObj(app)
})
return controllers;
}
function initService(app) {
let services = []
load("service", (filename,fileObj) => {
services[filename] = fileObj(app)
})
return services;
}
const schedule = require("node-schedule")
function initSchedule(app) {
load("schedule", (filename,fileObj) => {
schedule.scheduleJob(fileObj.interval, fileObj.handler);
})
}
const Sequelize = require('sequelize')
function initConfig(app) {
load('conf', (filename, conf) => {
if (conf.db) {
app.$db = new Sequelize(conf.db)
app.$model = {}
load('model', (filename, { schema, options }) => {
app.$model[filename] = app.$db.define(filename, schema, options)
})
app.$db.sync()
}
if (conf.middleware) {
conf.middleware.forEach(mid => {
const midPath = path.resolve(__dirname, 'middleware', mid)
app.$app.use(require(midPath))
})
}
})
}
module.exports = {
initRoute,initController,initService,initConfig,initSchedule
}
module.exports = (app) => ({
"get /" : app.$ctrl.home.index,
"get /detail" : app.$ctrl.home.detail,
})
module.exports = (app) => ({
"get /aaa": async app => {
const name = await app.$service.user.getName()
app.ctx.body = "xxx111用户" + name;
},
"get /info": app => {
app.ctx.body = "xxx用户年龄" + app.$service.user.getAge();
}
})
module.exports = (app) => ({
index : async app => {
app.ctx.body = await app.$model.user.findAll()
},
detail : async app => {
const name = await app.$service.user.getAge()
app.ctx.body = "con" + name;
},
})
const delay = (data, tick) => new Promise(resolve => {
setTimeout(() => {
resolve(data)
}, tick)
})
module.exports = (app) => ({
getName() {
return app.$model.user.findAll()
},
getAge() {
return 20
}
})
const { STRING } = require("sequelize");
module.exports = {
schema: {
name: STRING(30)
},
options: {
timestamps: false
}
};
module.exports = {
db: {
dialect: 'mysql',
host: '81.71.xxx.xxx',
database: 'xxxx',
username: 'root',
password: 'xxxx'
},
middleware:['logger']
}
module.exports = async (ctx, next) => {
console.log(ctx.method + " " + ctx.path);
const start = new Date();
await next();
const duration = new Date() - start;
console.log(
ctx.method + " " + ctx.path + " " + ctx.status + " " + duration + "ms"
);
};
module.exports = {
interval:'*/3 * * * * *',
handler(){
console.log('定时任务 嘿嘿 三秒执行一次'+ new Date())
}
}