smart doc:自动生成接口文档拓展

2023-11-02

smart doc 作为一个接口文档生成工具,可以根据代码的java doc注释,生成接口文档。同时已经对接到Torna接口平台。

鉴于大家用的接口平台五花八门,Torna的功能可能不符合大家的需求,研究下是否可以基于smart doc,拓展功能对接其他接口平台

源码功能分析

定位Torna功能源码

根据插件命令的名称,从 smart-doc-maven-plugin 项目找到 torna-rest 的maven插件命令定义Mojo类 TornaRestMojo

以下即为命令执行入口代码

@Execute(phase = LifecyclePhase.COMPILE)
@Mojo(name = MojoConstants.TORNA_REST_MOJO, requiresDependencyResolution = ResolutionScope.COMPILE)
public class TornaRestMojo extends BaseDocsGeneratorMojo {

    @Override
    public void executeMojo(ApiConfig apiConfig, JavaProjectBuilder javaProjectBuilder) {
        try {
            TornaBuilder.buildApiDoc(apiConfig, javaProjectBuilder);
        } catch (Exception e) {
            getLog().error(e);
        }
    }
}

这里可以看到实现入口为 TornaBuilder.buildApiDoc, 继续跟踪到 smart-doc 项目下的 TornaBuilder

流程主要分为两步:通过buildApiDoc 生成接口文档,再转换数据结构,根据接口配置,推送到Torna

    /**
     * Only for smart-doc maven plugin and gradle plugin.
     *
     * @param config             ApiConfig
     * @param javaProjectBuilder ProjectDocConfigBuilder
     */
    public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
        config.setParamsDataToTree(true);
        DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
        builderTemplate.checkAndInit(config, true);
        ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
        IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
        List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
        apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
        // 将数据转换为Torna的接口格式 并推送到Torna去
        buildTorna(apiDocList, config, javaProjectBuilder);
    }

文档生成部分目前符合我们的需求,看看推送部分,也只是简单的层级数据转换和接口请求。

    /**
     * build torna Data
     *
     * @param apiDocs   apiData
     * @param apiConfig ApiConfig
     * @param builder   JavaProjectBuilder
     */
    public static void buildTorna(List<ApiDoc> apiDocs, ApiConfig apiConfig, JavaProjectBuilder builder) {
        TornaApi tornaApi = new TornaApi();
        tornaApi.setAuthor(StringUtil.isEmpty(apiConfig.getAuthor()) ? System.getProperty("user.name") : apiConfig.getAuthor());
        tornaApi.setIsReplace((apiConfig.getReplace() == null || apiConfig.getReplace()) ? 1 : 0);
        Apis api;
        List<Apis> groupApiList = new ArrayList<>();
        //Convert ApiDoc to Apis
        for (ApiDoc groupApi : apiDocs) {
            List<Apis> apisList = new ArrayList<>();
            List<ApiDoc> childrenApiDocs = groupApi.getChildrenApiDocs();
            for (ApiDoc a : childrenApiDocs) {
                api = new Apis();
                api.setName(StringUtils.isBlank(a.getDesc()) ? a.getName() : a.getDesc());
                api.setItems(buildApis(a.getList(), TornaUtil.setDebugEnv(apiConfig, tornaApi)));
                api.setIsFolder(TornaConstants.YES);
                api.setAuthor(a.getAuthor());
                api.setOrderIndex(a.getOrder());
                apisList.add(api);
            }
            api = new Apis();
            api.setName(StringUtils.isBlank(groupApi.getDesc()) ? groupApi.getName() : groupApi.getDesc());
            api.setAuthor(tornaApi.getAuthor());
            api.setOrderIndex(groupApi.getOrder());
            api.setIsFolder(TornaConstants.YES);
            api.setItems(apisList);
            groupApiList.add(api);

        }
        tornaApi.setCommonErrorCodes(buildErrorCode(apiConfig, builder));
        // delete default group when only default group
        tornaApi.setApis(groupApiList.size() == 1 ? groupApiList.get(0).getItems() : groupApiList);
        //Build push document information
        Map<String, String> requestJson = TornaConstants.buildParams(PUSH, new Gson().toJson(tornaApi), apiConfig);
        //Push dictionary information
        Map<String, Object> dicMap = new HashMap<>(2);
        List<TornaDic> docDicts = TornaUtil.buildTornaDic(DocUtil.buildDictionary(apiConfig, builder));
        if (CollectionUtil.isNotEmpty(docDicts)) {
            dicMap.put("enums", docDicts);
            Map<String, String> dicRequestJson = TornaConstants.buildParams(ENUM_PUSH, new Gson().toJson(dicMap), apiConfig);
            String dicResponseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(dicRequestJson));
            TornaUtil.printDebugInfo(apiConfig, dicResponseMsg, dicRequestJson, ENUM_PUSH);
        }
        //Get the response result
        String responseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(requestJson));

        //Print the log of pushing documents to Torna
        TornaUtil.printDebugInfo(apiConfig, responseMsg, requestJson, PUSH);

    }

