05-KOA框架
# 1. KOA简介与入门
Koa 是⼀个新的 web 框架,由 Express 幕后的原班⼈⻢打造, 致⼒于成为web 应⽤和 API 开发领域中的⼀个更⼩、更富有表现⼒、更健壮的基⽯。 通过利⽤ async 函数,Koa 帮你丢弃回调函数,并有⼒地增强错误处理。 Koa并没有捆绑任何中间件, ⽽是提供了⼀套优雅的⽅法,帮助您快速⽽愉快地编写服务端应⽤程序。
步骤
- 创建文件夹 codekao
- 进入文件夹,生成项目配置文件 npm init -y
- 安装koa: npm i koa@2.13.4 -S
- 在codekao文件夹下,创建 01-搭建koa服务器.js
代码如下:
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
2
3
4
5
6
运行代码:node 01-搭建koa服务器.js
通过浏览器或postman访问之:
# 2. 中间件机制
再配⼀张洋葱模型
代码如下:
const Koa = require('koa');
const app = new Koa();
// logger
app.use(async (ctx, next) => {
console.log(1);
await next();
console.log(5);
const rt = ctx.response.get('X-Response-Time ');
console.log(`${ctx.method} ${ctx.url} -${rt}`);
});
// x-response-time
app.use(async (ctx, next) => {
const start = Date.now();
console.log(2);
await next();
console.log(4);
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
});
// response
app.use(async ctx => {
console.log(3);
ctx.status = 200; //设置响应状态码
ctx.type = 'html'; //等价于ctx.set('Content-Type ','text / html ')
ctx.body = 'Hello World'; //设置响应体
});
app.listen(3000); //语法糖 等同于http.createServer(app.callback()).listen(3000)
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
打印结果: 1 2 3 4 5
结论: 当请求开始时先通过X-Response-Time 和logger 中间件, 然后继续交给response 中间件,当⼀个中间件调⽤next() 则该函数暂停执⾏并将控制权传递给定义的下个中间件. 当在response 中间件执⾏后, 下游没有更多的中间件. 这个时候每个中间件恢复其上游⾏为
# 3. 错误监听
常⻅抛出异常和错误类型
- 代码语法不规范造成的JS报错异常
- 程序运⾏中发⽣的⼀些未知异常
- HTTP错误
- ⾃定义的业务逻辑错误
添加error全局事件侦听器
const Koa = require('koa');
const app = new Koa();
// app.use(async ctx => {
// ctx.body = 'hello world'
// })
// 触发错误 koa帮咱们做了处理
app.use(async (ctx, next) => {
throw new Error('未知错误');
})
//全局错误处理 后台打印
app.on('error', err => {
console.log('全局错误处理', err.message)
})
app.listen(3000);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 4. 错误处理中间件
代码如下:
const Koa = require('koa');
const app = new Koa();
// 错误处理中间件
app.use(async (ctx, next) => {
try {
await next();
} catch (error) {
// 给⽤户显示状态码
ctx.status = error.statusCode || error.status || 500;
//如果是ajax请求,返回的是json错误数据
ctx.type = 'json';
// 给⽤户显示
ctx.body = {
ok: 0,
message: error.message
};
// 系统⽇志
ctx.app.emit('error', error, ctx);
}
})
// 触发错误 koa帮咱们做了处理
app.use(async (ctx, next) => {
throw new Error('未知错误');
})
// response
//....
//全局错误处理 后台打印
app.on('error', err => {
console.log('全局错误处理', err.message)
})
app.listen(3000);
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
注意: 每次修改了服务器代码,都需要重新启动服务器,为了方便,可以全局安装nodemon。
- 全局安装:npm i nodemon -g
# 5. koa-logger处理⽇志
安装: npm i koa-logger@3.2.1
- 尽量和我的版本保持一致
- 在控制台可以更加细致看到错误信息
const Koa = require('koa');
const app = new Koa();
const logger = require('koa-logger')
app.use(logger())
app.use(async (ctx, next) => {
throw new Error('未知错误');
})
// 全局的事件监听器
app.on('error', (err) => {
console.log('全局错误处理:', err.message, err.status, err.data)
})
app.listen(3000, () => {
console.log('3000端口被监听了~~')
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 6. koa-erros处理错误
安装: npm i koa-onerror@4.2.0
- 尽量和我的版本保持一致
- 在控制台可以更加细致看到错误信息
const Koa = require('koa')
const onerror = require('koa-onerror')
const app = new Koa()
const logger = require('koa-logger')
app.use(logger())
onerror(app)
// koa的中间件
app.use(async (ctx, next) => {
// ctx.throw()相当于是一个中间件
ctx.throw(401, '未授权', {
data: '你瞅瞅'
})
// ctx.body = 'wc' //设置响应体
/*
等价
const err = new Error('未授权');
err.status = 401;
err.expose = true;
throw err;
*/
})
app.use(async (ctx) => {
ctx.body = '错误处理中间件'
})
// 全局的事件监听器
app.on('error', (err) => {
console.log('全局错误处理:', err.message, err.status, err.data)
})
app.listen(3000, () => {
console.log('3000端口被监听了~~')
})
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
# 7. koa-log4处理⽇志
koa-log4 ⽐较好⽤的node环境下处理⽇志处理的模块, koa-log4 在 log4js-node 的基础上做了⼀次包装,是 koa 的⼀个处理⽇志的中间件,此模块可以帮助你按照你配置的规则分叉⽇志消息。
操作步骤:
- 在根⽬录下新建 logger/ ⽬录
- 在 logger/ ⽬录下新建 logs/ ⽬录,⽤来存放⽇志⽂件
- 在 logger/ ⽬录下新建 index.js ⽂件
安装: npm i koa-log4@2.3.2
logger目录下的index.js代码(大家直接copy)如下:
const path = require('path')
const log4js = require('koa-log4')
log4js.configure({
appenders: {
// 访问级别
access: {
type: 'dateFile',
// 生成文件的规则
pattern: '-yyyy-MM-dd.log',
// 文件名始终以日期区分
alwaysIncludePattern: true,
encoding: 'utf-8',
// 生成文件路径和文件名
filename: path.join(__dirname, 'logs', 'access')
},
application: {
type: 'dateFile',
pattern: '-yyyy-MM-dd.log',
alwaysIncludePattern: true,
encoding: 'utf-8',
filename: path.join(__dirname, 'logs', 'application')
},
out: {
type: 'console'
}
},
categories: {
default: {
appenders: ['out'],
level: 'info'
},
access: {
appenders: ['access'],
level: 'info'
},
application: {
appenders: ['application'],
level: 'WARN'
}
}
})
// // 记录所有访问级别的日志
// exports.accessLogger = () => log4js.koaLogger(log4js.getLogger('access'))
// // 记录所有应用级别的日志
// exports.logger = log4js.getLogger('application')
module.exports = {
// 记录所有访问级别的日志
accessLogger: () => log4js.koaLogger(log4js.getLogger('access')),
// 记录所有应用级别的日志
logger: log4js.getLogger('application')
}
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
- 访问级别的,记录⽤户的所有请求,作为koa的中间件,直接使⽤便可。
- 应⽤级别的⽇志,可记录全局状态下的 error ,修改 app.js 全局捕捉异常
修改对应的代码如下:
const Koa = require('koa')
const onerror = require('koa-onerror')
const {
accessLogger,
logger
} = require('./logger')
const app = new Koa()
onerror(app)
app.use(accessLogger())
// koa的中间件
app.use(async (ctx, next) => {
// ctx.throw()相当于是一个中间件
ctx.throw(401, '未授权', {
data: '你瞅瞅'
})
// ctx.body = 'wc' //设置响应体
/*
等价
const err = new Error('未授权');
err.status = 401;
err.expose = true;
throw err;
*/
})
// app.use(async ctx => {
// ctx.body = 'Hello World';
// });
// 全局的事件监听器
app.on('error', (err) => {
logger.error(err)
})
app.listen(3000, () => {
console.log('3000端口被监听了~~')
})
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
36
37
38
39
# 8. 路由中间件koa-router
安装: npm i @koa/router@10.1.1 使⽤: 新建router/index.js和router/users.js
router/index.js中代码如下:
const Router = require('@koa/router');
const router = new Router();
router.get('/', (ctx, next) => {
ctx.body = '⾸⻚';
})
module.exports = router;
2
3
4
5
6
7
8
router/user.js中代码如下:
const Router = require('@koa/router');
const router = new Router();
router.prefix('/user')
router.get('/', (ctx, next) => {
ctx.body = '⽤户界⾯';
})
module.exports = router;
2
3
4
5
6
7
8
9
入口文件中导⼊并注册,如下:
const Koa = require('koa')
const index = require('./router/index')
const users = require('./router/user')
const app = new Koa()
// 注册路由
app.use(index.routes())
index.allowedMethods()
app.use(users.routes())
users.allowedMethods()
app.listen(3000, () => {
console.log('3000端口被监听了~~')
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 9. get请求
// router/user.js
const Router = require('@koa/router');
const router = new Router();
router.prefix('/user')
//访问http://localhost:3000/users/3/1
router.get('/:id/:pid', (ctx, next) => {
console.log(ctx.params.id, ctx.params.pid);
ctx.body = '⽤户界⾯1';
})
//访问http://localhost:3000/user/3?name=wc
router.get('/:id', (ctx, next) => {
//通过ctx.query获取查询的参数
console.log(ctx.query.name);
ctx.body = '⽤户界⾯2';
})
module.exports = router;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 10. post请求
- post解析请求的参数需要下载 koa-bodyParser
- 安装:npm i koa-bodyparser@4.3.0
// router/index.js
const Router = require('@koa/router');
const router = new Router();
router.post('/', (ctx, next) => {
console.log(ctx.request.body);
ctx.body = {
'ok': 1
}
})
module.exports = router;
2
3
4
5
6
7
8
9
10
11
12
13
// 入口 js
const Koa = require('koa')
const index = require('./router/index')
const users = require('./router/user')
const bodyParser = require('koa-bodyparser')
const app = new Koa()
app.use(bodyParser());
// 注册路由
app.use(index.routes())
index.allowedMethods()
app.use(users.routes())
users.allowedMethods()
app.listen(3000, () => {
console.log('3000端口被监听了~~')
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
由于浏览器地址栏,只能发送get请求,要发送post请求,需要使用postman,如下:
# 11. 重定向
// router/index.js
const Router = require('@koa/router');
const router = new Router();
router.get('/login', ctx => {
//判断⽤户是否处于登录状态...
ctx.redirect('/sign-in');
ctx.status = 301;
})
router.get('/sign-in', (ctx, next) => {
ctx.body = '注册⻚⾯'
})
module.exports = router;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 12. 静态资源托管
- 安装:npm i koa-static@5.0.0
- 静态资源都放在根目录的public目录下面
代码:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<h1>今天学习Koa,感觉非常爽~</h1>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* index.css */
h1 {
color: red;
}
2
3
4
配置:
const Koa = require('koa')
const index = require('./router/index')
const users = require('./router/user')
const bodyParser = require('koa-bodyparser')
const static = require('koa-static');
const app = new Koa()
app.use(bodyParser());
app.use(static(__dirname + '/public'))
// 注册路由
app.use(index.routes())
index.allowedMethods()
app.use(users.routes())
users.allowedMethods()
app.listen(3000, () => {
console.log('3000端口被监听了~~')
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
效果如下: