基于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.rhkb.cn/news/168801.html

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

相关文章

Xshell+screen解决ssh连接 服务器掉线的问题

Linux screen命令解决SSH远程服务器训练代码断开连接后运行中断_linux screen ssh-CSDN博客 Linux命令之screen命令_linux screen_恒悦sunsite的博客-CSDN博客 使用教程&#xff1a; 这里粗略介绍一下 &#xff08;1&#xff09;xshell xftp&#xff08;xshell点这个&#…

解救Kubernetes混乱:Descheduler快速实现资源平衡

By default, Kubernetes doesn’t recompute and rebalance workloads. You could have a cluster with fewer overutilized nodes and others with a handful of pods How can you fix this? 关注【云原生百宝箱】公众号&#xff0c;快速掌握云原生 默认情况下&#xff0c;Ku…

Linux_API_系列-整体概览

总论 Linux下API编程不像Windows一样&#xff0c;对每种设备和不同功能都有统一的API&#xff0c;所以有了《Windows核心编程》这种导论一类的大而全的书籍&#xff0c;整本书厚的像一块砖头。 Linux下贯彻了一贯的“一切皆文件”的宗旨&#xff0c;所以对于系统编程而言&…

RabbitMQ相关的其他知识点

RabbitMQ相关的其他知识点 一、幂等性1.1 概念1.2 消息重复消费1.3 消费端的幂等性保障 二、优先队列2.1 应用场景2.2 实现原理2.3 代码实现 三、惰性队列3.1 定义3.2 应用场景3.3 两种设置模式3.4 内存开销对比 一、幂等性 1.1 概念 用户对于同一操作发起的一次请求或者多次请…

初识JAVA,带你入门

本章重点&#xff1a; 1. Java语言简介、发展概述、语言优势、与C/C区别 2. 初识Java程序入口之main方法 3. 注释、标识符、关键字 1. Java语言概述 1.1 Java是什么&#xff1f; Java是一种优秀的程序设计语言&#xff0c;它具有令人赏心悦目的语法和易于理解的语义…

操作系统学习笔记7-IO管理

文章目录 1、IO管理学什么(学习逻辑图)2、IO管理硬件知识-IO设备的分类(硬件分类)3、IO管理硬件知识-IO控制方式的发展过程4、IO管理硬件知识-IO控制方式-程序直接控制方式5、IO管理硬件知识-IO控制方式-中断控制方式6、IO管理硬件知识-IO控制方式-DMA控制方式7、IO管理硬件知识…

中心胖AP(AD9430DN)+远端管理单元RU(R240D)+出口网关,实现组网

适用于&#xff1a;V200R008至V200R019C00版本的万兆中心胖AP&#xff08;AD9431DN-24X&#xff09;。 组网规划 RU管理&#xff1a;VLAN 100&#xff0c;网段为192.168.100.0/24。 无线业务&#xff1a;VLAN 3&#xff0c;SSID为“wlan-net”&#xff0c;密码为“88888888”…

安卓富文本部分高亮及点击事件

安卓富文本部分高亮及点击事件 前言一、富文本是什么&#xff1f;二、实现方法1.使用html2.使用SpannableString 总结 前言 富文本其实不是很常用&#xff0c;但有遇到了过后使用很方便的场景&#xff0c;例如免责声明。这时候就很重要了&#xff0c;前段时间遇到了&#xff0…

软件测试(概念篇)

前言 从这篇博客开始&#xff0c;我们将开始正式学习测试&#xff0c;在开始第一次软件测试之前&#xff0c;我们需要先了解软件测试的一些基本概念。 这些基本概念将帮助我们更加明确工作的目标&#xff0c;以便于更快的融入到测试团队中去   在这里我们将回答以下问题&…

vue v-for

目录 前言&#xff1a;Vue.js 中的 v-for 指令 详解&#xff1a;v-for 指令的基本概念 用法&#xff1a;v-for 指令的实际应用 1. 列表渲染 2. 动态组件 3. 表单选项 4. 嵌套循环 5. 键值对遍历 解析&#xff1a;v-for 指令的优势和局限性 优势&#xff1a; 局限性&a…

