Node实践总结4——数据库操作

数据库操作

web应用后台终究还是要和数据库打交道,不然只是一堆写死在html里的东西。
我在工程中使用了bookshelf和knex两个框架分别作为ORM和Query Builder,之前也已经写过两篇博客bookshelf.js笔记、knex.js笔记来介绍具体的语法,就不再赘述,这里就讲讲具体到实践中我是怎么用的。


knex配置

和JDBC类似,使用knex之前,需要将数据库的ip、端口、数据库名、登录账号和口令等基本信息配置到工程中,可以通过单独写配置文件将具体的保密信息隐藏,上传的时候设置好gitignore文件,不上传config即可:

const config = require('./config');
const knex = require('knex')({
    client: 'pg',
    connection: {
        host: config.host,
        user: config.username,
        password : config.password,
        database : config.database,
        port: config.port
    }
});

更科学的方法是,设置多个数据库配置文件,将生产、测试、开发的场景都区分开,根据运行模式动态选择要连接哪一个数据库。


使用bookshelf

const bookshelf = require('bookshelf')(knex);
const Users = bookshelf.Model.extend({
    tableName: 'users'
});
const WafLogs = bookshelf.Model.extend({
    tableName: 'waf_logs'
});

将knex作为参数用于创建bookshelf实例,tablename用于指定该数据对象对应的数据表。


操作数据库

配置好ORM和Query Builder之后,就可以开始进行数据库操作了。
以用户注册的业务为例,来讲一下:
先上代码:

router.post('/reg', async function (ctx, next) {
  if(ctx.request.body['username'].length > 25) {
    //判断用户名是否过长,数据库设置username字段为varchar(25)
    await ctx.render('reg', {
      title: 'OA-注册',
      error: '用户名不得超过25个字符'
    });
  } else if(ctx.request.body['password2'] !== ctx.request.body['password']) {
    //判断两次密码是否一致
    console.log('两次密码不一致');
    await ctx.render('reg', {
      title: 'OA-注册',
      error: '两次密码不一致'
    });
  } else {
    //判断用户名是否存在
    var count = await Users.where('username', ctx.request.body['username']).count('username');
    if(count != 0) {
      console.log('用户名已存在!');
      await ctx.render('reg', {
        title: 'OA-注册',
        error: '用户名已存在'
      });
    } else {
      var hmac = crypto.createHmac('sha256', 'liuyueyi');
      var password = hmac.update(ctx.request.body['password']).digest('hex');
      var newUser = new Users({
        username: ctx.request.body['username'],
        password: password
      });
      await newUser.save();
      console.log('注册成功,可以直接登录!');
      ctx.session.user = newUser;
      await ctx.render('reg', {
        title: 'OA-注册',
        success: '注册成功,可以直接登录'
      });
      return ctx.redirect('/login');
    }
  }
});

当reg页面的表单被POST上来之后,
1、通过ctx取出请求包中表单的username值,判断其长度是否超过数据库字段的限制,是的话,就重绘该页面,并传入error字段,写明错误的原因;
2、通过类似的方法判断两次输入的密码是否一致;
3、查询数据库,看是否已经存在该用户名,

var count = await Users.where('username', ctx.request.body['username']).count('username');

4、如果满足注册条件,则将数据组装成一个新的User对象,调用save()存入数据库。

至此基本就把简单的数据库selectinsert操作讲完了,由于其他操作我目前的代码还没有涉及到,以后写到了再补充进来。


session存储

由于http是无状态协议,为了让用户的访问操作连贯,就加入了cookie和session的机制,我是用了mongoDB作为session存储的载体,koa有比较成熟的解决方案。

const session = require('koa-session-store');
const mongoStore = require('koa-session-mongo');
app.use(convert(session({
  store: mongoStore.create({
    db: 'oa-session'
  })
})));

这样,就算建立好了整个session存储的环境,其中关于mongodb的配置都直接写在了koa-mongo-session包的index.js源码里,

/**
 * Default options
 */

var defaultOptions = {
  host: '127.0.0.1',
  port: 27017,
  collection: 'sessions',
  auto_reconnect: false,
  ssl: false,
  expirationTime: 60 * 60 * 24 * 14,    // 2 weeks
  w: 1
};

如果需要个性化配置,直接在require('koa-session-mongo')的时候在后面跟上参数即可。

配置好之后,通过ctx.session即可访问或赋值。
比如登陆成功之后,ctx.session.user = username
登出之后,ctx.session.user = null

你可能感兴趣的:(Node.js)