前言
- 学习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 | const koa = require('koa') |
2.Context对象
Koa将Node.js的Request(请求)和Response(响应)对象封装到Context对象中。可以在Context对象中自定义一些属性,配置以供全局使用
1 | app.use(async ctx => { |
常见属性和方法:
- ctx.request
使用方法:1
2
3
4
5
6
7
8
9
10
11
12app.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-routerrouter.all()方法一般用来设置请求头,如设置过期时间,CORS(Cross-Origin Resource Sharing,跨域资源共享)
1
2
3
4router.post()
.del()
.put()
.get()1
2
3
4
5router.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章 数据库了
准备完成微信小程序的云相册。