你的位置:首页 > 软件开发 > Java > Nodejs学习笔记(十五)

Nodejs学习笔记(十五)

发布时间:2017-11-16 20:00:10
目录前言搭建项目及其它准备工作创建数据库创建Koa2项目安装项目其它需要包清除冗余文件并重新规划项目目录配置文件规划示例路由,并新建相关文件实现数据访问和业务逻辑相关方法编写mysql-helper.js编写数据访问方法规划业务逻辑返回值编写业务逻辑注册登录首页安全退出写在之后前 ...

目录

  • 前言
  • 搭建项目及其它准备工作
    • 创建数据库
    • 创建Koa2项目
    • 安装项目其它需要包
    • 清除冗余文件并重新规划项目目录
  • 配置文件
  • 规划示例路由,并新建相关文件
  • 实现数据访问和业务逻辑相关方法
    • 编写mysql-helper.js
    • 编写数据访问方法
    • 规划业务逻辑返回值
    • 编写业务逻辑
  • 注册
  • 登录
  • 首页
  • 安全退出
  • 写在之后

前言

  前面一有写到一篇Node.js+Express构建网站简单示例  这篇还是用以前的例子, 用Node.js+Koa2构建

 

  Koa:   https://github.com/koajs/koa

        (中文)

 

  Koa就不多介绍了,前面也写过Express,同一个团队打造,前面也过express文章,对比着看,自然可以看出些优点!

 

搭建项目及其它准备工作

创建数据库

