基于OpenAPI、freemarker动态生成swagger文档

前言

spring项目中可以使用springfox或者springdoc,通过写注解的方式生成swagger文档,下面介绍一种不写注解,动态生成swagger文档的方式,在某些场景会适用,例如接口是动态生成的,此时swagger就不能通过注解来生成了。


一、定义swagger模板

通过观察一个swagger文档的openapi结构,将其中需要动态替换的部分写成变量,生成freemaker的ftl模板。
通过点击swagger图示链接可以查看openapi的json结构。
在这里插入图片描述
修改一个json结构,生成一个ftl模板,将模板放在springboot项目的resources/static/data-service-swagger-templates下面

{"openapi": "3.0.3","info": {"title": "通用查询-[${interfaceName}]接口","description": "通用查询接口","version": "0.0.1"},"servers": [{"url": "${dataServicePrefix}","description": "Generated server url"}],"security": [{"secretHeader": []}],"paths": {"${url}": {"post": {"tags": ["数据服务-通用查询接口"],"summary": "通用查询接口","description": "通用查询接口,请求体采用统一数据结构","operationId": "getData2UsingPOST","requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DmoRequest"}}}},"responses": {"200": {"description": "OK","content": {"*/*": {"schema": {"$ref": "#/components/schemas/ResponseEntity"}}}},"201": {"description": "Created"},"401": {"description": "Unauthorized"},"403": {"description": "Forbidden"},"404": {"description": "Not Found"}}}}},"components": {"schemas": {"ResponseEntity": {"title": "ResponseEntity","type": "object","properties": {"desc": {"type": "string","description": "错误详细描述"},"message": {"type": "string","description": "如果为非200的返回,可以将此message提示给用户"},"requestURL": {"type": "string"},"stackTrace": {"type": "string","description": "后端的异常栈信息,如果过长,只截取前面一部分"},"status": {"type": "integer","description": "200:正常;401:未登陆;403:没有权限;400:请求参数校验失败;500:服务器内部错误","format": "int32"},"tookInMillis": {"type": "integer","description": "请求耗时","format": "int64"},"value": {"type": "object"}}},"DmoRequest": {"title": "DmoRequest","type": "object","properties": {"fulltextNode": {"$ref": "#/components/schemas/QueryNode"},"node": {"$ref": "#/components/schemas/QueryNode"},"pageNumber": {"type": "integer","description": "页码","format": "int32"},"pageSize": {"type": "integer","description": "每页条数","format": "int32"},"showColumns": {"uniqueItems": true,"type": "array","items": {"type": "string","description": "显示的列"}},"sorts": {"type": "array","items": {"$ref": "#/components/schemas/DmoSort"}}}},"QueryNode": {"title": "QueryNode","type": "object","description": "查询条件","properties": {"children": {"type": "array","items": {"$ref": "#/components/schemas/QueryNode"}},"data": {"$ref": "#/components/schemas/NodeData"},"type": {"type": "string","description": "节点类型","enum": ["AND", "LEAF", "OR", "ROOT"]}}},"NodeData": {"title": "NodeData","type": "object","description": "节点数据","properties": {"operator": {"type": "string","description": "操作符","enum": ["BETWEEN", "EQ", "EXISTS", "GE", "GT", "IN", "IS_NOT_NULL", "IS_NULL", "LE", "LIKE", "LT", "NE", "NOT_BETWEEN", "NOT_EXISTS", "NOT_IN", "NOT_LIKE", "PREFIX", "REGEXP"]},"param": {"type": "string","description": "参数名称,一般对应表的列名"},"value": {"type": "array","description": "参数值","items": {"type": "object"}}}},"DmoSort": {"title": "DmoSort","type": "object","description": "排序","properties": {"column": {"type": "string","description": "列名"},"sortOrder": {"type": "string","description": "排序方式","enum": ["ASC", "DESC"]}}}},"securitySchemes": {"secretHeader": {"type": "apiKey","name": "Authorization","in": "header"}}}
}

二、使用freemarker生成openapi的JSON结构

1.引入库

代码如下(示例):

<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.32</version>
</dependency>

2.生成json

下面的serviceInterface就是一个实体,可以自行定义