最后结论

我们的可以完全复用接口文档生成的部分代码,然后将 List<ApiDoc> apiDocList 转换成我们需要的数据结构,融入到其他接口平台中去。不过这过程需要其他接口平台也提供这种接口推送,或者json及其他形式的数据导入。

只需要模仿TornaBuilder 进行拓展实现

以下为实现示例:

/**
 * 自定义文档生成接口推送
 *
 * @author azhuzhu 2022/9/20 15:13
 */
@Slf4j
public class CustomizeBuilder {

    /**
     * build controller api
     *
     * @param config config
     */
    public static void buildApiDoc(ApiConfig config) {
        JavaProjectBuilder javaProjectBuilder = JavaProjectBuilderHelper.create();
        buildApiDoc(config, javaProjectBuilder);
    }


    /**
     * Only for smart-doc maven plugin and gradle plugin.
     *
     * @param config             ApiConfig
     * @param javaProjectBuilder ProjectDocConfigBuilder
     */
    public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
        // 文档结构化数据生成部分完全复用
        config.setParamsDataToTree(true);
        DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
        builderTemplate.checkAndInit(config, true);
        ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
        IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
        List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
        apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
        // 将List<ApiDoc>转换为对应的接口平台的对接接口数据格式,并推送过去 配置的读取方式可以自行拓展
        customizeBuild(apiDocList, config, javaProjectBuilder);
    }

    private static void customizeBuild(List<ApiDoc> apiDocs, ApiConfig apiConfig, JavaProjectBuilder builder) {
        String bodyJson = buildBodyJson(apiDocs, apiConfig, builder);
        String responseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), bodyJson);
        log.debug(responseMsg);
    }

    private static String buildBodyJson(List<ApiDoc> apiDocs, ApiConfig apiConfig, JavaProjectBuilder builder) {
        // TODO: 实现数据结构的转换 返回Json
        return "";
    }

}

新建一个项目,引入smart-doc-maven-plugin 作为依赖,如上面代码所示实现自定义的builder,有需要的话创建自定义的插件。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

