Skip to content

Koa学习

1、技术分析

  • RESTFul理论
  • Koa2
  • Postman
  • MongoDB
  • jwt认证原理
  • 数据库设计
  • 线上部署

2、RESTFul Api

GitHub REST API

符合REST架构风格的Api

RESTFul长什么样子

  • 基本的URL,如:https://api.github.com/users
  • 标准的http方法,如:get、post、put、patch、delete
  • 传输的媒体数据类型,如:json、xml

请求设计规范

image.png

响应设计规范

  • 查询
  • 分页
  • 字段过滤
  • 状态码
  • 错误处理

安全

  • HTTPS
  • 鉴权
  • 限流

3、Koa简

Koa

一句话简介

基于Node.js平台的下一代web开发框架

官网简介

  • 由Express膜厚原班人马打造
  • Web应用和Api开发领域
  • 更小、更富有变现力、更健壮
  • 利用async函数,丢弃回调函数
  • 增强错误处理: try catch
  • 没有捆绑任何中间件

4、项目搭建

初始化项目

bash
npm init

安装Koa

bash
npm i koa --save

编写Hello Word

javascript
const Koa = require('koa');

const app = new Koa();

app.use((ctx) => {
    ctx.body = 'Hello .. Word!'
});

app.listen(3000);

自动重启

bash
npm i nodemon --save
json
{
    "start": "nodemon index.js"
}

5、中间件和洋葱模式

中间件

就是一个函数

javascript
/**
 * 中间件1
 */
app.use(async (ctx, next) => {
    // 有多个中间件的时候,先执行这个中间件,再去执行下个中间件,
    // 此处应该执行next,next返回的是一个Promise
    await next();
    // 下一个中间件执行完成,这也就是所谓的洋葱模式
    console.log(1);
    ctx.body = 'Hello .. Word!'
});

洋葱模式image.png

Reguest

Response

RegistryManager

StatusCodeRedirect

ErrorHandler

CacheMiddleware

SessionMiddleware

RoutesMiddleware

PylonsApp

image.png

6、路由

koa-router

javascript
const Router = require('koa-router');

// 实例化路由
const router = new Router({
   // 加路由前缀
	 refix: '/users'
})

// 注册路由
app.use(router.routes());

路由前缀

javascript
// 添加路由前缀
router.prefix('/api/photo');

多中间件

javascript
router.get('/users/:id',()=>{}, ()=>{}, ()=> {}, (ctx) => {
    ctx.body = `用户id: ${ctx.params.id}`;
});

options请求方法

预检请求

  • 检测服务器支持哪些请求方法
  • 支持cors的预检请求

allowedMethods

响应options请求

javascript
// 注册路由
app.use(router.routes());
app.use(router.allowedMethods()); // 响应options请求

7、控制器

类+类方法的方式组织控制器

断点调试

  • 调试
  • 监控变量

获取HTTP请求参数

Query String,如:name=name(可选)

ctx.query.name

Router Params,如:/users/:name(必选)

ctx.params.name

Body,如

ctx.request.body.name

Header,如Accept、Cookie

ctx.header.token

发送HTTP响应

发送Status,如:200

javascript
 ctx.status = 200;

发送Body,如:

javascript
ctx.body = {
  id: ctx.params.id,
  name: '马化腾',
};

发送Header,如:Allow、Content-Type

javascript
ctx.set('Allow', 'GET, POST');

处理业务逻辑

控制器处理业务逻辑

路由引入对应的操作

8、错误处理

处理软件或者程序出现的异常状况

运行时错误

500

逻辑错误

404,423,422

为什么错误处理?

  • 防止程序挂掉
  • 高速用户错误信息
  • 便于开发者调试

koa错误处理

  • 抛出错误
javascript
row(412, '先决条件失败');
  • 错误的处理

错误处理中间件

安装koa-json-error

bash
npm i koa-json-error --save-dev

错误处理配置(环境区分)

生产环境禁用打印堆栈信息

javascript
// 错误处理
app.use(koaJsonError({
    postFormat: (e, {
        stack,
        ...rest
    }) => {
        return process.env.NODE_ENV === 'production' ? rest : {
            stack,
            ...rest
        }
    }
}));

统一环境变量的库

bash
 "start": "cross-env NODE_ENV=production node index.js"

koa参数校验

  • 使用
javascript
 ctx.verifyParams({
    userName: {
        type: 'string',
        required: true,
    },
    userPwd: {
        type: 'string',
        required: true,
    },
});

目录结构

