【Spring/Java项目】如何利用swagger-parser解析yaml中的api请求类型、注释、接口名等等(含示例代码)

news2024/11/15 17:43:30

手打不易,如果转摘,请注明出处!

注明原文:https://zhangxiaofan.blog.csdn.net/article/details/129167371


目录

前言

官方文档

项目配置

示例代码

测试文件

 解析代码

运行结果


前言

        用到这个工具是因为项目需要,本身项目比较多,swagger.yaml也很多,公司的管理平台无法直观的统计全部服务的yaml中的API,因此就用这个工具快速提取我们各个项目中的API信息,包括API名称、操作类型、请求类型等等。

官方文档

swagger-api 的使用官方文档:

https://github.com/swagger-api/swagger-parser

项目配置

pom.xml : 

        <dependency>
            <groupId>io.swagger.parser.v3</groupId>
            <artifactId>swagger-parser</artifactId>
            <version>2.1.12</version>
        </dependency>
        
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.3</version>
        </dependency>

示例代码

测试文件

测试文件名:

swagger-test1.yaml
swagger-test2.yaml

测试文件目录:

src/main/resources/swagger/test

 

第1个swagger文件:

src/main/resources/swagger/test/service1/swagger-test1.yaml

 第2个swagger文件:

src/main/resources/swagger/test/service2/swagger-test2.yaml

测试文件内容(方便测试,两个都是一样的):

swagger: '2.0'
info:
  title: ping test
  version: '1.0'
host: 'localhost'
basePath: /test
schemes:
  - "https"
tags:
  - name: TestManage
    description: 测试管理
paths:
  /some/ping:
    get:
      tags:
        - TestManage
      operationId: pingGet
      description: 一个测试方法
      parameters:
        - name: i
          in: body
          description: query字段
          required: true
          schema:
            $ref: './swagger/swagger-reference.yaml#/type'
      responses:
        '201':
          description: OK
  /some/ping2:
    post:
      tags:
        - TestManage
      operationId: pingPost
      description: 一个测试方法2
      parameters:
        - name: num
          in: query
          description: 数量
          required: true
          type: integer
          format: int32
      responses:
        '201':
          description: OK

 解析代码

package util;

import cn.hutool.core.util.ObjectUtil;
import io.swagger.parser.OpenAPIParser;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.parser.core.models.ParseOptions;
import io.swagger.v3.parser.core.models.SwaggerParseResult;
import lombok.extern.slf4j.Slf4j;

import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
public enum SwaggerParseUtl {
    ;

    /**
     * 待解析的文件目录
     */
    private static final String RESOURCE_DIRECTORY = "E:\\JavaProject\\local\\JavaCoreTest\\src\\main\\resources\\swagger\\test";

    public static void main(String[] args) {
        List<String> fileList = new ArrayList<>();
        // 读取所有的 yaml 文件
        getFileList(RESOURCE_DIRECTORY, ".yaml", fileList);
        // 依次解析 yaml 文件
        for (String file : fileList) {
            String[] split = file.replace("\\", "/").split("/");
            // 文件名
            String fileName = split[split.length - 1];
            // 这里的 swagger.yaml 按服务名存放
            String serviceName = split[split.length - 2];
            parseSwaggerYaml("swagger/test", serviceName, fileName);
        }
    }

