使用swagger-typescript-api

引言

前后端分离大致是这样的

  • 后端:控制层 / 业务层 / 数据操作层
  • 前端:控制层 / 视图层

前后端的控制层,实际上就是前后端接口的对接
前后端分离,实现了更好地解耦合,但也引入了接口对接的过程,这个过程常常是繁琐,容易产生错误的

于是引入了api接口文档,来解决这个事情,如果有一份事先约定好的接口文档,双方都按照这个来,就能实现完美的对接。(但这通常很难实现,无法预先知道需要什么接口,接口的参数,是一个反复修改的过程)

现在后端广泛采用swagger技术,能够在开发时,就能生成接口文档,并能便捷地测试接口

对前端来说,就可以根据后端项目的swagger文档,来设计前端的控制层,也就是通常的根目录下的api文件夹,将对接口的请求封装为功能函数(也是为了与视图层解耦)

// user.ts
export const getUserList = () => request.get('/user/list')

但其实,一个api函数也就是对应的一个后端接口,已经有了接口文档,为什么不能直接生成前端的控制层?

前端控制层函数看似简单,其实做到类型完备,函数提示清晰(参数类型,返回值类型,各种注释),是一个十分繁琐的过程

所以,just relax,这个过程交由swagger-typescript-api来完成吧

swagger-typescript-api

我并不是讲swagger-typescript-api教程,可以去github上看它的所有用法,我只是讲述一下我是如何使用它的

我的项目并不是一个大型前后端分离项目,仅仅是作为练手,用前后端分离的方式自己开发。如果适用于您,您可以往下看

swagger-typescript-api有两种使用方式:命令行 & node脚本程序
优缺点显然:前者方便,后者易定制

我将以命令行的方式

进入我的前端项目中,在shell中输入

npx swagger-typescript-api -p http://localhost:8080/v2/api-docs?group=Manager -o ./src/api --axios --modular --module-name-index 1 --single-http-client
  • http://localhost:8080/v2/api-docs?group=Manager 我的swagger api文档地址
  • -o ./src/api 将生成的文件输出到src下的api目录下
  • --axios 采用axios客户端,默认fetch
  • --modular 分离http client, data constracts, 和routes,否则只会生成一个大文件
    • http client 这里就是axios客户端,对其进行了一定的封装
    • data constracts api接口中,用到的参数,或者返回值类型
  • --module-name-index 1 分离routes,意思是按api路径.split('/')[1]拆分接口文件

比如我有两个controller,UserController和DishController,访问UserController下的api,都是以/admin/user开头的,而访问DishController下的api,是以/admin/dish开头,所以这样做后,也就是按照后端的controller分离api接口文件了

  • --single-http-client 意为只有一个http客户端,稍后解释

于是在api文件夹下,生成了
在这里插入图片描述
这里swagger-typescript-api替我生成了除API.ts外的所有文件

如果直接使用的话,还是不太方便,因为每个controller都是一个http客户端

意味着我需要这么调用接口
new Category().getCategoryList()
new Dish().addDish()
当然,最重要的是,我们还需要对axios进行配置!

  • 比如添加baseUrl,当然它生成的http客户端默认为localhost:8080,但我们通常都会配置为环境变量,以便切换不同环境下的后端
  • 比如添加请求拦截器,向后端请求自动携带token认证信息
  • 比如添加响应拦截器,对产生的http错误,进行捕获和反馈(如show error message,告知unauthorized)

如果没有设置--single-http-client,产生的controller是这样的

class Employee<SecurityDataType = unknown> extends HttpClient<SecurityDataType>{...}

这样,你需要为每个controller的http客户端进行相同的配置,so dity!!!

但是,设置之后,产生controller是这样的

class Employee<SecurityDataType = unknown> {http: HttpClient<SecurityDataType>;constructor(http: HttpClient<SecurityDataType>) {this.http = http;}...
}

可以看到,前者是继承,后者是组合,也叫委派

但是,我们仍然需要为每个controller委派相同的http-client,所以我引入了API.ts来解决这个问题(这只是一个简单的示例)

