node使用Koa2搭建web项目的方法


Posted in Javascript onOctober 17, 2017

随着Node.js的日益火热,各种框架开始层出不穷的涌现出来,Node.js也开始逐渐的被应用到处理服务端请求的场景中。搭建Web项目的框架也随之开始出现——express、koa、koa2、egg等,当然要了解其好坏还是要自己去啃源码的。本文将不会涉及到源码,只是带领初学者简单了解下Koa2的基本使用,欢迎大家在评论中互相交流学习。

注意:koa2使用了ES7的语法,所以使用时请升级Node版本到最新。了解更详细的源码信息可以到git上的koajs/koa去了解

1. 项目目录结构

node使用Koa2搭建web项目的方法

2. 代码逻辑解析

2.1. 包结构文件

[package.json]

{
 "name": "weixin-node-koa",
 "version": "1.0.0",
 "description": "node.js with koa2",
 "private": true,
 "dependencies": {
  "koa": "^2.0.0",
  "koa-router": "^7.0.0",
  "mysql":"2.13.0"
 },
 "scripts": {
  "start": "node app.js"
 },
 "engines": {
  "node": ">=6.0.0"
 },
 "author": "Fly",
 "license": "CENTERM"
}

2.2. 启动入口文件

[app.js]

const Koa = require('koa');
const app = new Koa();
const router2controller = require('./app/router2controller.js');
const config = require('./config/config.local.js');

app.use(router2controller());
app.listen(config.port);
console.log("Server started and listen on port " + config.port);

如果请求的报文体是XML格式,可以添加下面的代码自动解析报文(注意引用koa-xxx的版本要与koa2对应)

const Koa = require('koa');
const app = new Koa();
const router2controller = require('./app/router2controller.js');
const config = require('./config/config.local.js');

//start接收到的xml数据请求单独解析存储
const xmlParser = require('koa-xml-body');
app.use(xmlParser()).use((ctx,next) => {
  ctx.data = ctx.request.body;
  return next();
});
//end

app.use(router2controller());
app.listen(config.port);
console.log("Server started and listen on port " + config.port);

从代码看到引入了一个router2controller.js的文件,这个文件是完成前端请求到具体处理方法的路由过程

2.3. 路由器文件

[router2controller.js]

该类将会自动扫描controller文件夹中的文件来加载请求映射,不需要挨个请求单独配置

koa-router原生提供方法如下:

router
 .get('/', async (ctx,next) => {
  this.body = 'Hello World!';
 })
 .post('/users', async (ctx,next) => {
  //TODO
 })
 .put('/users/:id', async (ctx,next) => {
  //TODO
 })
 .del('/users/:id', async (ctx,next) => {
  //TODO
 });

自动扫描controller包实现方法如下

const fs = require('fs');
const router = require('koa-router')();

function addMapping(router, mapping) {
  for (var url in mapping) {
    if (url.startsWith('GET ')) {
      var path = url.substring(4);
      router.get(path, mapping[url]);
      console.log(`register URL mapping: GET ${path}`);
    } else if (url.startsWith('POST ')) {
      var path = url.substring(5);
      router.post(path, mapping[url]);
      console.log(`register URL mapping: POST ${path}`);
    } else if (url.startsWith('PUT ')) {
      var path = url.substring(4);
      router.put(path, mapping[url]);
      console.log(`register URL mapping: PUT ${path}`);
    } else if (url.startsWith('DELETE ')) {
      var path = url.substring(7);
      router.del(path, mapping[url]);
      console.log(`register URL mapping: DELETE ${path}`);
    } else {
      console.log(`invalid URL: ${url}`);
    }
  }
}

function addControllers(router, dir) {
  fs.readdirSync(__dirname + '/' + dir).filter((f) => {
    return f.endsWith('.js');
  }).forEach((f) => {
    console.log(`process controller: ${f}...`);
    let mapping = require(__dirname + '/' + dir + '/' + f);
    addMapping(router, mapping);
  });
}