app
├── api                 # api 层
│   ├── cms             # 关于 cms 的 api
│   │   ├── admin.js
│   │   ├── log.js
│   │   ├── test.js
│   │   └── user.js
│   └── v1              # 普通api
│       └── book.js
├── config              # 配置文件目录
│   ├── code-message.js # 返回成功码错误码和返回信息配置
│   ├── log.js          # 日志配置文件
│   ├── secure.js       # 安全性配置文件
│   └── setting.js      # 普通配置文件
├── dao                 # 数据库操作
│   ├── admin.js
│   ├── book.js
│   ├── log.js
│   └── user.js
├── extension           # 扩展目录
├── lib                 # 其它类库
│   ├── db.js           # Sequelize 实例
│   ├── exception.js    # 异常类库
│   ├── type.js         # 枚举
│   └── util.js         # 助手函数
├── middleware          # 中间件目录
│   ├── jwt.js
│   └── logger.js
├── model               # 模型层
│   ├── book.js
│   ├── file.js
│   ├── group-permission.js
│   ├── group.js
│   ├── log.js
│   ├── permission.js
│   ├── user-group.js
│   └── user.js
├── plugin              # 插件目录
├── validator           # 校验层
│   ├── admin.js        # 校验器模块
│   ├── book.js
│   ├── common.js
│   ├── log.js
│   └── user.js
├── app.js              # 创建koa实例及应用扩展
└── starter.js          # 程序的启动文件

9、字段过滤

请求

http://127.0.0.1:3000/cms/users/id?fields=user_pwd;gender;headline;

接口过滤

js
// 查询特定
async function findOne(ctx) {
    const {
        fields = ''
    } = ctx.query;
    // 过滤字段的参数
    let selectFields = fields.split(';').filter(field => field).map(field => ' +' + field).join('');
    let res = await User.findOne({
        _id: ctx.params.id
    }).select(selectFields);  // 字段过滤
    if (!res) {
        ctx.throw(404, '该用户不存在')
    } else {
        ctx.body = res;
    }
}

10、上传图片的实现

功能点

  • 基础功能

上传图片、生成图片链接

  • 附加功能

限制上传图片的大小与类型、生成高中低三种分辨率的图片链接、生成CDN

技术方案

  • 阿里云OSS等云服务(推荐生产使用)
  • 直接上传到服务器(不推荐生产使用,适合学习使用)

操作步骤

安装koa-body,替换 koa-bodyparser

bash
npm i koa-bodyparser --save

设置图片上传目录

javascript
// 请求体解析
app.use(koaBody({
    multipart: true, // 启动文件
    formidable: {
        uploadDir: path.join(__dirname, '/public/uploads'), // 文件存放目录
        keepExtensions: true, // 保留扩展名
    }
}));
const koaBody = require('koa-body');

获取上传图片

upload (ctx) {
    const file = ctx.request.files.file;
    ctx.body = {
        path: file.path
    }
}

生成上传图片链接

image.png

js
function upload (ctx) {
    // 上传的文件
    const file = ctx.request.files.file;
    // 获取文件名
    const basename = path.basename(file.path);
    // 生成上传后的图片链接
    const url = `${ctx.origin}/uploads/${basename}`;
    ctx.body = {
        url
    }
}

11、二级嵌套路由的设计

a、前缀

javascript
const router = new Router({ prefix: '/questions/:questionId/answers' });

b、获取参数

javascript
ctx.params.questionId

12、koa应用的部署

登录服务器:

bash
ssh -p 22 root@106.12.182.39

安装Git,并下载项目

使用Git并clone代码至服务器,并安装Node

可以npm run start 测试下项目能不能跑起来

bash
npm install

但是,当我们退出服务器后,node的进程也就关了,服务也就没了,

所以我们需要 pm2 来守护进程

pm2使用

守护进程,后台运行

安装

npm install pm2 -g

安装完成后云服务切换到你项目所在路径

启动并监听服务:

pm2 start ./bin/www --watch

## --watch参数,koa2应用代码发生变化时,pm2会帮你重启服务。

启动之后,显示如下:说明启动成功!

pm2更多用法

pm2 reload <appname> ./bin/www // 开启
pm2 start <appname> ./bin/www // 开启
pm2 stop <appname> ./bin/www // 关闭
pm2 list //查看所用已启动项目:

pm2列表查看,pm2 list

输入 pm2 show 0 对应上图中的id = 0

image.png

关闭进程

www 对应list的name

bash
pm2 stop www

pm2杀死进程,pm2 kill

拓展

  • 使用企业级Node.js框架 ——Egg.js
  • 掌握多进程编程知识
  • 学习使用日志和性能监控
  • koa2 统一接口数据结构及类型定义文件扩展

常见问题


Nginx使用