Node+koa初识

前言

  • 学习Node.js最流行的框架—Koa
  • Koa是基于Node.js的web框架,特点是轻量,健壮,富有表现力。由Express的原班人马打造,目前有Koa1和Koa2两种版本
  • 异步处理机制相较于Express而言,Express主要采用ES5的语法,异步操作通过回调函数来处理(存在“回调地狱”)
    • Koa1 :采用ES6中的Generator函数+yield语句+Promise语句
    • Koa2 :采用ES7中的async/await+Promise
  • 基于Express的旧项目,转用Koa成本较高。不但需要升级Node.js的版本,还需要重新编写几乎所有中间件。
  • 除了语法差异,Koa不在内核方法中绑定任何中间件,仅仅提供一个轻量的函数库,几乎所有的功能引入第三方中间件来实现,使得框架自身更轻量,更优雅。
  • 一个直观对比,见下方代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    // Express版本
    var express = require('express'); // 引入Express
    var app = express(); // 实例化一个新app
    app.get('/', function (req, res) { // 路由中间件处理路由
    asyncFunction1(params, function() {
    asyncFunction2(params, function() {
    asyncFunction3(params, function() {
    res.send('Hello World!')
    })
    })
    })
    })
    var server = app.listen(3000) // 启动app,监听3000端口

    // Koa1版本
    var koa = require('koa') // 引入Koa1
    var app = koa() // 实例化一个新的app
    app.use(function* () { // 对任意请求进行处理的中间件
    yield asyncFunction1(params)
    yield asyncFunction2(params)
    yield asyncFunction3(params)
    this.body = 'Hello World'
    })
    app.listen(3000) // 启动app,监听3000端口

    // Koa2版本
    const koa = require('koa') // 引入koa2
    const app = new koa() //实例化一个新的app
    app.use(async ctx => {
    await asyncFunction1(params)
    await asyncFunction2(params)
    await asyncFunction3(params)
    ctx.body = 'Hello World'
    })
    app.listen(3000) // 启动app,监听3000端口

一. 遇见Koa

1.hello word

初始化项目:

  • 项目初始化:npm init
  • 新建app.js 输入:console.log(“hello world”)
  • 终端输入:node app.js
  • 控制台成功输出hello world

安装Koa: npm install koa -save

启动服务器: 对app.js的代码进行如下修改

1
2
3
4
5
6
7
8
9
10
11
const koa = require('koa')
const app = new koa()
// 加入一个简单的中间件 访问3000端口可以显示信息
app.use(async (ctx, next) => {
await next()
ctx.response.type = 'text/html'
ctx.response.body = '<h1>Hello World</h1>'
})
app.listen(3000, () => {
console.log('server is running at http://localhost:3000');
})

2.Context对象

Koa将Node.js的Request(请求)和Response(响应)对象封装到Context对象中。可以在Context对象中自定义一些属性,配置以供全局使用

1
2
3
4
5
6
7
8
app.use(async ctx => {
ctx; // 这是Context
ctx.request; // 这是Koa Request
ctx.response; // 这是Koa Response
this; // 这是Context
this.request; // 这是Koa Request
this.response; // 这是Koa Response
})

常见属性和方法:

  • ctx.request
    使用方法:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    app.use(async (ctx) => {
    ctx.response.body = {
    url: ctx.request.url, // 获取请求URL
    query: ctx.request.query, // 获取解析的查询字符串
    querystring: ctx.request.querystring, // 获取原始查询字符串
    }
    ctx.req.on('data',(data) => {
    // 监听data事件
    })
    ctx.request.method //判断请求是GET还是POST
    ctx.request.accepts('json') //判断客户期望的数据类型
    })
  • ctx.response
    ctx.response.status 设置请求状态
    ctx.response.type=’html’ 设置响应的Content-Type为HTML格式;如果Context-Type不对会发生解析错误
    ctx.response.is(types…) 用来检查响应类型是否是所提供的类型之一
    ctx.response.redirect(url,[alt]) 重定向
  • ctx.state
    ctx.state是推荐命名空间,用于通过中间件传递信息和前端视图。类似koa-views
  • ctx.cookies
    用于获取和设置Cookie
    ctx.cookies.get(name, [options])
    ctx.cookies.set(name, value, [options])
  • ctx.throw
    用于抛出错误

3.Koa中间件

