使用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;他们将会讨论…

web网站 固定的邀请码字符 能被爬虫爬取吗?动态改变邀请码的字符是不是可以避免爬虫爬取或数据泄露

无论邀请码字符是固定的还是动态改变的&#xff0c;都无法完全避免爬虫爬取或数据泄露的风险。以下是一些要考虑的因素&#xff1a; 爬虫技术的发展&#xff1a;爬虫技术不断发展&#xff0c;可以智能地解析和获取网页内容。即使邀请码字符是固定的&#xff0c;高级爬虫仍然可以…

Linux - 驱动开发 - watchdog - SMP机制下多核确活

说明 理论上&#xff1a;不管IC是单核还是多核&#xff0c;只要watchdog有被循环feed&#xff0c;就不会触发超时重启&#xff0c;因此watchdog在SMP机制下的多核环境显得比较宽松&#xff0c;只要任意核存活&#xff08;喂狗&#xff09;就不会重启设备。 实际情况 有客户反…

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

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

【数据结构】栈和队列的模拟实现(两个方式实现)

前言 &#x1f493;作者简介&#xff1a; 加油&#xff0c;旭杏&#xff0c;目前大二&#xff0c;正在学习C&#xff0c;数据结构等&#x1f440; &#x1f493;作者主页&#xff1a;加油&#xff0c;旭杏的主页&#x1f440; ⏩本文收录在&#xff1a;再识C进阶的专栏&#x1…

Qt绘制简单图表

Qt图表类似于model/view&#xff0c;chart就是model。 创建图表的各个部件&#xff1a; QChart *chart new QChart();chart->setTitle(tr("简单函数曲线")); // chart->setAcceptHoverEvents(true);ui->chartView->setChart(chart);ui->chartVi…

网络安全自学

前言 一、什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防…

springboot---pom.xml

<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 https://…

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

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

C#8.0本质论第十二章--泛型

C#8.0本质论第十二章–泛型 C#通过泛型来促进代码重用&#xff0c;在词义上等价于C模板。 在泛型编程中&#xff0c;数据类型也是一种参数。 12.1如果C#没有泛型 为object的方法使用值类型时&#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;…

学习c#的第十天

目录 C# 字符串&#xff08;String&#xff09; 创建 String 对象 String 类的属性 String 类的方法 实例 C#的string.Format格式化日期 C# 字符串&#xff08;String&#xff09; 创建 String 对象 可以使用以下方法之一来创建 string 对象&#xff1a; 1、通过给 St…

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; 法治自由公正爱国…