环境准备
操作系统:支持 macOS,Linux,Windows
运行环境:建议选择 LTS 版本,最低要求 8.x。
快速初始化
脚手架生成命令
$ mkdir egg-example && cd egg-example
$ npm init egg --type=simple
$ npm i
启动项目:
$ npm run dev
$ open http://localhost:7001
目录结构
egg-project ├── package.json ├── app.js (可选) ├── agent.js (可选) ├── app | ├── router.js │ ├── controller │ | └── home.js │ ├── service (可选) │ | └── user.js │ ├── middleware (可选) │ | └── response_time.js │ ├── schedule (可选) │ | └── my_task.js │ ├── public (可选) │ | └── reset.css │ ├── view (可选) │ | └── home.tpl │ └── extend (可选) │ ├── helper.js (可选) │ ├── request.js (可选) │ ├── response.js (可选) │ ├── context.js (可选) │ ├── application.js (可选) │ └── agent.js (可选) ├── config | ├── plugin.js | ├── config.default.js │ ├── config.prod.js | ├── config.test.js (可选) | ├── config.local.js (可选) | └── config.unittest.js (可选) └── test ├── middleware | └── response_time.test.js └── controller └── home.test.js
如上,由框架约定的目录:
app/router.js
用于配置 URL 路由规则,具体参见 Router。
app/controller/**
用于解析用户的输入,处理后返回相应的结果,具体参见 Controller。
app/service/**
用于编写业务逻辑层,可选,建议使用,具体参见 Service。
app/middleware/**
用于编写中间件,可选,具体参见 Middleware。
app/public/**
用于放置静态资源,可选,具体参见 内置插件。
app/extend/**
用于框架的扩展,可选,具体参见 框架扩展。
config/config.{env}.js
用于编写配置文件,具体参见,具体参见 配置。
config/plugin.js
用于配置需要加载的插件,具体参见 插件。
test/**
用于单元测试,具体参见 单元测试。
app.js 和 agent.js
用于自定义启动时的初始化工作,可选,具体参见 启动自定义。
由内置插件约定的目录:
app/public/**
用于放置静态资源,可选,具体参见egg-static自定义。
app/schedule/**
用于定时任务,可选,具体参见定时任务。
若需自定义自己的目录规范,参见 Loader API。
app/view/**
用于放置模板文件,可选,由模板插件约定,具体参见模板渲染。
app/model/**
用于放置领域模型,可选,由领域类相关插件约定,如 egg-sequelize。
数据源配置
Mysql配置
mysql orm框架选用sequelize,egg已经提供集成插件egg-sequelize,安装插件
$ npm install --save egg-sequelize mysql2
在 config/plugin.js 中引入 egg-sequelize 插件
exports.sequelize = {
enable: true,
package: 'egg-sequelize',
};
在 config/config.default.js 中编写 sequelize 配置
config.sequelize = {
// 数据库类型
dialect: 'mysql',
// 数据库名
database: 'yinghe-ogg',
// 数据库IP和端口
host: '127.0.0.1',
port: '3306',
// 数据库连接的用户和密码
username: 'root',
password: 'password',
// 是否自动进行下划线转换(这里是因为DB默认的命名规则是下划线方式,而我们使用的大多数是驼峰方式)
// underscored: true,
// 时区,sequelize有很多自动时间的方法,都是和时区相关的,记得设置成东8区(+08:00)
timezone: '+08:00',
// 数据库Model存放目录
baseDir: 'model/mysql',
pool: {
max: 5,
min: 0,
idle: 10000, // 超时时间
}
};
Mysql Model文件定义,以token表为例,放在model/mysql目录
module.exports = app => {
const {DATE, INTEGER, STRING} = app.Sequelize;
const access_token = app.model.define('access_token', {
id: {
type: INTEGER, //授权ID
primaryKey: true, // 主键
allowNull: false, // 不为null
autoIncrement: true // 自增
},
access_token: {
type: STRING(50) // 字符串类型长度50
},
expires_in: {
type: DATE //超时时间
},
scope: {
type: STRING(20)
},
status: {
comment: '数据状态 1启用;2停用', // 数据库生成注释
type: INTEGER(4),
defaultValue: 1 // 默认值
}
},
{
freezeTableName: true
});
// 表之间关联关系
access_token.associate = () => {
access_token.belongsTo(app.model.Users, {foreignKey: 'user_id', as: 'user'});
access_token.belongsTo(app.model.Client, {foreignKey: 'client_id', as: 'client'});
};
return access_token;
};
MongoDB配置
安装插件
$ npm install --save egg-mongoose
在 config/plugin.js 中引入 egg-mongoose 插件
exports.mongoose = {
enable: true,
package: 'egg-mongoose',
};
在 config/config.default.js 添加如下配置
mongoose: {
baseDir: 'model/mongo',
loadModel: false,
url:'utl',options: {poolSize: 5, useNewUrlParser: true}
}
egg默认读取model文件下数据库映射对象,由于mysql和mongodb默认文件夹都是model,所以如果项目需要同时用到这两种数据库,需要修改默认读取目录,在配置数据源添加baseDir属性来改变,如果只用到单数据源,egg默认会读取model目录也没有必要创建mysql和mongo目录来区分
Mongodb Model文件定义
module.exports = app => {
const mongoose = app.mongoose;
const Schema = mongoose.Schema;
const modelname= new Schema({
title: {type: String, default: ''},
obj: {},//对象类型
createdAt: {type: Date},
updatedAt: {type: Date},
remark: {type: String, default: ''}
}, {collection: 'modelname', toObject: {virtuals: true}, toJSON: {virtuals: true}});
return mongoose.model('modelname', modelname);
};
Redis配置
安装插件
$ npm install --save egg-redis
在 config/plugin.js 中引入 egg-mongoose 插件
exports.redis = {
enable: true,
package: 'egg-redis',
};
在 config/config.default.js 添加如下配置,这里为多redis链接配置示例
redis: {
clients: {
client: {
port: 6379, // Redis port
host: '127.0.0.1', // Redis host
password: 'password',
db: 3 // 数据库
},
// 用于发布订阅
client_pub: {
port: 6379, // Redis port
host: '127.0.0.1', // Redis host
password: 'password',
db: 3
}
}
}
配置启动自定义
在根目录创建app.js
const path = require('path');
// app.js
class AppBootHook {
constructor(app) {
this.app = app;
}
// 配置文件即将加载,这是最后动态修改配置的时机
async configWillLoad() {}
// 配置文件加载完成
async configDidLoad() {}
//文件加载完成
async didLoad() {
// 加载mongo模型,由于默认加载model文件夹下默认文件,由于mysql和mongo需要区分所以单独加载
const dir = path.join(this.app.config.baseDir, 'app/model/mongo');
const pro = this.app.mongoose.Model;
this.app.loader.loadToApp(dir, 'mongo', {
inject: this.app,
caseStyle: 'upper',
filter(model) {
return typeof model === 'function' && model.prototype instanceof pro;
},
});
console.log("文件加载完成")
}
// 插件启动完毕
async willReady() {
const { model } = this.app;
// 初始化数据库
model.sync({ force: false });
console.log("插件启动完毕")
}
// 应用启动完成
async didReady() {}
// worker 准备就绪
async serverDidReady() {}
// 应用即将关闭
async beforeClose() {}
}
module.exports = AppBootHook;
用法
Mysql 用法:
this.ctx.app.model.User
,User为model/mysql下User数据库映射文件,与sequelize用法一致
MongoDB 用法:this.ctx.app.mongo.modelname
,为区分model对象取值,“mongo”为上面app.js中定义的别名
Redis 用法:this.ctx.app.redis.get("client")
,由于本示例配置了两个redis链接,需要根据每个链接别名获取