中间件函数有2个参数,ctx和next。通过app.use()函数来加载中间件
next用于将中间件的执行权交给下游的中间件
在next()之前使用await关键字是因为next()会返回一个Promise对象。
执行顺序类似于:先进后出的堆栈结构

  • koa-bodyparser
    可以将POST请求的参数解析到ctx.request.body中。
    使用之前先安装:npm install –save koa-bodyparser
  • koa-router
    1
    2
    3
    4
    router.post()
    .del()
    .put()
    .get()
    router.all()方法一般用来设置请求头,如设置过期时间,CORS(Cross-Origin Resource Sharing,跨域资源共享)
    1
    2
    3
    4
    5
    router.all('/*', async (ctx, next) => {
    // 符号*代表允许来自所有域名的请求
    ctx.set("Access-Control-Allow-Origin", "https://www.baidu.com");
    await next()
    })
  • koa-static
    用于加载静态资源的中间件
  • koa-views
    用于加载HTML模板文件

二.路由

Routing is mapping URLs to code that handles them

RESTful规范

在RESTful架构中,所有的关键点都集中在如何定义资源和如何提供资源的访问上。
OOP(面向对象)的思想,一个资源提供多种方法,就如同一个类提供多种方法一样
深入学习其中的精髓可以参考GitHub。Github的API设计被称为RESTful API教科书的典范,地址为https://developer.github.com/v3/
Guthub v4 的API使用了全新的设计风格 GraphQL ,地址为https://developer.github.com/v4/

在一个基于RESTful规范的应用中,URL对应的不同路径以为着不同的资源,所以对资源访问的限制即对URL访问的限制。
常见的鉴别用户权限的方式有两种,一种是广泛使用的Cookie-Based Authentication(基于Cookie的认证模式),另一种是Token-Based Authentication(基于Token的认证模式)
Token方式的最大优点在于采用了无状态机制,在此基础上,可以实现天然的跨域支持,前后端分离等,同时降低了服务端开发和维护的成本。
Token方式的缺点在于服务器每次都需要对Token进行校验,这一步会对服务器产生运算压力。另一方面,无状态API缺乏对用户流程或异常的控制,为避免出现一些例如回放攻击的异常情况,应该设置较短的过期时间,且需要对密钥进行严格的保护。对于具有复杂流程的高危场景(如支付等),则要谨慎选择Token认证模式

用JWT来实现Token的生成,校验和解码。Token的中间件实现选择koa-jwt,koa-jwt会在中间件流程中通过JWT完成对Token的校验和解码,开发者只需要通过JWT实现Token的生成即可。

请求过程:
Token会把每次请求通过请求头中的Authorization字段传给服务器端。
koa-jwt支持自定义getToken方法,Cookie和Header中的Authorization等3种校验方式,需要注意的是这里的Cookie方式不同于前面提到的基于Cookie的认证方式,只是一个使用Cookie作为存储并发送给服务器端的区域,校验并不依赖于服务器端的Session机制,服务器不会进行任何状态的保存。
所以流程是客户端访问login接口后获取Token,之后的请求需要将请求头中的Authorization设置为Bearer加Token的内容。
当请求经过koa-jwt中间件时,JWT会解码并校验Token,如果有权限将会进入到下一层中间件,否则会阻止访问。

通过curl工具可以模拟发送post请求
比如:通过curl工具模拟一次Token认证流程,当用户直接访问userInfo或/api/user/detail接口时,命令如下:
curl http://127.0.0.1:3000/api/userInfo

三.数据库

在Koa中应用MySQL

当然也可以连接MongoDB,Redis 等等数据库,但是使用的类库会有区别
关系型数据库是需要通过SQL语言来存取数据的,但是书写SQL语句需要一定的技术能力,并且不恰当的SQL语句还会带来SQL注入漏洞。
于是社区出现了ORM(Object Relational Mapping)类库,开发者不需要通过编写SQL脚本来操作数据库,直接通过访问对象的方式来查询,更新数据。
ORM统一封装了SQL查询,在某些情况下生成的SQL并不高效,依旧需要开发者编写SQL语句来提升性能
在Node.js中,一般采用Sequelize这个ORM类库来操作数据库。

Sequelize

使用步骤:

  • 安装:npm install sequelize -save
  • 建立数据库连接
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 使用Sequelize类库
    const Sequelize = require('sequelize')
    // database username password
    const sequelize = new Sequelize('database', 'username', 'password', {
    host: 'localhost', // 数据库服务地址
    dialect: 'mysql', // sql语言类型
    })
    sequelize.authenticate().then(() => { // 校验数据库连接
    console.log('Connected');
    }).catch(err => {
    console.log('Connected failed');
    })
  • 具体的语法可以查询官方Sequelize文档学习,这里有一个例子,客户信息数据展示
    其实就是4步:
    1
    2
    3
    4
    // 1.连接数据库并校验
    // 2.定义Table模型
    // 3.在model中定义完模型之后,就可以对定义的模型执行增删改查
    // 4.通过koa-router提供的RESTful接口,给业务方使用

未完待续。。。。。
学到第7章 数据库了
准备完成微信小程序的云相册。