@ApiOperation(value = "获取openapi的JSON", notes = "获取openapi的JSON")@GetMapping("/swagger-json/{id}")public String getSwaggerJson(@ApiParam(value = "id") @PathVariable Integer id) throws BaseException {ServiceInterface serviceInterface = getServiceInterface(id);return getOpenApiJson(ServiceInterface serviceInterface, "test.ftl") ;}private String getOpenApiJson(ServiceInterface serviceInterface, String ftl) throws BaseException {freemarker.template.Configuration configuration = new 		freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_0);// 设置默认编码configuration.setDefaultEncoding("utf-8");//设置类加载器configuration.setClassLoaderForTemplateLoading(this.getClass().getClassLoader(), "data-service-swagger-templates");try {// 生成模板对象Template template = configuration.getTemplate(fileName);TEMPLATE_CACHE.put(fileName, template);} catch (Exception e) {throw new BaseException(String.format("获取模版文件:[%s]出错", fileName), e);}Template template = getFltTemplate(ftl);String dataServicePrefix = dataServiceProtocol + dataServiceUpstream;Map<String, String> dataMap = new HashMap<>();dataMap.put("interfaceName", serviceInterface.getServiceName());dataMap.put("dataServicePrefix", dataServicePrefix);dataMap.put("url", serviceInterface.getUrl());StringWriter sw = new StringWriter();try {template.process(dataMap, sw);return sw.toString();} catch (Exception e) {throw new BaseException("模板转换出错:" + e.getMessage(), e);}}

三、前端生成swagger示例