class API<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {public category = new Category(this);public common = new Common(this);public dish = new Dish(this);public employee = new Employee(this);
}export const api = new API({paramsSerializer: (params) => qs.stringify(params, { indices: false }),baseURL: import.meta.env.VITE_APP_API_URL,
});api.instance.interceptors.request.use((config) => {if (getToken()) {config.headers["token"] = getToken();}return config;},(error) => {console.log(error);Promise.reject(error);}
);api.instance.interceptors.response.use((res) => {const code = res.data.code;const msg = res.data.msg || "系统未知错误,请反馈给管理员";if (res.request.responseType === "blob" ||res.request.responseType === "arraybuffer") {return res;}if (code !== 1) {message.error(msg);return Promise.reject(new Error(msg));} else {return res;}},(error) => {console.log("err" + error);let { message: msg } = error;if (msg === "Network Error") {msg = "后端接口连接异常";} else if (msg.includes("timeout")) {msg = "系统接口请求超时";} else if (msg.includes("Request failed with status code")) {// 获得异常http状态码const statusCode = +msg.substr(msg.length - 3);if (statusCode === 401) {Modal.confirm({title: "系统提示",content: "登录状态已过期,请重新登录",okText: "确定",onOk() {removeToken();location.href = "/";},});return Promise.reject("无效的会话,或者会话已过期,请重新登录。");}msg = "系统接口" + statusCode + "异常";}message.error(msg);return Promise.reject(error);}
);

进行封装后,我们可以更为优雅地调用api
api.category.getCategoryList()

Is it elegant ?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/140828.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT-3.5 插件推荐:语音输入,视频总结,联网检索

前言 GPT4 里是有内置的插件市场的&#xff0c;不过博主一直觉得自己对这个工具的使用还不够到位&#xff0c;现在购买升级版性价比不划算所以暂时还没有开。不过今天在学习使用的时候&#xff0c;发现 GPT3.5 也是可以通过网页插件方式进行升级扩展的&#xff0c;而且功能还比…

ChatGPT+Roblox,元宇宙的AI叙事逻辑#Leveling Up

MixCopilot 嗨&#xff0c;亲爱的听众朋友们&#xff01;欢迎收听我们的播客节目&#xff01;我是你们的主播&#xff1a;MixCopilot 混合副驾。今天我们要为大家带来的是我们的AI革命系列节目之一。这个系列节目聚焦于AI领域的一些最有影响力的建设者&#xff0c;他们将会讨论…

直播间自动发言机器人的运行分享,与开发需要到的技术分析

先来看实操成果&#xff0c;↑↑需要的同学可看我名字↖↖↖↖↖&#xff0c;或评论888无偿分享 一、引言 随着人工智能技术的不断发展&#xff0c;自动发言机器人已经成为了当今社交媒体领域的重要组成部分。它们能够自动化地发布内容、回复用户评论和消息&#xff0c;大大提高…

纯c语言模拟栈和队列(初学必看)

一、栈(Stack) 1.栈的概念及其结构 栈是一种特殊的线性表&#xff0c;在栈这个结构里&#xff0c;越先存进去的数据越难取出来。 这个结构就像是一个只有一端有打开的容器&#xff0c;越先放进去的球越在底部&#xff0c;想要把底部的球拿出来&#xff0c;就必须先把前面的求…

树莓派4B的测试记录(CPU、FFMPEG)

本文是用来记录树莓派 4B 的一些测试记录。 温度 下面记录中的风扇和大风扇是这样的&#xff1a; 为什么要用大风扇呢&#xff1f;因为小风扇在外壳上&#xff0c;气流通过外壳的珊格会有啸叫&#xff0c;声音不大但是很烦人&#xff0c;大风扇没这个问题&#xff0c;并且同样…

Vue3 数据响应式原理:Proxy和Reflect

我们在Vue2中使用的是Object.defineProperty方法来实现数据响应式的&#xff0c;可以通过get和set方法来监听对象的访问和修改。 但是并不能响应对象中属性的增加和删除&#xff0c;只能使用Vue.$set 和Vue.$delete 来对对象中的属性进行增加和删除。 数组也不能直接通过下标…

PyCharm因安装了illuminated Cloud插件导致加载项目失败

打开Pycharm时会有弹窗提示&#xff1a; The license for Illuminated Cloud is invalid or has expired. All Illuminated Cloud features will be disabled. 这个弹窗会导致你加载项目一直失败&#xff0c;close project 也关不掉&#xff0c;我都是用任务管理器杀死进程的…

Jmeter 性能 —— 负载阶梯场景!

1、安装阶梯测试的第三方插件->搜jpgc 选项-JMeter Plugins Manager -搜jpgc 空格&#xff0c;然后安装 2、脚本-线程组选jpgc Stepping Thread Group 最终并发数为100&#xff0c;并发数从0开始&#xff0c;5秒内增加10个并发数&#xff0c;增加10个后持续30s&#xff0c;…

taro(踩坑) npm run dev:weapp 微信小程序开发者工具预览报错

控制台报错信息&#xff1a; VM72:9 app.js错误: Error: module vendors-node_modules_taro_weapp_prebundle_chunk-JUEIR267_js.js is not defined, require args is ./vendors-node_modules_taro_weapp_prebundle_chunk-JUEIR267_js.js 环境&#xff1a; node 版本&#x…

Spring Boot(二)

1、运行维护 1.1、打包程序 SpringBoot程序是基于Maven创建的&#xff0c;在Maven中提供有打包的指令&#xff0c;叫做package。本操作可以在Idea环境下执行。 mvn package 打包后会产生一个与工程名类似的jar文件&#xff0c;其名称是由模块名版本号.jar组成的。 1.2、程序…

vue分片上传视频并转换为m3u8文件并播放

开发环境&#xff1a; 基于若依开源框架的前后端分离版本的实践&#xff0c;后端java的springboot&#xff0c;前端若依的vue2&#xff0c;做一个分片上传视频并分段播放的功能&#xff0c;因为是小项目&#xff0c;并没有专门准备文件服务器和CDN服务&#xff0c;后端也是套用…

2023NewStarCTF

目录 一、阳光开朗大男孩 二、大怨种 三、2-分析 四、键盘侠 五、滴滴滴 六、Include? 七、medium_sql 八、POP Gadget 九、OtenkiGirl 一、阳光开朗大男孩 1.题目给出了secret.txt和flag.txt两个文件&#xff0c;secret.txt内容如下&#xff1a; 法治自由公正爱国…

【Redis】list常用命令内部编码使用场景

文章目录 前置知识列表类型的特点 命令LPUSHLPUSHXRPUSHRPUSHXLRANGELPOPRPOPLINDEXLREMLINSERTLTRIMLSETLLEN 阻塞版本命令BLPOPBRPOP 命令总结内部编码测试内部编码 使用场景消息队列分频道的消息队列 模拟栈和队列 前置知识 列表类型是⽤来存储多个有序的字符串&#xff0c…

第一次实操Python+robotframework接口自动化测试

目前我们需要考虑的是如何实现关键字驱动实现接口自动化输出&#xff0c;通过关键字的封装实现一定意义上的脚本与用例的脱离&#xff01; robot framework 的安装不过多说明&#xff0c;网上资料比较太多~ 实例&#xff1a;&#xff01;&#xff01;&#xff01;&#xff01…

AI:80-基于深度学习的医学图像分割与病变识别

🚀 本文选自专栏:人工智能领域200例教程专栏 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的代码,详细讲解供大家学习,希望可以帮到大家。欢迎订阅支持,正在不断更新中,…

Flink SQL 表值聚合函数(Table Aggregate Function)详解

使用场景&#xff1a; 表值聚合函数即 UDTAF&#xff0c;这个函数⽬前只能在 Table API 中使⽤&#xff0c;不能在 SQL API 中使⽤。 函数功能&#xff1a; 在 SQL 表达式中&#xff0c;如果想对数据先分组再进⾏聚合取值&#xff1a; select max(xxx) from source_table gr…

2022年06月 Python(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 Python中 print(“八进制{: o}”.format(12)) 正确的输出结果是?( ) A: 八进制:O B: 八进制:O14 C: 八进制14O D: 八进制14 答案:D 字符串的format()格式。 第2题 下列的程…

pychon/PIL/opencv/json学习过程中遇到的问题

1. 使用PIL.Image读取图片 注意&#xff1a;pytorch中对图像预处理是transforms的输入必须是PIL格式的文件&#xff0c;使用cv2读取的图片就按照第二条的代码处理&#xff08;3通道合并、归一化处理&#xff09; from PIL import Image img Image.open("test1.jpg"…

2023 年最新企业微信官方会话机器人开发详细教程(更新中)

目标是开发一个简易机器人&#xff0c;能接收消息并作出回复。 获取企业 ID 企业信息页面链接地址&#xff1a;https://work.weixin.qq.com/wework_admin/frame#profile 自建企业微信机器人 配置机器人应用详情 功能配置 接收消息服务器配置 配置消息服务器配置 配置环境变量…

如何利用 cpolar 内网穿透技术实现 U8 用友 ERP 异地访问

文章目录 前言1. 服务器本机安装U8并调试设置2. 用友U8借助cpolar实现企业远程办公2.1 在被控端电脑上&#xff0c;点击开始菜单栏&#xff0c;打开设置——系统2.2 找到远程桌面2.3 启用远程桌面 3. 安装cpolar内网穿透3.1 注册cpolar账号3.2 下载cpolar客户端 4. 获取远程桌面…