希捷推出Exos系列24TB硬盘:配备增强型缓存 性能提高三倍

希捷推出了全新的Exos 24TB硬盘。其基于传统的CMR构建&#xff0c;为3.5英寸规格&#xff0c;转速为7200 RPM。 同时&#xff0c;Exos系列24TB硬盘拥有10片磁盘&#xff0c;每片磁盘的容量为2.4TB&#xff0c;是希捷存储密度最高的硬盘&#xff0c;适用于超大规模企业和数据中心…

s27.linux运维面试题分享

第一章 计算机基础和Linux安装 1.冯诺依曼体系结构组成部分 计算机硬件由运算器、控制器、存储器、输入设备和输出设备五大部分组成。2.Linux哲学思想(或Liunx基本原则、思想、规则) 一切都是一个文件&#xff08;包括硬件&#xff09;。小型&#xff0c;单一用途的程序。连…

贪心算法(1)--经典贪心算法

目录 一、活动安排问题 二、最优装载问题 三、分数背包问题 四、多机调度问题 一、活动安排问题 1、策略 活动安排问题&#xff1a;设有n个活动的集合E{1,2,...,n}&#xff0c;每个活动i都有一个使用该资源的起始时间和一个结束时间&#xff0c;且。如果选择了活动i则它在…

网络编程的学习初篇

网络原理初始 网络原理和网络编程[重要] 网络能够跨主机通信! 我们未来工作,很可能是成为后端开发工程师,写服务器,和客户端通信,肯定会涉及到网络. 网络初始 计算机网络的由来 ~~ 计算机网络这是计科相关专业最核心的专业课!!! 计算机是咋来的??最初是用来计算弹道导弹的轨…

Kubernetes技术与架构-Ingress Controller

Ingress Controller控制器是实现Ingress对象的定义的组件&#xff0c;也即网关&#xff0c;负责Kubernetes集群内流量的分发&#xff0c;Kubernetes可以运行多个Ingress Controller控制器实例&#xff0c;不同的Ingress定义可以使用不同的Ingress Controller控制器实现&#xf…

搞个微信小程序002:个人信息

新建一个用于&#xff0c;和001中一样&#xff0c;然后&#xff0c;就改掉两个文件&#xff1a; index.wxml: <view><!-- 头像区域 --><view class"top"><view class"user-img"><image src"/images/tx.png"><…

PostgreSQL 插件 CREATE EXTENSION 原理

PostgreSQL 提供了丰富的数据库内核编程接口&#xff0c;允许开发者在不修改任何 Postgres 核心代码的情况下以插件的形式将自己的代码融入内核&#xff0c;扩展数据库功能。本文探究了 PostgreSQL 插件的一般源码组成&#xff0c;梳理插件的源码内容和实现方式&#xff1b;并介…

mybatis写sql

批量查询 <select id"getPreIds" resultType"java.lang.String"parameterType"java.util.List">SELECT pre_batch_id FROM public.mine_data_quality_check_record WHERE deleted0<if test"list ! null">AND pre_batch…

codeshell安装配置

codeshell安装配置 1 注意事项1.1 Python版本问题 2 codeshell环境搭建2.1 codeshell使用软件各版本2.2 软件下载2.3 codeshell使用环境安装2.3.1 python-3.10.9-amd64.exe安装2.3.2 Anaconda3-2022.10-Windows-x86_64.exe安装2.3.3 创建环境2.3.4 Pytorch安装2.3.5 transforme…

C++初阶 入门(2)

目录 一、缺省函数 1.1什么是缺省函数 1.2为什么要有缺省函数 1.3使用缺省函数 1.4测试代码 二、函数重载 2.1什么是函数重载 2.2为什么要有函数重载 2.3什么情况构成函数重载 2.4函数重载例子及代码 三、引用 3.1什么是引用 3.2如何引用 ​3.3常引用(可略过) 3…