You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Rest Doc为带版本控制的REST API生成文档?

我之前在维护带版本控制的REST API文档时,刚好也是用TestNg+Spring Rest Docs+Asciidoc的组合,踩过几个坑,分享几个实用的解决方案,帮你适配版本化的文档需求:

1. 给每个版本的API操作加版本前缀,隔离Snippets

这是最直接的方式,给不同版本的测试生成的snippets加上版本标识,避免互相覆盖,同时在Asciidoc里分版本章节引用。

比如针对v1和v2的Get People接口:

  • 在TestNg测试方法里,给document()方法的operation ID加上版本前缀,比如v1-get-people和v2-get-people:
@Test
public void getPeopleV1Test() throws Exception {
    mockMvc.perform(get("/api/v1/people")
            .accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andDo(document("v1-get-people",
                    requestFields(/* v1 请求字段定义 */),
                    responseFields(/* v1 响应字段定义 */)));
}

@Test
public void getPeopleV2Test() throws Exception {
    mockMvc.perform(get("/api/v2/people")
            .accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andDo(document("v2-get-people",
                    requestFields(/* v2 请求字段定义,比如新增了`department`字段 */),
                    responseFields(/* v2 响应字段定义 */)));
}
  • 然后在Asciidoc文档里分版本引用:
# API Version 1
=== Get People (v1)
Get the people registered in v1 API.
operation::v1-get-people[snippets='http-request,request-fields,http-response,response-fields,error-codes']

# API Version 2
=== Get People (v2)
Get the people registered in v2 API (supports department filtering).
operation::v2-get-people[snippets='http-request,request-fields,http-response,response-fields,error-codes']

这种方式的好处是逻辑清晰,每个版本的snippets完全隔离,不会互相干扰,适合版本差异较大的场景。

2. 用Asciidoc的条件渲染/文件包含,实现版本切换

如果你的API版本之间大部分内容是复用的,只有少量差异,可以用Asciidoc的条件指令来动态渲染对应版本的内容,减少重复代码。

  • 先把每个版本的差异部分单独写成小的Asciidoc片段,比如v1-get-people-diff.adoc和v2-get-people-diff.adoc。
  • 主文档里用ifdef指令根据构建参数选择加载的版本:
=== Get People
Get the people registered.

ifdef::api-version=v1[]
include::v1-get-people-diff.adoc[]
operation::v1-get-people[snippets='http-request,request-fields,http-response,response-fields,error-codes']
endif::api-version=v1[]

ifdef::api-version=v2[]
include::v2-get-people-diff.adoc[]
operation::v2-get-people[snippets='http-request,request-fields,http-response,response-fields,error-codes']
endif::api-version=v2[]

构建的时候,你可以通过传递参数指定版本,比如用Maven的话,在asciidoctor-maven-plugin里配置attributes:

<plugin>
    <groupId>org.asciidoctor</groupId>
    <artifactId>asciidoctor-maven-plugin</artifactId>
    <version>2.2.6</version>
    <configuration>
        <attributes>
            <api-version>${api.version}</api-version>
        </attributes>
    </configuration>
</plugin>

然后运行mvn asciidoctor:process-asciidoc -Dapi.version=v2就能生成v2版本的文档。

3. 动态注入版本信息到测试中,批量生成多版本Snippets

如果需要批量生成所有版本的文档,可以在TestNg里通过系统参数或者配置文件注入版本号,动态生成对应版本的operation ID和请求路径。

比如在测试类里设置版本变量:

private String apiVersion;

@BeforeMethod
public void setup() {
    // 从系统参数获取版本,默认v1
    apiVersion = System.getProperty("api.version", "v1");
    this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
            .apply(documentationConfiguration(restDocumentation))
            .build();
}

@Test
public void getPeopleTest() throws Exception {
    mockMvc.perform(get("/api/{version}/people", apiVersion)
            .accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andDo(document(apiVersion + "-get-people",
                    requestFields(getRequestFieldsForVersion(apiVersion)),
                    responseFields(getResponseFieldsForVersion(apiVersion))));
}

// 根据版本返回对应的字段定义
private RequestFieldsSnippet getRequestFieldsForVersion(String version) {
    if ("v2".equals(version)) {
        return requestFields(
                fieldWithPath("name").description("Person's full name"),
                fieldWithPath("department").description("Person's department (v2 only)")
        );
    } else {
        return requestFields(
                fieldWithPath("name").description("Person's full name")
        );
    }
}

然后运行测试时指定版本:mvn test -Dapi.version=v2,就能生成v2版本的snippets。重复运行不同版本的测试,就能得到所有版本的snippets,之后在Asciidoc里按版本引用即可。

一些额外的小技巧

  • 把通用的字段定义(比如错误码、基础响应字段)抽成Asciidoc的宏或者include文件,比如common-error-codes.adoc,在各个版本的文档里引用,减少重复。
  • 用构建工具(Maven/Gradle)的任务来自动化生成多版本文档,比如创建generate-docs-v1和generate-docs-v2任务,一键生成所有版本的文档。

内容的提问来源于stack exchange,提问作者Manuelarte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:41:24