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 相关文章推荐
JavaScript高级程序设计阅读笔记(六) ECMAScript中的运算符(二)
Feb 27 Javascript
简单的jquery左侧导航栏和页面选中效果
Aug 21 Javascript
jQuery实现滑动页面固定顶部显示(可根据显示位置消失与替换)
Oct 28 Javascript
Bootstrap源码解读导航条(7)
Dec 23 Javascript
Node.js使用Express创建Web项目详细教程
Mar 31 Javascript
微信小程序中做用户登录与登录态维护的实现详解
May 17 Javascript
electron中使用bootstrap的示例代码
Nov 06 Javascript
layui使用form表单实现post请求页面跳转的方法
Sep 14 Javascript
Vue脚手架编写试卷页面功能
Mar 17 Javascript
JavaScript判断数据类型有几种方法及区别介绍
Sep 02 Javascript
js仿淘宝放大镜效果
Dec 28 Javascript
vue实现倒计时功能
Mar 24 Vue.js
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
MYSQL数据库初学者使用指南
2006/11/16 PHP
PHP 模板高级篇总结
2006/12/21 PHP
laravel框架的安装与路由实例分析
2019/10/11 PHP
js不是基础的基础
2006/12/24 Javascript
加载jQuery后$冲突的解决办法
2010/07/09 Javascript
JavaScript(JS) 压缩 / 混淆 / 格式化 批处理工具
2010/12/10 Javascript
父子窗体间传递JSON格式的数据的代码
2010/12/25 Javascript
最短的IE判断代码
2011/03/13 Javascript
seajs1.3.0源码解析之module依赖有序加载
2012/11/07 Javascript
javascript制作loading动画效果 loading效果
2014/01/14 Javascript
按钮接受回车事件的三种实现方法
2014/06/06 Javascript
node.js中的querystring.escape方法使用说明
2014/12/10 Javascript
javascript实现类似百度分享功能的方法
2015/07/27 Javascript
JS如何判断浏览器类型和详细区分IE各版本浏览器
2017/03/04 Javascript
7个好用的JavaScript技巧分享(译)
2019/05/07 Javascript
Vue防止白屏添加首屏动画的实例
2019/10/31 Javascript
vue 实现在同一界面实现组件的动态添加和删除功能
2020/06/16 Javascript
基于PHP pthreads实现多线程代码实例
2020/06/24 Javascript
vuejs实现下拉框菜单选择
2020/10/23 Javascript
[01:56]无止竞 再出发——中国军团出征2017年DOTA2国际邀请赛
2017/07/05 DOTA
[52:06]完美世界DOTA2联赛决赛日 Inki vs LBZS 第一场 11.08
2020/11/10 DOTA
Python中的FTP通信模块ftplib的用法整理
2016/07/08 Python
Python内置模块turtle绘图详解
2017/12/09 Python
深入理解Python爬虫代理池服务
2018/02/28 Python
详解如何为eclipse安装合适版本的python插件pydev
2018/11/04 Python
python语言基本语句用法总结
2019/06/11 Python
k-means 聚类算法与Python实现代码
2020/06/01 Python
css3实现针线缝合效果(图解步骤)
2013/02/04 HTML / CSS
《我为你骄傲》教学反思
2014/02/20 职场文书
给学校建议书范文
2014/05/13 职场文书
水电维修专业推荐信
2014/09/06 职场文书
公司承诺函范文
2015/01/21 职场文书
爱心助学感谢信
2015/01/21 职场文书
暑期家教宣传单
2015/07/14 职场文书
Python中OpenCV实现查找轮廓的实例
2021/06/08 Python
Mysql中的触发器定义及语法介绍
2022/06/25 MySQL