smart doc:自动生成接口文档拓展 的相关文章

  • import java 导入错误:没有名为 java 的模块

    我似乎遇到了障碍 根本无法解决这个问题 任何人都可以帮我弄清楚为什么我无法导入 java 模块吗 Error Traceback most recent call last File datasource config py line 3
  • Maven项目中的HDF5

    我正在尝试将 hdf hdf5lib H5 导入到 NetBeans 中的 Maven 项目中 它有这个作为导入行 import hdf hdf5lib H5 正如这里所建议的 https support hdfgroup org prod
  • 在 JList 中写一些东西

    嘿 我还有另一个问题 我创建JList在我的主窗口中 现在我想向其中添加一些内容 我这样做 private void jButton2ActionPerformed java awt event ActionEvent evt Dodaj
  • 如何在 Java 中复制对象?

    考虑下面的代码 DummyBean dum new DummyBean dum setDummy foo System out println dum getDummy prints foo DummyBean dumtwo dum Sys
  • Jboss EAP 7 - 如何从部署中排除隐式模块(javax.jms)?

    我没想到我会来到这里 但经过大量 Google 和 StackOverflow 搜索后 我来到了这里 这就是我的确切问题 https www linkedin com pulse tale two jars marco antonio al
  • 在 alpine / Jprofile 10 中运行 jpenable 时出现 UnsatisfiedLinkError

    当运行 jpenable 以允许在运行 JDK 8 的 alpine 3 3 容器中对 Jprofiler10 进行分析时 我收到 UnsatisfiedLinkError 异常 有任何想法吗 ERROR The agent could n
  • 简单的Java程序插入USB热点后速度慢100倍

    我有以下Java程序 class Main public static void main String args throws java io IOException long start System nanoTime java io
  • 竞争条件和 Clojure Atoms

    clojure atom 的文档指出 Changes to atoms are always free of race conditions 然而 竞争条件不仅是根据更改定义的 而且是在不同线程中并行逻辑操作的上下文中定义的 我想知道 保证
  • String.intern() 线程安全吗

    我想在Java中使用 String intern 来节省内存 对具有相同内容的字符串使用内部池 我从不同的线程调用这个方法 这是个问题吗 对你的问题的简短回答是肯定的 它是线程安全的 但是 您可能需要重新考虑使用此工具来减少内存消耗 原因是
  • 更改JavaFX TableView字体大小[重复]

    这个问题在这里已经有答案了 您好 我想在表视图列内的文本上设置字体 我如何用 Java 做到这一点 这是我的代码 感谢帮助 private final TableView
  • SFTP Java - 管道关闭 Jsch 异常

    我正在研究一种 java 方法 将文件从一个位置复制到另一个远程位置 我的代码如下 我尝试使用jsch 0 1 42 0 1 50 0 1 54 public static void processFiles ArrayList
  • 为什么我无法使用 HttpUrlConnection 上传第一个文件块?

    在我的项目中 我应该从一台服务器逐块下载文件 并将每个块立即上传到另一台服务器 我有一个应该下载的文件的 URL 我们就这样称呼它吧downloadUrl 因此 这就是我逐块下载文件的方式 val chunkSize 1024 1024 B
  • Spring Boot 中的服务限流能力

    有什么办法可以实现Spring中其余服务的服务限制能力 特别是Spring boot 这里的期望是 我的服务暴露于外界 目前每秒 分钟的服务调用数量没有限制 我们希望通过设置限制来控制这一点 我有一个替代选项 通过跟踪并发哈希映射或任何缓存
  • jasper 报告文件中出现错误

    首先 我在 iReport 5 1 0 中创建一个 R D1 jrxml 文件 我执行该报告的 Java 代码如下所示 import java sql Connection import java sql DriverManager imp
  • 致命异常:OkHttp 调度程序

    我在 Android 应用程序中使用 OkHttp 库向天气 API 发出 Web 请求 我已经实现了我的代码 但在执行请求时遇到了致命异常 我也已经在我的清单中添加了互联网权限 MainActivity java private Curr
  • 如何预先填充 JFileChooser 将“文件名”?

    我打算用数据库中的名称填充 JFileChooser 但使用标准 JFileChooser 对话框进行加载 删除 保存和另存为 我想给用户留下这样的印象 他们正在处理文件系统 而在后端使用数据库来保存更改 用户不应该能够浏览到不同的目录进行
  • 为什么找不到 getservletcontext?

    我正在尝试使用getServletContext getRealPath 但我不断收到此错误 cannot find symbol symbol method getServletContext location interface jav
  • 原子整数的compareandexchange()与compareandset()

    在研究 AtomicInteger 时 我发现这个 API 提供了两种方法 比较和交换 如果当前值被引用 则自动将该值设置为 newValue to 作为见证值 预期值 记忆效应为 由指定VarHandle compareAndExchan
  • CreateProcess error=206,运行 gwtCompile 时文件名或扩展名太长

    我的应用程序是一个 springboot gradle 应用程序 我的应用程序的一部分涉及使用 gradle 进行遗留 gwt 编译 它工作正常 但今天当我运行下面的 gradle 任务时 它显示 CreateProcess error 2
  • 找出对象列表中是否包含具有指定字段值的内容?

    我有一个从数据库收到的 DTO 列表 它们有一个 ID 我想确保我的列表包含具有指定 ID 的对象 显然 在这种情况下创建具有预期字段的对象不会有帮助 因为 contains 调用 Object equals 并且它们不会相等 我想出了这样