    /**
     * 解析方法
     *
     * @param resourceRelativePath 目标文件在 resources 下的相对路径
     * @param serviceName          服务名
     * @param fileName             文件
     */
    public static void parseSwaggerYaml(String resourceRelativePath, String serviceName, String fileName) {
        String filePath = resourceRelativePath + "/" + serviceName + "/" + fileName;
        ParseOptions options = new ParseOptions();
        options.setResolve(true);
        SwaggerParseResult result = new OpenAPIParser().readLocation(filePath, null, options);
        OpenAPI openAPI = result.getOpenAPI();
        Paths paths = openAPI.getPaths();

        for (Map.Entry<String, PathItem> entry : paths.entrySet()) {
            // url path
            String path = entry.getKey();
            // api
            PathItem pathItem = entry.getValue();
            Operation api = getOperation(pathItem);
            // request type
            PathItem.HttpMethod method = getMethod(pathItem);
            // operationId
            String operationId = api.getOperationId();
            // 描述
            String description = "";
            if (!StringUtils.isEmpty(api.getDescription())) {
                description = api.getDescription();
            } else {
                description = api.getSummary();
            }
            String tag = "";
            if (!CollectionUtils.isEmpty(api.getTags())) {
                tag = api.getTags().get(0);
            }
            System.out.println(MessageFormat.format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}", serviceName, fileName,
                    method, path, tag, operationId, description));
        }
    }

    /**
     * 获取请求方法类型
     */
    private static PathItem.HttpMethod getMethod(PathItem pathItem) {
        Operation api = null;
        if (!ObjectUtil.isEmpty(pathItem.getGet())) {
            return PathItem.HttpMethod.GET;
        } else if (!ObjectUtil.isEmpty(pathItem.getPost())) {
            return PathItem.HttpMethod.POST;
        } else if (!ObjectUtil.isEmpty(pathItem.getPut())) {
            return PathItem.HttpMethod.PUT;
        } else if (!ObjectUtil.isEmpty(pathItem.getDelete())) {
            return PathItem.HttpMethod.DELETE;
        } else if (!ObjectUtil.isEmpty(pathItem.getPatch())) {
            return PathItem.HttpMethod.PATCH;
        } else {
            throw new RuntimeException("不支持的请求类型");
        }
    }

    /**
     * 获取 Operation Api
     */
    private static Operation getOperation(PathItem pathItem) {
        Operation api = null;
        if (!ObjectUtil.isEmpty(pathItem.getGet())) {
            api = pathItem.getGet();
        } else if (!ObjectUtil.isEmpty(pathItem.getPost())) {
            api = pathItem.getPost();
        } else if (!ObjectUtil.isEmpty(pathItem.getPut())) {
            api = pathItem.getPut();
        } else if (!ObjectUtil.isEmpty(pathItem.getDelete())) {
            api = pathItem.getDelete();
        } else if (!ObjectUtil.isEmpty(pathItem.getPatch())) {
            api = pathItem.getPatch();
        } else {
            throw new RuntimeException("不支持的请求类型");
        }
        return api;
    }


    /**
     * 递归遍历所有文件
     *
     * @param filePath 文件路径
     * @param suffix   指定的文件格式
     * @param fileList 获取的文件list
     */
    private static List<String> getFileList(String filePath, String suffix, List<String> fileList) {
        File root = new File(filePath);
        // 非目录
        if (!root.isDirectory()) {
            fileList.add(root.getAbsolutePath());
            return fileList;
        }
        // 目录则递归遍历
        File[] files = root.listFiles();
        if (null != files) {
            for (File file : files) {
                if (file.isDirectory()) {
                    // 递归xml
                    getFileList(file.getAbsolutePath(), suffix, fileList);
                } else if (file.getName().contains(suffix)) {
                    fileList.add(file.getAbsolutePath());
                }
            }
        }
        return fileList;
    }
}

运行结果

Connected to the target VM, address: '127.0.0.1:3983', transport: 'socket'
service1	swagger-test1.yaml	GET	/some/ping	TestManage	pingGet	一个测试方法
service1	swagger-test1.yaml	POST	/some/ping2	TestManage	pingPost	一个测试方法2
service2	swagger-test2.yaml	GET	/some/ping	TestManage	pingGet	一个测试方法
service2	swagger-test2.yaml	POST	/some/ping2	TestManage	pingPost	一个测试方法2
Disconnected from the target VM, address: '127.0.0.1:3983', transport: 'socket'

Process finished with exit code 0

后面可以直接复制这个结果到 excel 编辑,或者用 Java 代码直接写到 excel 中都可以!

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

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

相关文章

构造函数与成员变量初始化

