手把手搭建koa2后端服务器-API文档生成(番外)
ztj100 2024-12-25 16:49 24 浏览 0 评论
因为我们之前的框架没有接入 API 文档,而大多数 API 文档均采用编写注释来生成,我不是特别喜欢这种方式,所以暂时没有添加,后来发现一个库—koa-swagger-decorator,它对 koa-router 进行了封装,可以自动生成 API 文档,而且自带验证,这种方式比较好,但是项目结构上会有一些细微的差异,因此我决定单开一个分支来使用这种方式初始化一个新的项目,大家可以选择自己喜欢的项目结构来使用,这篇文档我只介绍与之前不同的地方,如果一模一样,我就不单独写了。
创建项目目录
mkdir koa2-demo
yarn init
安装依赖库
yarn add koa koa-body koa-swagger-decorator dotenv log4js typeorm reflect-metadata mysql2 koa2-cors bcryptjs jsonwebtoken
yarn add -D ts-node typescript nodemon @types/dotenv @types/koa @types/log4js @types/reflect-metadata @types/koa2-cors @types/bcryptjs @types/jsonwebtoken
这里我们一次性把常用的库全部安装上,下面我大概介绍以下库的用途:
- koa-body:解析 post 参数的库,koa 默认会解析查询参数和路径参数,但是对于请求体没有解析,所以需要这个库,我们就能使用 ctx.request.body 来处理请求体了。
- koa-swagger-decorator:这个库当中集成了 路由(koa-router)、认证(validator)库,这个就不需要我们单独安装了。
- dotenv:环境变量读取库。
- log4js:日志处理库。
- typeorm、reflect-metadata、mysql2:数据库操作库。
- bcryptjs:加密库。
- jsonwebtoken:jwt 加解密库。
- ts-node:支持ts直接运行的库。
- nodemon:监控文件改变热加载的库。
- 其他:@types开头的库都是为了支持 ts 提示的,在安装库的时候使用@type/库名 ,如果可以安装就安装,如果没有就不需要安装。
接下来除了请求参数校验和路由动态加载以外,其他的均可参考之前的教程。
路由处理修改
// src/router/index.ts
import path from 'path';
import { SwaggerRouter } from 'koa-swagger-decorator';
const router = new SwaggerRouter();
// 定义 schema 的初始信息
router.swagger({
title: 'koa2 基础 API',
description: 'API',
version: '1.0.0',
});
// 这里会动态的检索 controller 目录下的所有 .js、.ts 文件,并获取默认导出类,生成路由和API
// 因此就不需要我们再收到注册路由和自己实现动态加载路由的功能了,具体的路由格式请参考 controller
// 目录下的实现
router.mapDir(path.resolve(__dirname, '../controller'));
// 重定向/路由到/swagger-html路由,这是默认的API文档路由地址
router.redirect('/', '/swagger-html');
export default router;
业务逻辑修改
之前我们通过在 controller 下创建子目录及指定名称的文件来区分业务逻辑,例如
- controller
- common
- view.ts
- router.ts
- rules.ts
- types.ts
现在我们可以简化这个目录,结构如下:
- controller
- common
- view.ts
- schema.ts
其中 view.ts 中实现我们的业务逻辑,schema.ts 中定义我们的参数信息,用来进行参数验证和API文档生成。
修改登录逻辑
// src/controller/common/view.ts
import { Context } from 'koa';
import bcryptjs from 'bcryptjs';
import { request, summary, body, tags } from 'koa-swagger-decorator';
import response from '../../utils/response';
import { loginRules } from './schema';
import User from '../../entity/User';
import { generateToken } from '../../utils/auth';
export default class IndexController {
@request('post', '/login')
@summary('登录')
@tags(['基础接口'])
@body(loginRules)
static async login(ctx: Context) {
const data = ctx.request.body;
// 校验用户是否存在
let user: User | undefined = await User.getUserInfo(data.username);
if (!user) {
response.error(ctx, '用户不存在');
return;
}
// 校验密码是否正确
if (!bcryptjs.compareSync(data.password, user.password)) {
response.error(ctx, '密码错误');
return;
}
const { password, ...rest } = user;
const token = generateToken(rest);
response.success(ctx, { token }, '登录成功');
}
}
主体逻辑基本没有变化,有几个需要注意的点
- 类必须使用 export default 导出,路由扫描时会通过这个进行验证(必须)
- 使用@request装饰器修饰函数,参数为方法类型和地址,路由注册是就会根据这些生成,而不是根据我们的函数名(必须)
- 函数应该定义成静态的,因为在使用的时候并不会创建类对象,使用静态方法更符合状况(可选)
我们访问:http://localhost:3100/ 就可以看到API文档
路由修饰参数的意义
路由装饰器分为两种:函数装饰器和类装饰器
函数装饰器
- request:定义路由方法和地址,用于注册路由和API接口文档
- summary:API 文档中的路由解释,参考上图
- tags:路由分类,API 文档中用来对多个路由进行分组显示。
- query:查询参数:url?name=xxx&age=12
- path:路径参数:/getuserinfo/{id}
- body:请求体参数
- formData:表单数据。
- middlewares:koa中间件,eg:[md1, md2]
- security:
- description:接口描述
- responses:接口返回值,可以设定不同的状态返回不同的数据
- deprecated:
类装饰器
- orderAll:参数为数字,表示在文档中的位置。
- tagsAll:此类下的所有路由都属于这个tag。
- responsesAll:此类下的所有路由都返回这种类型。
- middlewaresAll:此类下的所有路由都拥有的中间件。
- securityAll:
- deprecatedAll:
- queryAll:此类下的所有路由都拥有的查询参数,与函数的查询参数会合并。
参数验证
参数校验支持:string, number, boolean, object, array。在object和array里面的参数也支持校验,对于integer类型是不支持校验的,会直接返回其值。默认是开启校验的,可以通过配置关闭校验。
router.mapDir(__dirname, { doValidation: true})
经过校验的数据可以通过ctx.validatedBody等方式获取经过校验的数据了,对应关系如下:
- ctx.query ≤==> ctx.validatedQuery
- ctx.params ≤==> ctx.validatedParams
- ctx.request.body ≤==> ctx.validatedBody
校验对象配置
- 基础校验字段
字段 | 值类型 | 备注 |
required | boolean | 必须参数 |
example | any | 参数类型,API 文档中使用的示例 |
description | string | 接口描述 |
readOnly | boolean | 只读参数 |
writeOnly | boolean | 只写参数 |
nullable | boolean | 是否可以为空 |
- 字符串类型
字段 | 值类型 | 备注 |
type | 'string' | |
minLength | number | 最小长度,实测不会校验 |
maxLength | number | 最大长队,实测不会校验 |
format | string | 格式校验,email |
pattern | string | 正则验证 |
- 数值类型
字段 | 值类型 | 备注 |
type | 'number' | |
minimum | number | |
exclusiveMinimum | boolean | |
maximum | number | |
exclusiveMaximum | boolean | |
multipleOf | number |
- 布尔类型
字段 | 值类型 | 备注 |
type | 'boolean' |
- 数组类型
字段 | 值类型 | 备注 |
type | 'array' | |
minItems | number | |
maxItems | number | |
uniqueItems | boolean | |
items | PropertyOptions |
- 对象类型
字段 | 值类型 | 备注 |
type | 'object' | |
properties | any | |
minProperties | number | |
maxProperties | number |
相关推荐
- sharding-jdbc实现`分库分表`与`读写分离`
-
一、前言本文将基于以下环境整合...
- 三分钟了解mysql中主键、外键、非空、唯一、默认约束是什么
-
在数据库中,数据表是数据库中最重要、最基本的操作对象,是数据存储的基本单位。数据表被定义为列的集合,数据在表中是按照行和列的格式来存储的。每一行代表一条唯一的记录,每一列代表记录中的一个域。...
- MySQL8行级锁_mysql如何加行级锁
-
MySQL8行级锁版本:8.0.34基本概念...
- mysql使用小技巧_mysql使用入门
-
1、MySQL中有许多很实用的函数,好好利用它们可以省去很多时间:group_concat()将取到的值用逗号连接,可以这么用:selectgroup_concat(distinctid)fr...
- MySQL/MariaDB中如何支持全部的Unicode?
-
永远不要在MySQL中使用utf8,并且始终使用utf8mb4。utf8mb4介绍MySQL/MariaDB中,utf8字符集并不是对Unicode的真正实现,即不是真正的UTF-8编码,因...
- 聊聊 MySQL Server 可执行注释,你懂了吗?
-
前言MySQLServer当前支持如下3种注释风格:...
- MySQL系列-源码编译安装(v5.7.34)
-
一、系统环境要求...
- MySQL的锁就锁住我啦!与腾讯大佬的技术交谈,是我小看它了
-
对酒当歌,人生几何!朝朝暮暮,唯有己脱。苦苦寻觅找工作之间,殊不知今日之事乃我心之痛,难道是我不配拥有工作嘛。自面试后他所谓的等待都过去一段时日,可惜在下京东上的小金库都要见低啦。每每想到不由心中一...
- MySQL字符问题_mysql中字符串的位置
-
中文写入乱码问题:我输入的中文编码是urf8的,建的库是urf8的,但是插入mysql总是乱码,一堆"???????????????????????"我用的是ibatis,终于找到原因了,我是这么解决...
- 深圳尚学堂:mysql基本sql语句大全(三)
-
数据开发-经典1.按姓氏笔画排序:Select*FromTableNameOrderByCustomerNameCollateChinese_PRC_Stroke_ci_as//从少...
- MySQL进行行级锁的?一会next-key锁,一会间隙锁,一会记录锁?
-
大家好,是不是很多人都对MySQL加行级锁的规则搞的迷迷糊糊,一会是next-key锁,一会是间隙锁,一会又是记录锁。坦白说,确实还挺复杂的,但是好在我找点了点规律,也知道如何如何用命令分析加...
- 一文讲清怎么利用Python Django实现Excel数据表的导入导出功能
-
摘要:Python作为一门简单易学且功能强大的编程语言,广受程序员、数据分析师和AI工程师的青睐。本文系统讲解了如何使用Python的Django框架结合openpyxl库实现Excel...
- 用DataX实现两个MySQL实例间的数据同步
-
DataXDataX使用Java实现。如果可以实现数据库实例之间准实时的...
- MySQL数据库知识_mysql数据库基础知识
-
MySQL是一种关系型数据库管理系统;那废话不多说,直接上自己以前学习整理文档:查看数据库命令:(1).查看存储过程状态:showprocedurestatus;(2).显示系统变量:show...
- 如何为MySQL中的JSON字段设置索引
-
背景MySQL在2015年中发布的5.7.8版本中首次引入了JSON数据类型。自此,它成了一种逃离严格列定义的方式,可以存储各种形状和大小的JSON文档,例如审计日志、配置信息、第三方数据包、用户自定...
你 发表评论:
欢迎- 一周热门
-
-
MySQL中这14个小玩意,让人眼前一亮!
-
旗舰机新标杆 OPPO Find X2系列正式发布 售价5499元起
-
【VueTorrent】一款吊炸天的qBittorrent主题,人人都可用
-
面试官:使用int类型做加减操作,是线程安全吗
-
C++编程知识:ToString()字符串转换你用正确了吗?
-
【Spring Boot】WebSocket 的 6 种集成方式
-
PyTorch 深度学习实战(26):多目标强化学习Multi-Objective RL
-
pytorch中的 scatter_()函数使用和详解
-
与 Java 17 相比,Java 21 究竟有多快?
-
基于TensorRT_LLM的大模型推理加速与OpenAI兼容服务优化
-
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)