随机推荐

  • 【疑难杂症】vmware虚拟机提示“该虚拟机似乎正在使用中”,并且无法获取所有权解决办法(三步解决虚拟机vmware提示正在使用中的问题)

    目 录 一 背景介绍 二 解决步骤 三 原因说明 四 参考文献 一 背景介绍 最近公司机房意外出现断电 机房的服务器来不及手动关机也都 啪唧 一下突然下了电 于是乎服务器上的vmware虚拟机因为异常中断 出现了如下异常 虚拟机上出现红色叉
  • windows和Linux下用qt开发串口调试助手

    windows下开发串口调试助手 当在Windows环境下使用Qt开发串口调试助手时 可以使用Qt的串口模块 QSerialPort 来实现串口通信功能 下面是一个简单的代码示例 详细说明了如何使用Qt开发串口调试助手 首先 需要在Qt项目
  • rtmp/rtsp/hls公网真正可用的测试地址

    相信大家在调试播放器的时候 都有这样的困惑 很难找到合适的公有测试源 以下是大牛直播SDK GitHub地址 整理的真正可用的直播地址源 其中 rtmp和rtsp的url 用我们播放器验证通过 1 rtmp 58 200 131 2 193
  • Forster论文预积分难理解部分推导(不定期更新)

    预积分 横线上面是今早泡泡机器人推送的推导过程 完全摘抄了下来 但这个式4 1到下一步却很晦涩 下面是详细推导
  • Python获取 只因 弹幕数据+制作词云分析.........就差唱、跳、rap不会了

    人生苦短 我用python 最近在小破站热门上看见了这个 不得不说还是挺不一样的 对吧 什么你说不是 哎呦 你干嘛 咳咳 话不多说 让我们一起来康康 基本开发环境 Python 3 6 Pycharm 相关模块的使用 requests re
  • HTML浮动窗口效果

    因项目中弹出窗口用的是thickbox 但是这个插件不支持多次层级弹出 但是需求需要实现的功能又是在弹出窗口中再次用一个弹出窗口展示效果 就想到了用浮动窗口效果 直接上代码 点击按钮弹出浮动窗口
  • 代码随想录算法训练营day1~18总结

    时间 空间复杂度 解题过程中运用的函数补充说明 数组 day1 http t csdn cn dBSgY day2 http t csdn cn JTDvH 数组总结 链表 day3 http t csdn cn mJx9V day4 ht
  • PAT乙级刷题之路1055 集体照 (25分)

    1055 集体照 25分 拍集体照时队形很重要 这里对给定的 N 个人 K 排的队形设计排队规则如下 每排人数为 N K 向下取整 多出来的人全部站在最后一排 后排所有人的个子都不比前排任何人矮 每排中最高者站中间 中间位置为 m 2 1
  • 动态修改 MeshCollider

    借鉴 https www cnblogs com imteach p 10348744 html using System Collections Generic using UnityEngine RequireComponent typ
  • 关于超参数调优及迁移学习的一些见解

    前言 最近看了一本书 TensorFlow 实战google深度学习框架 其中里面的在第6章中的6 5 2这个小结中 里面有这样的一个代码 具体我就不贴了 总之就是先通过图片数据输入成一个 npy文件 然后通过这个npy文件来输入到模型中
  • 4.20/21实习总结:k8s

    文章目录 什么是k8s 是个软件系统 容器集群管理工具 提供了应用部署 规划 更新 维护的一种机制 1 k8s组件 2 k8s对象 都可以在yaml文件中作为一种API类型来配置 3 namespace名称空间 通过名称空间在同一个物理集群
  • Android开发技巧(三)—— 创建定时任务

    每种手机都有自己的休眠策略 Android手机在长时间不操作时会自动让CPU进入睡眠状态 这就导致JAVA原生Timer的定时任务无法运行 所以我们需要借助Alarm唤醒CPU 一 Alarm机制 Alarm借助了AlermManager类
  • React 常用生命周期函数

    文章目录 React 生命周期图示 创建 constructor render componentDidMount 更新 render componentDidUpdate prevProps prevState 卸载 componentW
  • P2597 [ZJOI2012]灾难【支配树】

    题目链接 这是一道支配树的模板题了 然后写一下我初见支配树的理解 第一次碰到支配树是在昨天的多校第三场的1002 当时我推了个拓扑排序加上LCA的求差 dp a dp b dp lca a b 来解这个问题 然后为了处理出来每个的dp值 我
  • caret教程10:随机森林示例

    我们今天给大家演示下caret包做随机森林分类的一个小例子 同时也给大家看看做预处理和不做预处理两种情况下的模型表现 加载R包和数据 rm list ls library caret Loading required package ggp
  • Jmeter分布式测试的各种坑

    第一坑 启动压力机的时候 直接 jmeter server 会报如下错误 错误原因 127 0 0 1是本机 一个回路地址 没有指定地址 正确的启动方式 启动命令加一个参数 IP地址写压力机对应的地址 jmeter server D jav
  • python爬虫之逆向破解_Python爬虫:一个反爬 JS 逆向分析的例子

    挺久没发爬虫相关的教程啦 今天给大伙分享一下关于网站反爬对请求参数值的加密分析例子 主要还是看看思路 定位加密点 在某网站中进行登录请求 简单抓下包 点击登录按钮之后 可以在浏览器的控制台中看到相关的请求 接着往下拉 可以看到 POST 请
  • 实时CPU设计

    Patmos with Chisel https github com t crest patmos
  • Wireshark使用详解

    文章目录 wireshark简介 抓包原理 抓包 抓包窗口介绍 封包详细信息 Packet Details Pane 过滤信息介绍 显示过滤 抓包过滤 高级功能 数据流追踪 wireshark简介 wireshark是捕获机器上的某一块网卡
  • smart doc:自动生成接口文档拓展

    smart doc 作为一个接口文档生成工具 可以根据代码的java doc注释 生成接口文档 同时已经对接到Torna接口平台 鉴于大家用的接口平台五花八门 Torna的功能可能不符合大家的需求 研究下是否可以基于smart doc 拓展