module.exports = function (dir) {
  var controllersDir = dir || 'controller';
  addControllers(router, controllersDir);
  return router.routes();
};

2.4. 控制器

[userController.js]

***Controller.js是用来处理具体请求信息以及返回数据的,userController.js中处理了GET请求获取用户信息,POST请求保存用户信息

const userService = require('./../service/userService.js');

var getUserinfo = (ctx, next) => {
  let query = ctx.query;
  let userId = query.id;
  let userInfo = userService.getUserById(userId);

  let html = '<html><body>'
    + '<div> userinfo: ' + userInfo + '</div>'
    + '</body></html>';
  ctx.response.type ='text/html';
  ctx.response.body = html;
};

var saveUserinfo = (ctx, next) => {
  const requestString = ctx.data;
  //TODO数据处理
  Console.log(requestString);
};

module.exports = {
  'GET /getUserinfo': getUserinfo,
  'POST /saveUserinfo': saveUserinfo
};

2.5. 数据处理

[userService.js]

处理封装从***Dao.js获取到的数据返回给Controller

const userDao = require('./../dao/userDao.js');

var getUserById = async (userId) => {
  var users = userDao.getUserById(userId);
  var responseContent = '';
  for(let user of users) {
    reaponseContent += '姓名:' + user.name + ' |';
    reaponseContent += '年龄:' + user.age + ' |';
    reaponseContent += '身高:' + user.height + '<br />';
  }
  return responseContent;
}

module.exports = {
  getUserById : getUserById
};

2.6. 数据获取

[userDao.js]

通过请求传入参数来获取user数据

const mysql = require('./../utils/mysqlUtil.js');

var getUserById = async (userId) => {
  let mysqlOptions = {
    sql : 'select * from table_user where user_id = ?',
    args : [userId]
  };

  var users = await mysql.execQuery(mysqlOptions);
  if(users.length == 0) {
    return null;
  } else {
    return users;
  }
};

module.exports = {
  getUserById : getUserById
};

2.7. 数据库操作

[mysqlUtil.js]

包含了数据库连接池控制,连接建立、释放管理,执行Dao发起的数据库操作请求

const mysql = require('mysql');
const config = require('./../../config/config.local.js');

var connectionPool = mysql.createPool({
  'host' : config.database.host,
  'port':config.database.port,
  'user' : config.database.user,
  'password' : config.database.password,
  'database' : config.database.database,
  'charset': config.database.charset,
  'connectionLimit': config.database.connectionLimit,
  'supportBigNumbers': true,
  'bigNumberStrings': true
});

var release = connection => {
  connection.end(function(error) {
    if(error) {
      console.log('Connection closed failed.');
    } else {
      console.log('Connection closed succeeded.');
    }
  });
};

var execQuery = sqlOptions => {
  var results = new Promise((resolve, reject) => {
      connectionPool.getConnection((error,connection) => {
      if(error) {
        console.log("Get connection from mysql pool failed !");
        throw error;
      }

      var sql = sqlOptions['sql'];
      var args = sqlOptions['args'];

      if(!args) {
        var query = connection.query(sql, (error, results) => {
          if(error) {
            console.log('Execute query error !');
            throw error;
          }

          resolve(results);
        });
      } else {
        var query = connection.query(sql, args, function(error, results) {
          if(error) {
            console.log('Execute query error !');
            throw error;
          }

          resolve(results);
        });
      }

      connection.release(function(error) {
        if(error) {
          console.log('Mysql connection close failed !');
          throw error;
        }
      });
    });
  }).then(function (chunk) {
    return chunk;
  });

  return results;
};