<!DOCTYPE html>
<html><head><title>数据服务接口文档</title><link rel="stylesheet" type="text/css" href="swagger-ui.css"/></head><body><div id="swagger-ui"></div><script src="swagger-ui-bundle.js"></script><script>window.onload = function () {SwaggerUIBundle({// url: "http://localhost:14500/v3/api-docs", // 替换成您的OpenAPI规范的URL或文件路径//  url: "swagger-custom-select.json", // 替换成您的OpenAPI规范的URL或文件路径url: "http://192.168.33.22:3282/dmo/service-interface/swagger-json/226", // 替换成您的OpenAPI规范的URL或文件路径dom_id: "#swagger-ui",deepLinking: true,});};</script></body>
</html>

其中url 为第二步的接口

用到的css和js下载地址:https://blog.csdn.net/weixin_41085315/article/details/124965953

四、测试

在这里插入图片描述

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

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

相关文章

Qt中QFile、QByteArray QDataStream和QTextStream区别及示例

在Qt中&#xff0c;QFile、QByteArray、QDataStream和QTextStream是常用的文件和数据处理类。 主要功能和区别 QFile&#xff1a; QFile是用于读写文本和二进制文件以及资源的I/O设备。可以单独使用QFile&#xff0c;或者更方便地与QTextStream或QDataStream一起使用。 通常在…

Cookie和Session

前言扩展&#xff1a;笔者在之前学习前端扫盲阶段&#xff0c;写过一个简单易读的&#xff1a;表白墙项目&#xff0c;具体的前端代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta ht…

mac安装+配置python3环境

一、python3下载 官网下载 https://www.python.org/ 二、python3安装 打开下载好的.pkg文件一直继续确认即可。 三、验证是否安装成功 打开终端&#xff0c;输入python3&#xff0c;如果返回python对应的版本信息&#xff0c;则安装成功。 四、python配置 如果需要输入…

2023java攻克了抖音视频去水印视频下载

2023java攻克了抖音视频去水印视频下载 1、过滤链接 /*** 过滤链接&#xff0c;获取http连接地址* param url* return*/public static String decodeHttpUrl(String url) {int start url.indexOf("http");int end url.lastIndexOf("/");String decodeu…

基于卷积优化优化的BP神经网络(分类应用) - 附代码

基于卷积优化优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于卷积优化优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.卷积优化优化BP神经网络3.1 BP神经网络参数设置3.2 卷积优化算法应用 4.测试结果…

flash-linear-attention CUDA算子成功实现(但限制极多。。)

在 C/DirectX着色器 的基础上速成CUDA编程&#xff0c;还好思维模式基本通用&#xff0c;就多了线程组排布和共享内存方面的东西&#xff0c;入门还行&#xff0c;高级加速方面就不太行了。 代码仓库&#xff1a;https://github.com/One-sixth/flash-linear-attention-pytorch…

Qt窗体设计的布局

本文介绍Qt窗体的布局。 Qt窗体的布局分为手动布局和自动布局&#xff0c;手动布局即靠手工排布各控件的位置。而自动布局则是根据选择的布局类型自动按此类型排布各控件的位置&#xff0c;使用起来比较方便&#xff0c;本文主要介绍Qt的自动布局。 1.垂直布局 垂直布局就是…

内核驱动模块分布编译

内核驱动模块代码 #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include <linux/device.h> #include <linux/ioctl.h> #include <linux/cdev.…

Redis的开发利用

在Redis中&#xff0c;可以使用两个数据结构来实现阅读量和点赞量的计数。 1. 使用字符串来计数阅读量和点赞量 在Redis中&#xff0c;字符串类型的数据可以通过 INCR 和 DECR 命令来实现原子递增和递减。 例如&#xff0c;假设要对一篇文章进行阅读量统计&#xff0c;可以使…

基于WebRTC构建的程序因虚拟内存不足导致闪退问题的排查以及解决办法的探究

目录 1、WebRTC简介 2、问题现象描述 3、将Windbg附加到目标进程上分析 3.1、Windbg没有附加到主程序进程上&#xff0c;没有感知到异常或中断 3.2、Windbg感知到了中断&#xff0c;中断在DebugBreak函数调用上 3.3、32位进程用户态虚拟地址和内核态虚拟地址的划分 …

mysql 查询表字段名,注释 , 以及sql拼接查询出的内容

#sql查询字段名&#xff0c;注释操作拼接 #查询字段名和注释 select COLUMN_NAME,COLUMN_COMMENT from information_schema.COLUMNS where table_name 表名 and table_schema 库名 order by ordinal_position #查询整个内容 select * from information_schema.COLUMNS wh…

adb 获取当前界面元素

adb配置正确&#xff0c;直接看6&#xff0c;pull的位置是你执行pull的目录下。 --------------------------------------------------------------------------------------------------------------------------------- 使用adb命令获取当前应用的元素需要先连接到手机或模…

义乌再次位列第一档!2022年跨境电商综试区评估结果揭晓!

义乌跨境电商综试区捷报频传&#xff0c;在商务部公布的“2022年跨境电子商务综合试验区评估”结果中&#xff0c;中国&#xff08;义乌&#xff09;跨境电子商务综合试验区&#xff08;以下简称&#xff1a;“跨境综试区”&#xff09;评估结果为成效明显&#xff0c;综合排名…

C语言获取文件长度

C语言获取文件长度 文章目录 C语言获取文件长度一、使用标准库方法二、使用Linux系统调用 一、使用标准库方法 #include <stdio.h>long get_file_size(const char * filename ){long size 0;FILE * fp fopen(filename,"rb");if( fp NULL ) {printf("o…

【C++技能树】Lambda表达式

Halo&#xff0c;这里是Ppeua。平时主要更新C&#xff0c;数据结构算法&#xff0c;Linux与ROS…感兴趣就关注我bua&#xff01; 文章目录 0. Lambda表达式简介1. Lambda表达式2. Lambda表达式语法 0. Lambda表达式简介 在C98及之前,想要对sort进行自定义排序,或者对自定义类…

uniapp实现登录组件之外区域置灰并引导登录

实现需求 每个页面需要根据用户是否登录决定是否显示登陆组件,登录组件半屏底部显示,登录组件之外区域置灰,功能按钮点击之后引导提示登录.页面效果如下: 实现思路说明 设置登录组件背景颜色为灰色,将页面分成登录区域(底部)和非登陆区域(上面灰色显示部分), 置灰区域添加…

腾讯共享WiFi贴项目推广员是怎么收益的?

腾讯共享WiFi贴项目是一种非常普遍的商业共享模式&#xff0c;它为用户提供了便携、高速的无线网络服务。然而&#xff0c;人们对于这种项目是否真的能让共享WiFi贴推广员挣到钱还存在疑问。 腾讯共享WiFi贴扫码项目的运作方式是这样的&#xff1a;推广员将WiFi贴二维码粘贴到商…

kotling构造函数

Kotlin-继承与构造函数 - 简书 (jianshu.com) Kotlin语言中的继承与构造函数&#xff08;详解&#xff09;_kotlin 继承 构造函数_young螺母的博客-CSDN博客

Qt扫盲-QImage 理论总结

QImage 理论总结 一、概述二、读写图像文件三、图像信息四、像素操作1. 32位2. 8位 五、图像格式六、图像转换 一、概述 QImage类提供了一个独立于硬件的图像表示&#xff0c;允许直接访问像素数据&#xff0c;并且可以用作绘画设备。Qt提供了四个类来处理图像数据&#xff1a…

ES挂载不上怎么处理?

全文搜索 EelasticSearch安装 Docker安装 docker run -d --name es7 -e ES_JAVA_POTS"-Xms256m -Xmx256m" -e "discovery.typesingle-node" -v /home/206/es7/data/:/usr/share/elasticsearch/data -p 9200:9200 -p 9300:9300 elasticsearch:7.14.0 …