通过docsify实现接口文档

0、说在前面:

之前使用了apidoc技术生成的接口文档,但是总有多种不便,如:

  • 框架束缚太严重,改动源码成本太高。
  • 文档的模板较为固定,难以对文档做自定义的保存。
  • 由于数据的规范问题,对个别接口字段的数据读取有误,难以数据保证100%的准确性。

继而转向使用docsify技术。

理由如下:

APIDOCdocsify
文档形式data.js—>htmlMarkdown—>html,未来可兼容飞书文档
新增内容显示固定模板,额外新增字段需要改源码直接修改.md,所见即所得。
加载速度稍慢:生成的json文件转js文件包很快:生成Markdown之日,就是html完成之时。
搜索功能支持目录支持目录+正文
数据兼容性不规范的数据类型,需修改源码匹配规则支持任何类型
数据准确性有个别数据排序不准确文档支持任何类型
扩展性第三方插件多
版本对比versiong控制,对比清晰无法进行对比

高德地图api

https://lbs.amap.com/api/webservice/guide/api/search

1、使用docsify生成接口文档

sa-doc

一个基于markdown的接口文档编写工具,这里没有使用原生docsify,采用开源二次开发后的sa-doc,但框架格式和书写语法都是一样的。

  • 基础框架基于:docsify
  • 书写格式参考:apidoc
  • 根据markdown格式编写api接口文档,写时方便
  • 自动将markdown格式转换为表格形式,看时方便

1.1、通过freemarker生成模板文件

FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 是一个Java类库。

1、增加pom依赖

<!-- 引入freemarker模板引擎的依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2、配置application.properties

# 是否开启thymeleaf缓存,本地为false,生产建议为true
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.allow-request-override=false
spring.freemarker.check-template-location=true
    
#类型
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
    
#文件后缀
spring.freemarker.suffix=.ftl
#路径
spring.freemarker.template-loader-path=classpath:/templates/

3、定义模板文件

apidoc_md.ftl


## ${moduleName} | ${pageName}

<#list tables as table>

---

### ${table.actionName}
**请求类型**:  `${table.method}`&emsp;&emsp;**接口类型**:  `${table.interfaceType}`&emsp;&emsp;**版本号**:  `${table.version}`&emsp;**协议号**: `${table.protocolNo}`&emsp;&emsp;**责任人**: `${table.owner}`

**接口描述**: `${table.description}`

**请求Url**:`${table.url}`

**请求参数**

| 变量名   | 备注       |  数据类型  | mock数据  | 是否必须 |
| -------- | ---------- | ------ | --------- | -------- |
<#list table.apiParamsList as apiParam>
| ${apiParam.field} | ${apiParam.description} | ${apiParam.type}  | ${apiParam.mock} |    ${apiParam.must}      |
</#list>

**响应数据**

<style>
    table th:first-of-type {
        width: 60%;
    }
    table th:nth-of-type(2) {
        width: 15%;
    }
    table th:nth-of-type(3) {
        width: 3%;
    }
    table th:nth-of-type(4) {
        width: 20%;
    }
    table th:nth-of-type(5) {
        width: 2%;
    }
</style>
| 变量名                | 备注                                | 数据类型                   | mock数据 | 是否必须 |
| --------------------- | ----------------------------------- | ---------------------- | -------- | -------- |
<#list table.apiSuccessList as apiSuccess>
| ${apiSuccess.field} | ${apiSuccess.description}| ${apiSuccess.type} | ${apiSuccess.mock}| ${apiSuccess.must} |
</#list>
</#list>

4、编写路由ApiDocController.java

重点代码已隐藏,只展示测试类的处理step,其实原理就是按照test.ftl的关键字将值来put到dataMap中,最后通过template.process将dataMap输出到out目录中。

    @RequestMapping(value = "/shareApiDoc", method = RequestMethod.GET)
    public Map<String, Object> shareApiDoc(@RequestParam(value = "actionId") int actionId) {

        // step1 创建freeMarker配置实例
        Configuration configuration = new Configuration();
        Writer out = null;
        try {
            // step2 获取模版路径
            configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
            // step3 创建数据模型
            Map<String, Object> dataMap = new HashMap<String, Object>();
            //assemble apidoc base info
            dataMap.put("apiVersion", apiVersion);
            dataMap.put("method", requestType);
            dataMap.put("url", actionInfo.getRequestUrl());
            dataMap.put("title", actionInfo.getName());
            dataMap.put("group", page.getName());
            dataMap.put("description", actionInfo.getDescription());
            //get apiParamsList
            List<ApiParam> apiParams = new ArrayList<>();
            dataMap.put("apiParamsList", apiParams);
            //get apiSuccessList
            List<ApiParam> apiSuccess = new ArrayList<>();
            dataMap.put("apiSuccessList", apiSuccess);
            // step4 加载模版文件
            Template template = configuration.getTemplate("test.ftl");
            // step5 生成数据 output to apisrc directory
            File docFile = new File(fileSrc.getPath() + "/" + actionInfo.getName() + nowTime + ".java");
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
            template.process(dataMap, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != out) {
                    out.flush();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return null;
    }

1.2、将生成的md文件渲染成网页

上面的步骤简单说就是通过模版生成了markdown格式的文件,接下来要把文件中的数据渲染成网页。

  • 将生成的markdown文件放在project目录下。
  • 将umeapi_doc目录放置到tomcat上。
  • 通过127.0.0.1/umeApi-doc/index.html#/project/share631-2122-10528来访问在线文档

后续规划

多接口文档的分享功能

整个项目接口的分享功能