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


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

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

    源码功能分析

    定位Torna功能源码

    根据插件命令的名称,从 smart-doc-maven-plugin 项目找到 torna-restmaven插件命令定义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 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转换为对应的接口平台的对接接口数据格式,并推送过去 配置的读取方式可以自行拓展
            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,有需要的话创建自定义的插件。

  • 相关阅读:
    葡萄糖-聚乙二醇-阿奇霉素,Azithromycin-PEG-Glucose
    【EMC专题】案例:电源适配器传导超标,但接产品整机测试却正常?
    触觉智能分享-SSD20X实现升级显示进度条
    智能汽车的算力大战“开打”,高通、华为、英伟达入场谁会赢?
    在lua中新建内嵌库
    关于feign调用之间boolean类型的序列化问题
    RHCE(逻辑卷LVM,NFS服务)
    搭建知识库系统不难,选对工具很重要!
    零信任特权访问管理
    Redis--1.CentOS8安装redis服务器
  • 原文地址:https://blog.csdn.net/Azhuzhu_chaste/article/details/126954522