6

使用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-redisegg-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验证 ....


Leo_
669 声望22 粉丝

learning...