CREATE DATABASE IF NOT EXISTS nodesample CHARACTER SET UTF8;USE nodesample;SET FOREIGN_KEY_CHECKS=0;DROP TABLE IF EXISTS `userinfo`;CREATE TABLE `userinfo` ( `Id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `UserName` varchar(64) NOT NULL COMMENT '用户名', `UserPass` varchar(64) NOT NULL COMMENT '用户密码', PRIMARY KEY (`Id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息表';

创建Koa2项目

  安装koa-generator:  https://github.com/17koa/koa-generator

npm install -g koa-generator

 安装成功后下图(版本:1.1.16)

 Nodejs学习笔记(十五)

 然后创建Koa2项目,安装相关依赖项

cd 工作目录koa2 项目名cd 项目目录 && npm install

安装项目其它需要包

1.安装使用MySQL需要的包

npm install --save mysql

 没有使用过的可以看我以前写的相关操作文章 install --save ejs

没有使用过的可以看我以前写的相关操作文章 install koa-session  https://github.com/koajs/session

npm install --save koa-session

koa-session-redis https://github.com/Chilledheart/koa-session-redis

npm install --save koa-session-redis

清除冗余文件并重新规划项目目录

 1.删除掉创建项目后自带的views和routes下的文件

 2.重新规划项目目录,规划后如下

Nodejs学习笔记(十五)

目录规则解释:

1.新增pub目录:主要为了统一存放"数据访问"、"业务逻辑"、"公共方法文件"、"数据库帮助文件"、"配置文件"等

2.新增pub目录下utils目录:主要为了统一存放类似"公共函数文件"、"返回值文件"、"枚举文件"等公共文件

3.新增pub目录下config目录:主要为了统一存放各种类型的配置文件

4.新增pub目录下db目录:主要为了统一存放各种数据库帮助类,比如:"mysql-helper.js"、"mongo-helper.js"等等

5.新增pub目录下model目录:主要为了统一存放各种数据库各表CURD操作

6.新增pub目录下bll目录:主要为了统一存放各种业务逻辑的具体实现

配置文件

 从上面的图可以看出,我在pub下新建的config目录下新建了一个config.js

 这个config.js中将编写“开发环境”和“发布环境”中所需的配置,代码如下

/** * 配置文件 *///发布配置const production = { //服务器端口 SERVER_PORT : 3000, //REDIS配置 REDIS: {  host: 'localhost',     port: 6379,  password: "abcd",  maxAge: 3600000 }, //MYSQL数据库配置 MYSQL: {  host: "localhost",  user: "root",  password: "abcd",  port: "3306",  database: "nodesample",  supportBigNumbers: true,  multipleStatements: true,  timezone: 'utc' }}//开发配置const development = { //服务器端口 SERVER_PORT : 3000, //REDIS配置 REDIS: {  host: 'localhost',     port: 6379,  password: "abcd",  maxAge: 3600000 }, //MYSQL数据库配置 MYSQL: {  host: "localhost",  user: "root",  password: "abcd",  port: "3306",  database: "nodesample",  supportBigNumbers: true,  multipleStatements: true,  timezone: 'utc' }}const config = developmentmodule.exports = config

规划示例路由,并新建相关文件

 示例中将有注册、登录功能,先规划好路由,新建routes、views下的相关需要的文件(如项目目录图中文件),并修改app.js文件

const Koa = require('koa')const app = new Koa()const views = require('koa-views')const json = require('koa-json')const onerror = require('koa-onerror')const bodyparser = require('koa-bodyparser')const logger = require('koa-logger')const config = require('./pub/config/config.js');const session = require('koa-session');const RedisStore = require('koa2-session-redis');const index = require('./routes/index')const reg = require('./routes/reg')const login = require('./routes/login')const logout = require('./routes/logout')// error handleronerror(app)// middlewaresapp.use(bodyparser({ enableTypes:['json', 'form', 'text']}))app.use(json())app.use(logger())app.use(require('koa-static')(__dirname + '/public'))app.use(views(__dirname + '/views', { extension: 'ejs'}))// loggerapp.use(async (ctx, next) => { const start = new Date() await next() const ms = new Date() - start console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)})app.keys = ['Porschev'];const redis_conf = { key: 'Porschev', maxAge: config.REDIS.maxAge, overwrite: true, httpOnly: true, rolling: false, sign: true, store: new RedisStore({ host: config.REDIS.host, port: config.REDIS.port,  password: config.REDIS.password  })};app.use(session(redis_conf, app));// routesapp.use(index.routes(), index.allowedMethods())app.use(reg.routes(), reg.allowedMethods())app.use(login.routes(), login.allowedMethods())app.use(logout.routes(), logout.allowedMethods())// error-handlingapp.on('error', (err, ctx) => { console.error('server error', err, ctx)});app.listen(config.SERVER_PORT, () => { console.log(`Starting at port ${config.SERVER_PORT}!`)});module.exports = app

注意看红色标记修改或增加的部分

实现数据访问和业务逻辑相关方法

 1.首先编写一个mysql-helper.js方便以连接池的方式进行操作

const config = require('./../config/config.js')const mysql = require("mysql")const pool = mysql.createPool(config.MYSQL) let query = function(sql, args) {  return new Promise((resolve, reject) => {  pool.getConnection(function(err, connection) {   if (err) {    resolve(err)   } else {    connection.query(sql, args, (err, result) => {       if (err) {      reject(err)     } else {      resolve(result)     }     connection.release()    })   }  }) }) }module.exports = {  query }

2.编写数据访问相关方法(model目录下的userinfo.js),如下

const mysqlHelper = require('./../db/mysql-helper.js')const userinfo = { /** * 增加一条数据 * @param {object} args 参数 * @return {object}  结果 */ async add ( args ) { let sql = 'INSERT INTO userinfo(UserName, UserPass) VALUES(?, ?)' let params = [args.username, args.userpass] let result = await mysqlHelper.query(sql, params) return result }, /** * 根据UserName得到一条数据 * @param {object} args 参数 * @return {object}  结果 */ async getByUserName( args ){ let sql = 'SELECT Id, UserName, UserPass FROM userinfo WHERE UserName = ?' let params = [args.username] let result = await mysqlHelper.query(sql, params) return result }, /** * 根据UserName得到数量 * @param {object} args 参数 * @return {object}  结果 */ async getCountByUserName( args ){ let sql = 'SELECT COUNT(1) AS UserNum FROM userinfo WHERE UserName = ?' let params = [args.username] let result = await mysqlHelper.query(sql, params) return result },}module.exports = userinfo

3.在写业务逻辑之前先规划好返回值(utils目录下retcode.js)

Nodejs学习笔记(十五)Nodejs学习笔记(十五)
/* * 返回码 */const RetCode = { SessionExpired: -1,    //session过期 Fail: 0,      //失败 Success: 1,      //成功 ArgsError: 2,     //参数错误 UserExisted: 10,    //用户已经存在 UsernameOrPasswordError: 11, //用户名或者密码错误   UserNotExist: 12,    //用户不存在 };module.exports = RetCode
retcode.js

4.编写“登录”、“注册”等业务逻辑(bll下userinfo.js)

const usermodel = require('./../model/userinfo.js')const retCode = require('./../utils/retcode.js')const userinfo = { /** * 注册 * @param {object} ctx 上下文 * @return {object}  结果 */ async register ( ctx ) { let form = ctx.request.body  const args = {  username: form.username,  userpass: form.userpass }   let result = {  code: retCode.Success,   data: null }  //验证非空 if(!args.username || !args.userpass){  result.code = retCode.ArgsError    return result } //根据用户名得到用户数量 let userNumResult = await usermodel.getCountByUserName(args) //用户名已被注册 if(userNumResult[0].UserNum > 0){  result.code = retCode.UserExisted    return result } //插入注册数据 let userResult = await usermodel.add(args) if(userResult.insertId <= 0){  result.code = retCode.Fail    return result } return result }, /** * 登录 * @param {object} ctx 上下文 * @return {object}  结果 */ async login ( ctx ) { let form = ctx.request.body  const args = {  username: form.username,  userpass: form.userpass }   let result = {  code: retCode.Success,   data: null }  //验证非空 if(!args.username || !args.userpass){  result.code = retCode.ArgsError    return result } //根据用户名得到用户信息 let userResult = await usermodel.getByUserName(args) //用户不存在 if(userResult.length == 0){  result.code = retCode.UserNotExist    return result }  //用户名或密码错误 if(userResult[0].UserName != args.username || userResult[0].UserPass != args.userpass){  result.code = retCode.UsernameOrPasswordError    return result } //将用户ID存入Session中 ctx.session = {id: userResult[0].Id} return result },}module.exports = userinfo

注册

1.views目录下reg.ejs

Nodejs学习笔记(十五)Nodejs学习笔记(十五)
<html><head><title>Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例</title></head><body><h1><%= title %></h1>登录名:<input type="text" id="txtUserName" maxlength="20" /><br/><br/>密码:<input type="password" id="txtUserPwd" maxlength="12" /><br/><br/>密码:<input type="password" id="txtUserRePwd" maxlength="12" /><br/><br/><input type="button" id="btnSub" value="注册" /></body></html><script src='/images/loading.gif' data-original="http://www.cnblogs.com//javascripts/jquery-1.11.2.min.js" type="text/javascript"></script><script src='/images/loading.gif' data-original="http://www.cnblogs.com//javascripts/md5.js" type="text/javascript"></script><script type="text/javascript">  $(function(){  $('#btnSub').on('click', function(){   var $txtUserName = $('#txtUserName'),    txtUserNameVal = $.trim($txtUserName.val()),    $txtUserPwd = $('#txtUserPwd'),    txtUserPwdVal = $.trim($txtUserPwd.val()),    $txtUserRePwd = $('#txtUserRePwd'),    txtUserRePwdVal = $.trim($txtUserRePwd.val());         if(txtUserNameVal.length == 0){    alert('用户名不能为空');        return false;   }   if(txtUserPwdVal.length == 0){        alert('密码不能为空');        return false;   }   if(txtUserRePwdVal.length == 0){    alert('重复密码不能为空');     return false;   }   if(txtUserPwdVal != txtUserRePwdVal){         alert('两次密码不一致');         return false;   }   $.ajax({    url: '/reg',    type: 'POST',    dataType: 'json',    data: {     username: txtUserNameVal,          userpass: hex_md5(txtUserPwdVal)              },    beforeSend: function (xhr) {},    success: function (res) {     if (res != null && res.code) {      var retVal = parseInt(res.code);      switch (retVal) {       case 2:        alert('输入有误');        break;       case 0:        alert('注册失败');        break;       case 1:        alert('注册成功!');        location.href = '/login'                break;       case 10:        alert('用户已注册');        break;             }     }     else {      alert('操作失败');     }    },    complete: function (function ('操作失败');    }   });     }) });</script>
reg.ejs

2.routes目录下reg.js

const router = require('koa-router')()const userBll = require('./../pub/bll/userinfo.js')const title = '注册'router.prefix('/reg')router.get('/', async (ctx, next) => { await ctx.render('reg', { title })})router.post('/', async (ctx, next) => { let result = await userBll.register(ctx) ctx.body = result;})module.exports = router

登录

 1.views目录下login.ejs

Nodejs学习笔记(十五)Nodejs学习笔记(十五)
<html><head><title>Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例</title></head><body><h1><%= title %></h1>登录名:<input type="text" id="txtUserName" maxlength="20" /><br/><br/>密码:<input type="password" id="txtUserPwd" maxlength="12" /><br/><br/><input type="button" id="btnSub" value="登录" /></body></html><script src='/images/loading.gif' data-original="http://www.cnblogs.com//javascripts/jquery-1.11.2.min.js" type="text/javascript"></script><script src='/images/loading.gif' data-original="http://www.cnblogs.com//javascripts/md5.js" type="text/javascript"></script><script type="text/javascript">  $(function(){  $('#btnSub').on('click', function(){   var $txtUserName = $('#txtUserName'),    txtUserNameVal = $.trim($txtUserName.val()),    $txtUserPwd = $('#txtUserPwd'),    txtUserPwdVal = $.trim($txtUserPwd.val());         if(txtUserNameVal.length == 0){    alert('用户名不能为空');        return false;   }   if(txtUserPwdVal.length == 0){        alert('密码不能为空');        return false;   }      $.ajax({    url: '/login',    type: 'POST',    dataType: 'json',    data: {     username: txtUserNameVal,          userpass: hex_md5(txtUserPwdVal)              },    beforeSend: function (xhr) {},    success: function (res) {     if (res != null && res.code) {      var retVal = parseInt(res.code);      switch (retVal) {       case 2:        alert('输入有误');        break;       case 0:        alert('登录失败');        break;       case 1:        alert('登录成功!');        location.href = '/'                break;       case 11:        alert('用户名或者密码错误');        break;       case 12:        alert('用户不存在');        break;      }     }     else {      alert('操作失败');     }    },    complete: function (function ('操作失败');    }   });     }) });</script>
login.ejs

 2.routes目录下login.js

const router = require('koa-router')()const userBll = require('./../pub/bll/userinfo.js')const title = '登录'router.prefix('/login')router.get('/', async (ctx, next) => { await ctx.render('login', { title })})router.post('/', async (ctx, next) => {  let result = await userBll.login(ctx); ctx.body = result; })module.exports = router

首页

 1.views目录下index.ejs

Nodejs学习笔记(十五)Nodejs学习笔记(十五)
<html><head><title>Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例</title></head><body><h1><%= title %></h1><% if(id != null) {%> <h3>登录用户ID:<%= id %> <a id="btnLogOut" href="javascript:void(0);">安全退出</a></h3><% } %></body></html><script src='/images/loading.gif' data-original="http://www.cnblogs.com//javascripts/jquery-1.11.2.min.js" type="text/javascript"></script><script type="text/javascript">  $(function(){  $('#btnLogOut').on('click', function(){      if(!confirm('确认要退出吗?')){    return;   }   $.ajax({    url: '/logout',    type: 'POST',    dataType: 'json',    data: {},    beforeSend: function (xhr) {},    success: function (res) {     if (res != null && res.code) {      var retVal = parseInt(res.code);      switch (retVal) {              case 0:        alert('失败');        break;       case 1:        alert('成功!');        location.href = '/login'                break;             }     }     else {      alert('操作失败');     }    },    complete: function (function ('操作失败');    }   });     }) });</script>
index.ejs

 2.routes目录下index.js

const router = require('koa-router')()const title = '首页'router.get('/', async (ctx, next) => { //判断登录 if(!ctx.session || !ctx.session.id){ await ctx.redirect('/login') }else{  const id = ctx.session.id; await ctx.render('index', { title, id }) } })module.exports = router

 index.js文件中实现如果不存在session则跳回登录页

安全退出

 1.routes目录下logout.js

const router = require('koa-router')()const retCode = require('./../pub/utils/retcode.js')router.prefix('/logout')router.get('/', async (ctx, next) => { await ctx.render('logout', {})})router.post('/', async (ctx, next) => { ctx.session = null; let result = { code: retCode.Success,  data: null } ctx.body = result; })module.exports = router

写在之后

   没有去说一些细节API,写这篇主要可以对比 Nodejs学习笔记(七)--- Node.js + Express 构建网站简单示例 来看,完全是一亲的示例,只是这次用的Koa2,方便大家看看Koa2和express写出来的不同

   总的来说Koa2还是比较好上手,async、await这个对于有C#语言基础的来说也比较亲切,不用二次理解

   可以对比一下express时的各种嵌套回调写法,Koa2写好更优雅、更易阅读

 示例有限,其它操作通过官网查找API或github找一些组件来动手试,比如最常用的一些功能:操作cookies、上传文件、session存储到其它介质等

 

 参考资料: https://koa.bootcss.com/

 

 老规划不放源码,虽然是示例结构,但是尽量按照平常做项目的想法去实现的,有兴趣的动手去搭项目做才会理解一些思路,代码都放在文章中了,有问题留言^_^!

原标题:Nodejs学习笔记(十五)

关键词:JS

JS
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。