module.exports = {
  release : release,
  execQuery : execQuery
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
基于jquery的让textarea自适应高度的插件
Aug 03 Javascript
ie与ff下的event事件使用介绍
Nov 25 Javascript
JS实现简洁、全兼容的拖动层实例
May 13 Javascript
Bootstrap中的表单验证插件bootstrapValidator使用方法整理(推荐)
Jun 21 Javascript
原生js仿jquery animate动画效果
Jul 13 Javascript
jQuery实现为LI列表前3行设置样式的方法【2种方法】
Sep 04 Javascript
Javascript中判断一个值是否为undefined的方法详解
Sep 28 Javascript
原生js实现淘宝购物车功能
Jun 23 Javascript
微信小程序switch开关选择器使用详解
Jan 31 Javascript
iview table render集成switch开关的实例
Mar 14 Javascript
koa源码中promise的解读
Nov 13 Javascript
vue项目中axios请求网络接口封装的示例代码
Dec 18 Javascript
Node 自动化部署的方法
Oct 17 #Javascript
利用JS实现scroll自定义滚动效果详解
Oct 17 #Javascript
jquery实现图片跟随鼠标的实例
Oct 17 #jQuery
vue获取input输入值的问题解决办法
Oct 17 #Javascript
node.js 用socket实现聊天的示例代码
Oct 17 #Javascript
Bootstrap图片轮播效果详解
Oct 17 #Javascript
vue组件之Alert的实现代码
Oct 17 #Javascript
You might like
全国FM电台频率大全 - 16 河南省
2020/03/11 无线电
php selectradio和checkbox默认选择的实现方法详解
2013/06/29 PHP
PHP-FPM运行状态的实时查看及监控详解
2016/11/18 PHP
Yii2框架实现利用mpdf创建pdf文件功能示例
2019/02/08 PHP
JS效率个人经验谈(8-15更新),加入range技巧
2007/01/09 Javascript
js判断是否为ie的方法小结
2014/01/13 Javascript
SeaJS入门教程系列之完整示例(三)
2014/03/03 Javascript
js四舍五入数学函数round使用实例
2014/05/09 Javascript
JS完整获取IE浏览器信息包括类型、版本、语言等等
2014/05/22 Javascript
对new functionName()定义一个函数的理解
2014/05/22 Javascript
nodejs文件操作模块FS(File System)常用函数简明总结
2014/06/05 NodeJs
jQuery实例—选项卡的简单实现(js源码和jQuery)
2016/06/14 Javascript
url中的特殊符号有什么含义(推荐)
2016/06/17 Javascript
利用浮层使select不可选的实现方法
2016/12/03 Javascript
Bootstrap3下拉菜单的实现
2017/02/22 Javascript
微信小程序开发之数据存储 参数传递 数据缓存
2017/04/13 Javascript
微信小程序实时聊天WebSocket
2018/07/05 Javascript
函数式编程入门实践(一)
2019/04/20 Javascript
JavaScript跳出循环的三种方法(break, return, continue)
2019/07/30 Javascript
使用uni-app开发微信小程序的实现
2019/12/13 Javascript
vue项目配置同一局域网可使用ip访问的操作
2020/10/23 Javascript
[02:43]中国五虎出征TI3视频
2013/08/02 DOTA
[40:31]Secret vs Alliacne 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
Python采用socket模拟TCP通讯的实现方法
2014/11/19 Python
python中的装饰器详解
2015/04/13 Python
在Python的Django框架上部署ORM库的教程
2015/04/20 Python
浅谈Python peewee 使用经验
2017/10/20 Python
通过实例解析Python return运行原理
2020/03/04 Python
Django获取model中的字段名和字段的verbose_name方式
2020/05/19 Python
KIKO美国官网:意大利的平价彩妆品牌
2017/05/16 全球购物
Made in Design意大利:现代家具、名家灯具和装饰
2020/10/27 全球购物
追悼会主持词
2014/03/20 职场文书
关于安全演讲稿
2014/05/09 职场文书
供应链金融服务方案
2014/05/25 职场文书
民政局副局长民主生活会个人整改措施
2014/10/04 职场文书
Go语言中break label与goto label的区别
2021/04/28 Golang