摘要:注解方式为应用动态生成文档目前我司服务端应用程序框架主要采用了与,而因为今年有很多的调研阶段的产品线发布,持续部署接口文档以及线上质量监控这三个问题愈发突出。
swagger-decorator:注解方式为 Koa2 应用动态生成 Swagger 文档swagger-decorator:注解方式为 Koa2 应用自动生成 Swagger 文档 从属于笔者的服务端应用程序开发与系统架构,记述了如何在以 Koa2 与 koa-router 开发服务端应用时,通过自定义 swagger-decorator 库来实现类 Spring-Boot 中注解方式动态生成 Swagger 标准的接口文档。
目前我司服务端应用程序框架主要采用了 Java Spring 与 Node.js,而因为今年有很多的调研阶段的产品线 Demo 发布,持续部署、接口文档以及线上质量监控这三个问题愈发突出。本文则主要针对接口文档的实时发布进行一些探讨;在前后端分离的今天,即使是由单人纵向负责某个业务流,也需要将前后端交互的接口规范清晰地定义并且发布,以保证项目的透明性与可维护性。理想的开发流程中,应当在产品设计阶段确定好关键字段命名、数据库表设计以及接口文档;不过实际操作中往往因为业务的多变性以及人手的缺失,使得接口的定义并不能总是实时地在项目成员之间达成一致。如果要让开发人员在更改接口的同时花费额外精力维护一份开发文档,可能对于我司这样的小公司而言存在着很大的代价与风险。软件开发中存在着所谓 Single Source of Truth 的原则,我们也需要尽量避免文档与实际实现的不一致造成的团队内矛盾以及无用的付出。综上所述,我们希望能够在编写后台代码、添加注释的同时,能够自动地生成接口文档;笔者比较熟悉 Spring 中以注解方式添加 Swagger 文档的模式,不过 Java 库的抽象程度一般较高,用起来也不怎么顺手。笔者在编写我司 node-server-boilerplate 根据自己的想法设计了 swagger-decorator。此外,项目中使用 Flow 进行静态类型检测,并且遵循我司内部的 JavaScript 编程样式指南。
我们可以使用 npm 或者 yarn 安装 swagger-decorator,需要注意的是,因为使用了注解,因此建议是配置 Webpack 与 Babel,不熟悉的同学可以直接参考 node-server-boilerplate :
$ yarn add swagger-decorator # 依赖于 Babel 的 transform-decorators-legacy 转换插件来使用 Decorator $ yarn add transform-decorators-legacy -D
安装完毕之后,我们需要对项目中使用的路由进行封装。目前笔者只是针对 koa-router 中的路由对象进行封装,未来若有必要可以针对其他框架的路由解决方案进行封装。我们首先需要做的就是在路由定义之前使用 wrappingKoaRouter 函数修饰 router 对象:
import { wrappingKoaRouter } from "swagger-decorator"; ... const Router = require("koa-router"); const router = new Router(); wrappingKoaRouter(router, "localhost:8080", "/api", { title: "Node Server Boilerplate", version: "0.0.1", description: "Koa2, koa-router,Webpack" }); //定义默认的根路由 router.get("/", async function(ctx, next) { ctx.body = { msg: "Node Server Boilerplate" }; }); //定义用户处理路由 router.scan(UserController);
该函数的参数说明如下,对于 info 的结构参考这里:
/** * Description 将 router 对象的方法进行封装 * @param router 路由对象 * @param host API 域名 * @param basePath API 基本路径 * @param info 其他的 Swagger 基本信息 */ export function wrappingKoaRouter( router: Object, host: string = "localhost", basePath: string = "", info: Object = {} ) {}
值得一提的是,在封装 router 时,笔者自定义了 scan 方法,其能够根据自动遍历目标类中的自定义方法,有点类似于 Java 中的 ComponentScan:
/** * Description 扫描某个类中的所有静态方法,按照其注解将其添加到 * @param staticClass */ router.scan = function(staticClass: Function) { let methods = Object.getOwnPropertyNames(staticClass); // 移除前三个属性 constructor、name methods.shift(); methods.shift(); methods.shift(); for (let method of methods) { router.all(staticClass[method]); } };
准备工作完成之后,我们即可以开始定义具体的接口控制器;笔者不喜欢过多的封装,因此这里选用了类的静态方法来定义具体的接口函数,整个 Controller 也只是朴素函数。下面笔者列举了常见的获取全部用户列表、根据用户编号获取用户详情、创建新用户这几个接口的文档注释方式:
import { apiDescription, apiRequestMapping, apiResponse, bodyParameter, pathParameter, queryParameter } from "swagger-decorator"; import User from "../entity/User"; /** * Description 用户相关控制器 */ export default class UserController { @apiRequestMapping("get", "/users") @apiDescription("get all users list") @apiResponse(200, "get users successfully", [User]) static async getUsers(ctx, next): [User] { ... } @apiRequestMapping("get", "/user/:id") @apiDescription("get user object by id, only access self or friends") @pathParameter({ name: "id", description: "user id", type: "integer" }) @queryParameter({ name: "tags", description: "user tags, for filtering users", required: false, type: "array", items: ["string"] }) @apiResponse(200, "get user successfully", User) static async getUserByID(ctx, next): User { ... } @apiRequestMapping("post", "/user") @apiDescription("create new user") @bodyParameter({ name: "user", description: "the new user object, must include user name", required: true, schema: User }) @apiResponse(200, "create new user successfully", { status_code: "200" }) static async postUser(): number { ... } }
在对接口注解的时候,我们需要用实体类指明返回值或者请求体中包含的参数信息,因此我们也需要使用 swagger-decorator 提供的 entityProperty 注解来为实体类添加描述。值得一提的是,这里我们支持直接将 Object 作为描述对象的返回值,算是避免了 Java 中的一大痛点。
// @flow import { entityProperty } from "swagger-decorator"; /** * Description 用户实体类 */ export default class User { // 编号 @entityProperty({ type: "integer", description: "user id, auto-generated", required: false }) id: string = 0; // 姓名 @entityProperty({ type: "string", description: "user name, 3~12 characters", required: true }) name: string = "name"; // 朋友列表 friends: [number] = [1]; // 属性 properties: { address: string } = { address: "address" }; }
对于没有添加注解的属性,swagger-decorator 会自动根据其默认值来推测类型。然后我们就可以正常地启动应用,swagger-decorator 已经自动地为 router 对象添加了两个路由,其中 /swagger 指向了 Swagger UI:
而 /swagger/api.json 指向了 Swagger 生成的 JSON 文档:
欢迎有兴趣的朋友提出 ISSUE、指导意见或者希望纳入的特性。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/83519.html
摘要:中基于的自动实体类构建与接口文档生成是笔者对于开源项目的描述,对于不反感使用注解的项目中利用添加合适的实体类或者接口类注解,从而实现支持嵌套地实体类校验与生成等模型生成基于的接口文档生成等等功能。 JavaScript 中基于 swagger-decorator 的自动实体类构建与 Swagger 接口文档生成是笔者对于开源项目 swagger-decorator 的描述,对于不反感使...
摘要:前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点分为新闻热点开发教程工程实践深度阅读开源项目巅峰人生等栏目。对该漏洞的综合评级为高危。目前,相关利用方式已经在互联网上公开,近期出现攻击尝试爆发的可能。 前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点;分为新闻热点、开发教程、工程实践、深度阅读、开源项目、巅峰人生等栏目。欢...
摘要:其标准为前身是,提供强大的在线编辑功能,包括语法高亮错误提示自动完成实时预览,并且支持用户以格式撰写导入导出转换文档。 团队内部RestAPI开发采用设计驱动开发的模式,即使用API设计文档解耦前端和后端的开发过程,双方只在联调与测试时耦合。在实际开发和与前端合作的过程中,受限于众多因素的影响,开发效率还有进一步提高的空间。本文的目的是优化工具链支持,减少一部分重复和枯燥的劳动。 现状...
摘要:前端日报精选常用实例的实现与封装实现一个构建基于的可扩展应用规范翻译从到中文开源中国两级缓存实践掘金中基于的自动实体类构建与接口文档生成某熊的全栈之路继承总结教程中的五种组件形式掘金再说的问题前端开发前端每周清单第期正式 2017-07-18 前端日报 精选 javascript常用实例的实现与封装实现一个 SwiperRekit 2.0 构建基于React+Redux+React-r...
摘要:请注意,截至目前版本,用于的集成仍处于孵化阶段,并且存在一些严重的错误和缺少的功能例如,请参阅此处和此处。响应可以使用和注解来调整不同的响应状态及其有效结论允许您在创建数据库驱动的时产生快速结果。 原文: Documenting a Spring Data REST API with Springfox and Swagger 使用Spring Date REST,你可以迅速为Spr...
阅读 3448·2019-08-30 15:55
阅读 2050·2019-08-30 15:44
阅读 1453·2019-08-30 12:47
阅读 740·2019-08-30 11:05
阅读 1629·2019-08-30 10:54
阅读 654·2019-08-29 16:07
阅读 3566·2019-08-29 14:17
阅读 2221·2019-08-23 18:31