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 使用手册(三)
Sep 23 Javascript
javascript获取当前的时间戳的方法汇总
Jul 26 Javascript
jquery+html5烂漫爱心表白动画代码分享
Aug 24 Javascript
jquery实现表单验证简单实例演示
Nov 23 Javascript
Node.js Sequelize如何实现数据库的读写分离
Oct 23 Javascript
浅谈js数组和splice的用法
Dec 04 Javascript
AngularJS模仿Form表单提交的实现代码
Dec 08 Javascript
Javascript基础回顾之(一) 类型
Jan 31 Javascript
Node.js连接MongoDB数据库产生的问题
Feb 08 Javascript
javascript事件的传播基础实例讲解(35)
Feb 14 Javascript
微信小程序页面开发注意事项整理
May 18 Javascript
vue 自定义组件的写法与用法详解
Mar 04 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
印尼林东PWN黄金曼特宁咖啡豆:怎么冲世界上最醇厚的咖啡冲煮教程
2021/03/03 冲泡冲煮
图书管理程序(二)
2006/10/09 PHP
php设计模式 Template (模板模式)
2011/06/26 PHP
基于curl数据采集之单页面采集函数get_html的使用
2013/04/28 PHP
php数组删除元素示例
2014/03/21 PHP
php.ini中的request_order推荐设置
2015/05/10 PHP
详解PHP变量传值赋值和引用赋值变量销毁
2019/03/23 PHP
javascript常用的方法分享
2015/07/01 Javascript
jQuery学习笔记之回调函数
2016/08/15 Javascript
jquery文字填写自动高度的实现方法
2016/11/07 Javascript
react-native 封装选择弹出框示例(试用ios&amp;android)
2017/07/11 Javascript
vuejs使用$emit和$on进行组件之间的传值的示例
2017/10/04 Javascript
加载 vue 远程代码的组件实例详解
2017/11/20 Javascript
vue之浏览器存储方法封装实例
2018/03/15 Javascript
使用 Vue-TCB 快速在 Vue 应用中接入云开发的方法
2020/02/10 Javascript
[01:30]2016国际邀请赛中国区预选赛神秘商店火爆开启
2016/06/26 DOTA
flask中主动抛出异常及统一异常处理代码示例
2018/01/18 Python
python将文本分每两行一组并保存到文件
2018/03/19 Python
Python中如何使用if语句处理列表实例代码
2019/02/24 Python
Python去除字符串前后空格的几种方法
2019/03/04 Python
Python远程开发环境部署与调试过程图解
2019/12/09 Python
python剪切视频与合并视频的实现
2020/03/03 Python
Django def clean()函数对表单中的数据进行验证操作
2020/07/09 Python
pytest fixtures装饰器的使用和如何控制用例的执行顺序
2021/01/28 Python
Rakuten Kobo台湾:电子书、eReaders和Reading应用程式
2017/11/24 全球购物
伦敦香水公司:The London Perfume Company
2019/11/13 全球购物
GOLFINO英国官网:高尔夫服装
2020/04/11 全球购物
C++如何引用一个已经定义过的全局变量
2014/08/25 面试题
Python如何实现单例模式
2016/06/03 面试题
专业毕业生个性的自我评价
2013/10/03 职场文书
会计主管岗位职责
2014/01/03 职场文书
党员教师学习党的群众路线教育实践活动心得体会
2014/10/31 职场文书
采购员岗位职责范本
2015/04/07 职场文书
大学生心理健康活动总结
2015/05/08 职场文书
2015年三年级班主任工作总结
2015/05/21 职场文书
2015年小学体育教师工作总结
2015/10/23 职场文书