1 为何需要定义构造函数&#xff1f; 构造函数的主要目的在于对成员变量进行初始化&#xff0c;确保类对象具有良好的初始状态。 2 构造函数对成员变量的初始化 接下来&#xff0c;我们将完善前文中提到的几个构造函数&#xff0c;使其能够有效地完成成员变量的初始化工作。 …

【趣说冒泡排序】

前言 在计算机科学中&#xff0c;排序算法是一种常见且重要的算法。排序算法的目标是将一组无序的数据按照一定的规则进行重新排列&#xff0c;以便更方便地进行搜索、查找或其他操作。 冒泡排序&#xff08;Bubble Sort&#xff09;是最简单的排序算法之一&#xff0c;它的原…

软件测试技能,JMeter压力测试教程,统一随机定时器/高斯随机定时器(十九)

目录 前言 一、统一随机定时器 1、统一随机定时器&#xff08;Uniform Random Timer&#xff09; 2、设置延迟时间 二、高斯随机定时器 1、高斯随机定时器Gaussian Random Timer 2、设置延迟时间 前言 如果想加个随机等待时间可以用到 jmeter 里面的统一随机定时器&…

WPF 样式设计总结

文章目录 行内样式页内样式样式继承控件样式只能继承一个 局部样式窗口控件和用户控件直接的区别使用代码用户控件引用 全局样式 行内样式 我们新建一个简单的样式 <Grid><TextBox Text"我是样式" FontSize"100" /></Grid>这种属性直接…

【QT】常用组件及其用法总结

前面我们看了如何用QT实现纯代码和纯Designer工具的图形化的页面设计&#xff0c;下面我们来看看如何用QT结合两者实现混合界面设计&#xff0c;主要是学习使用一些常用的组件。 目录 信号和槽 菜单栏、状态栏和工具栏 QLabel setGeometry Button pushbutton CheckBox…

SSMP整合案例(10) vue端调整项目环境 发送请求 基本界面编写

好 之前我们已经将后端服务整个写好了 然后 我们就继续回来写我们前端的项目 之前文章SSMP整合案例(1) 构建 Spring Boot Vue MySql项目环境中我们顺手搭建了前端的项目环境 我们打开它 在终端输入 npm i axios0.21.0引入 axios 它是一个专门用来发请求的第三方插件 一定要注…

Nginx(4)nginx的反向代理

反向代理 正向代理反向代理的常用指令反向代理实战 Nginx的安全控制使用SSL对流量进行加密nginx添加SSL的支持Nginx的SSL相关指令生成证书 反向代理系统调优 正向代理代理的对象是客户端&#xff0c;反向代理代理的是服务端&#xff0c;这是两者之间最大的区别。Nginx即可以实现…

Python实现发送电子邮件功能

大家好&#xff0c;以编程方式发送电子邮件可以成为自动化通信过程的一种强大方式&#xff0c;本文将探讨如何使用Python发送电子邮件&#xff0c;介绍如何设置SMTP服务器、为Gmail生成应用程序密码&#xff0c;并提供使用smtplib库发送电子邮件的逐步指南。 在深入研究编码之…

单链表【数据结构】

1、顺序表存在的问题 顺序表存在一些问题&#xff1a; &#xff08;1&#xff09;中间、头部的插入删除&#xff0c;时间复杂度为O(N)&#xff08;2&#xff09;增容需要申请新空间&#xff0c;拷贝数据&#xff0c;释放旧空间。会有不小的消耗。&#xff08;3&#xff09;增容…

剑指 Offer 42: 连续子数组的最大和

这道题多了第二句&#xff0c;并且作为nums[i]&#xff0c;当前值一定是要取的&#xff0c;只是要不要加上前面那个而已。

uniapp 之 uniapp app 与uniapp H5的通信 webview,以及处理H5页面的手机物理返回问题

