JApiDocs 增加导出 postman 格式插件,方便接口测试

之前写了在 JBolt 中集成 JApiDocs 的分享(传送门)。满足给前端对接接口人员查看 api 文档的需求。

有时后端或前端有执行接口的需求,看看返回值、验证下接口等。所以,需要导出 postman 格式文件,然后 import 到 postman 或类似 apifox、apipost 工具中。

好在 JApiDocs 提供了插件机制,直接上代码。

package com.hccx.common.japidocs;

import freemarker.template.Template;
import freemarker.template.TemplateException;
import io.github.yedaxia.apidocs.DocContext;
import io.github.yedaxia.apidocs.IPluginSupport;
import io.github.yedaxia.apidocs.Resources;
import io.github.yedaxia.apidocs.Utils;
import io.github.yedaxia.apidocs.parser.ControllerNode;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PostmanDocPlugin implements IPluginSupport {
    public PostmanDocPlugin() {
    }

    public void execute(List<ControllerNode> controllerNodeList) {
        FileWriter docFileWriter = null;

        try {
            Template ctrlTemplate = this.getDocTpl();

            String docFileName = String.format("%s-%s-api-docs.json", DocContext.getDocsConfig().getProjectName(), DocContext.getDocsConfig().getApiVersion());
            File docFile = new File(DocContext.getDocPath(), docFileName);
            docFileWriter = new FileWriter(docFile);
            Map<String, Object> data = new HashMap();
            data.put("controllerNodes", controllerNodeList);
            data.put("currentApiVersion", DocContext.getCurrentApiVersion());
            data.put("projectName", DocContext.getDocsConfig().getProjectName());
            data.put("i18n", DocContext.getI18n());
            ctrlTemplate.process(data, docFileWriter);

        } catch (IOException | TemplateException var10) {
            var10.printStackTrace();
        } finally {
            Utils.closeSilently(docFileWriter);
        }

    }

    private Template getDocTpl() throws IOException {
        return Resources.getFreemarkerTemplate("postman-doc.json.ftl");
    }
}


postman-doc.json.ftl 模板文件放在 resources 目录下。

{
   "info": {
      "_postman_id": "",
      "name": "${projectName}",
      "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
   },
   "item": [
      <#list controllerNodes as controller>
      {
         "name": "${controller.description}",
         "item": [
            <#list controller.requestNodes as reqNode>
               {
               "name": "${reqNode.description}",
               "request": {
                  "header": [{
                        "key": "JBOLTAPI",
                        "value": "true",
                        "type": "text"
                     },
                     {
                        "key": "jboltappid",
                        <#if reqNode.url?contains("wxa")>
                           "value": "{{wxa_appid}}",
                        <#else>
                           "value": "{{app_appid}}",
                        </#if>
                        "type": "text"
                     },
                     {
                        "key": "jboltjwt",
                        "value": "{{app_jwt}}",
                        "type": "text"
                     }
                  ],
                  "url": {
                     "raw": "{{domain}}${reqNode.url}",
                     "query": [
                        <#if reqNode.paramNodes?size != 0>
                           <#list reqNode.paramNodes as paramNode>
                              {
                                 "key": "${paramNode.name}",
                                 "value": "",
                                 "description": "${paramNode.description}"
                              }<#if paramNode_has_next>,</#if>
                           </#list>
                        </#if>
                        ]
                     }
                  }
               }<#if reqNode_has_next>,</#if>
            </#list>
         ]
      }<#if controller_has_next>,</#if>
      </#list>
   ]
}


其中 {{domain}} 是 postman 等接口测试工具中设置的环境变量。

其中 header 部分,是为了方便 JBolt 的 jwt 接口鉴权添加的,如果不需要可以去掉。

                  "header": [{
                        "key": "JBOLTAPI",
                        "value": "true",
                        "type": "text"
                     },
                     {
                        "key": "jboltappid",
                        <#if reqNode.url?contains("wxa")>
                           "value": "{{wxa_appid}}",
                        <#else>
                           "value": "{{app_appid}}",
                        </#if>
                        "type": "text"
                     },
                     {
                        "key": "jboltjwt",
                        "value": "{{app_jwt}}",
                        "type": "text"
                     }
                  ],


JApiDocsGenerator.java 中添加一句即可 config.addPlugin(new PostmanDocPlugin());

/**
 * JApiDocs 无需额外注解的 API 文档生成工具
 * <p>
 * 源码 https://github.com/YeDaxia/JApiDocs
 * 文档 https://japidocs.agilestudio.cn/#/zh-cn/
 *
 * @author zxd 2022-02-17
 */
public class JApiDocsGenerator {

    /**
     * JApiDocs 生成器
     * 如果报错,做如下检查:
     * 1 javadoc @param 后是否有注释
     * 2 src.main.java 目录中非 .java 扩展名文件的内容要 // 注释起来
     * 3 删除 config.setDocsPath 目录中的文件,再生成试试
     * <p>
     * 如果生成的 api 文档不是预期的,作如下检查:
     * 1 必须在 configRoute(Routes me) 中已该方式 me.add("/xx/yy", xx.class, "/"); 定义 Controller
     * 2 在需要生成 api 的 Controller 中添加 @ApiDoc 注解
     * 3 如果要忽略某 action,在 action 上添加 @Ignore     */
    public static void main(String[] args) {
        DocsConfig config = new DocsConfig();
        config.setProjectPath("f:/zxd_workspace/used_car/src"); // root project path
        config.setProjectName("used_car"); // project name
        config.setApiVersion("v1.0");       // api version
        config.setDocsPath("f:/zxd_workspace/used_car/src/main/webapp/assets/apidocs"); // api docs target path
        config.addPlugin(new PostmanDocPlugin());
        config.setAutoGenerate(Boolean.FALSE);  // auto generate
        //config.setMvcFramework("JFinal");
        Docs.buildHtmlDocs(config); // execute to generate
    }

}


在 config.setDocsPath 设置的目录中能找到 used_car-v1.0-api-docs.json ,将其导入到 postman 或 apifox 中。

我使用的是 apifox,看下效果。

微信截图_20220218161542.png


评论区

l745230

2022-02-19 16:35

返回值如何描述?

欲风217

2022-02-21 15:53

@l745230 返回值通过@ApiDoc(result = AdminVO.class) 或者 @ApiDoc(stringResult = "{code: 0, data: 'success'}")。我们团队没用这些方法,后台人写着麻烦,接接口的人一调接口就知道了。

欲风217

2022-02-21 15:53

@l745230 这些方法 JApiDocs 官网有介绍 https://japidocs.agilestudio.cn/#/zh-cn/