使用Sequelize操作MySQL
Sequelize是Node.js v4及更高版本的基于promise的ORM。它支持方言PostgreSQL,MySQL,SQLite和MSSQL,并具有坚实的事务支持,关系,读取复制等等。Egg官方也有egg-sequelize的插件,所以这里使用它来进行代码中所有SQL操作.
添加并开启sequelize插件:
// {workdir}/config/plugin.js
// 挂在到app下,通过app.sequelize使用
exports.sessionRedis = {
enable: true,
package: "egg-sequelize"
};
启动前创建表:
// {workdir}/app.js
module.exports = app => {
app.beforeStart(async function () {
await app.model.sync({ force: false }); // false 为不覆盖 true会删除再创建
});
};
添加model文件:
// {workdir}/app/model/user.js 一定要使用此目录
// 挂在到ctx下通过 ctx.model.User.fn()使用
module.exports = app => {
const { STRING, INTEGER, DATE, BIGINT } = app.Sequelize;
const User = app.model.define("user", {
login: STRING,
id: {
type: BIGINT(11),
autoIncrement:true,
primaryKey : true,
unique : true
},
role: {
type: INTEGER,
default: 0
},
name: STRING(30),
passwd: STRING(32),
age: INTEGER,
last_sign_in_at: DATE,
created_at: DATE,
updated_at: DATE
});
return User;
};
存在问题 添加外键没有解决
文档中可以通过app.createAnonymousContext()
创建一个匿名ctx,但这里报错,所以无法获取其它model,这里设置外键需要
sequelize常用API:
Model.findOne({ where: {filed: 'value'} }).then(...) // query
Model.create({ filed1: 'value', filed2: 'value' }).then(...) // create
Model.destroy() // delete
// ...
官方文档地址: http://docs.sequelizejs.com
中文API
session和redis配置
Egg已经内置了Seesion插件,通过ctx.session
可以直接使用,
可以将session自定义外部存储,实现如下
// {workdir}/app.js
module.exports = app => {
app.sessionStore = {
* get (key) {
// return value;
},
* set (key, value, maxAge) {
// set key to store
},
* destroy (key) {
// destroy key
},
};
};
但这里使用了egg-redis
和egg-session-redis
两个插件来将session存储到redis中.
启用插件:
// {workdir}/config/plugin.js
exports.sessionRedis = {
enable: true,
package: "egg-session-redis"
};
exports.redis = {
enable: true,
package: "egg-redis"
};
插件配置:
// {workdir}/config/config.default.js
const database = "egg";
const redisHost = "192.168.189.130";
const dbHost = "localhost";
module.exports = appInfo => {
const config = {};
config.redis = { // 单个redis
client: {
port: 6379, // Redis port
host: redisHost, // Redis host
password: "",
db: 0
}
};
config.sessionRedis = {
key: "EGG_SESSION",
maxAge: 24 * 3600 * 1000, // 1 天
httpOnly: true,
encrypt: false
};
return config;
};
session使用实例:
// {workdir}/app/controller/auth.js
...
async login(ctx) {
ctx.validate(userRule);
const user = await ctx.service.auth.login(ctx.request.body);
ctx.assert(user, "用户名或密码错误");
const token = await app.genToken(user.id, ctx.request.ip);
ctx.session.user = user.id;
ctx.session.token = token.id;
ctx.status = 204;
}
...
token实现
token主要用来记录一些用户登录的信息,存储在db中.
首先定义token的model:
// {workdir}/app/model/token.js
module.exports = app => {
const { STRING, DATE, BIGINT, BOOLEAN } = app.Sequelize;
const Token = app.model.define("token", {
id: {
type: BIGINT(11),
autoIncrement:true,
primaryKey : true,
unique : true
},
user: BIGINT(11),
expire: DATE,
ip: STRING,
valid: BOOLEAN
});
return Token;
};
token DB 操作的service层代码:
// {workdir}/app/service/token.js
const moment = require("moment");
module.exports = app => {
class Token extends app.Service {
async fetchOne (id) {
const token = await this.ctx.model.Token.find({
where: { id: id }
});
return token;
}
async genToken (userId, ip) {
const expire = new Date(moment().add(1, "days"));
const token = await this.model.Token.create({ expire, ip, user: userId, valid: true });
return token;
};
}
return Token;
};
登录后session中记录token的id ....
在中间件中添加token验证 ....