目录 app给H5传参&#xff1a;通过h5地址传参app给H5传参&#xff1a;通过方法evalJS传参H5给app传参&#xff1a;通过web-view 组件的message绑定的方法处理H5页面的手机物理返回问题 APP端&#xff1a; <web-view :webview-styles"webviewStyles" :src"sr…

python学习之【继承、封装、多态】

#来评选你心中的TOP1编程语言# 前言 距离上篇文章 python学习之【类和对象】已有三个星期之久&#xff0c;这篇文章介绍 面向对象的三大特征——封装&#xff0c;继承&#xff0c;多态。 对于编程初学者来说&#xff0c;学习python应该是比较好入手的&#xff0c;文末会给大家…

计算机视觉:多相机硬件同步拍摄

计算机视觉&#xff1a;多相机硬件同步拍摄 传感器同步硬件同步信号FSYNC信号STROBE信号 硬件接线硬件设备接线步骤&#xff1a; 软件驱动参考文献 传感器同步 目前主要有两种方法来同步不同传感器的信息&#xff08;帧、IMU数据包、ToF等&#xff09;&#xff1a; 硬件同步&…

2023-07-01:redis过期策略都有哪些?LRU 算法知道吗?

2023-07-01&#xff1a;redis过期策略都有哪些&#xff1f;LRU 算法知道吗&#xff1f; 答案2023-07-01&#xff1a; 缓存淘汰算法&#xff08;过期策略&#xff09; 当Redis的内存超出物理内存限制时&#xff0c;内存中的数据就会频繁地与磁盘进行交换&#xff0c;这个过程…

二叉树的练习

文章目录 单值二叉树检查两颗树是否相同对称二叉树二叉树的前序遍历二叉树的中序遍历二叉树的后序遍历另一颗树的子树通过前序遍历的数组构建二叉树判断二叉树是否是完全二叉树层序遍历k层节点数二叉树的销毁二叉树的整体 单值二叉树 单值二叉树&#xff0c;可以使用等式的传递…

Java基础---有了基本类型为什么还需要包装类

目录 缘由 基本类型和包装类型的区别 如何理解自动拆装箱 哪些地方会自动拆装箱 自动拆装箱与缓存 缘由 Java中有8种基本数据类型&#xff0c;这些基本类型又都有对应的包装类 因为Java是一种面向对象语言&#xff0c;很多地方都需要使用对象而不是基本数据类型比如&…

Domino Admin管理客户机中为每个管理域设置不同的图标

大家好&#xff0c;才是真的好。 一直在讲Domino管理中的单个网络 域&#xff0c;很少讲到多个Domino网络域的管理。其实&#xff0c;很多企业会有多个Domino网络域。因为以前多个部门或组织、企业等合并&#xff0c;或者隔离国内和国外的目录隔开等等&#xff0c;都会产生多个…

从0-1手写一个RPC框架

前言 什么是RPC RPC&#xff08;Remote Procedure Call&#xff09;远程过程调用&#xff0c;简言之就是像调用本地方法一样调用远程服务。目前外界使用较多的有gRPC、Dubbo、Spring Cloud等。相信大家对RPC的概念都已经很熟悉了&#xff0c;这里不做过多介绍。 为啥要自己写…

nvm 和 nrm安装使用

前端工具推荐&#xff1a;nvm&#xff08;Node 版本管理工具&#xff09; 和 nrm&#xff08;管理npm源&#xff09;&#xff1a; 一、nvm 1.1 nvm 是什么 1.2 安装 nvm 1.3 使用 nvm 二、nrm 2.1 nrm 是什么 2.2 安装 nrm 2.3 使用 nrm 一、nvm 如果直接将 node 安装到…

20230701:成电的“七年之痒”,毕业啦

毕业那些事儿 毕业随笔写在最后 毕业随笔 伴随着走完最后一道流程&#xff0c;成电7年&#xff0c;总算是毕业了。经济下行&#xff0c;行业寒冬&#xff0c;全被90后赶上了&#xff0c;庆幸学校的金字招牌让自己斩获了不少OFFER。荒废了半年的跑步和博客计划&#xff0c;接下…