Restdoc与Docsify,更简单的生成Api文档

大半年前就写过一篇文章《测试驱动开发(TDD)的实践》,关于测试的。时至今日,我仍然坚信测试是软件开发一重要环节,它在绝大多数情况下,保障了系统的质量与稳定性。

但当时所搭的框架存在一些不足,当然主要是由于Asciidoctor。这是一个足够完善的标记语言,但也足够复杂。然而大多数情况下我们并不需要这些语法,Markdown正好足够。

事实上,当时我最先尝试的也是Markdown,使用Spring Restdoc中推荐的Slate方案,来解决Markdown无法包含问题。缺点是它运行使用的Ruby,与我所学的完全不同(Java、Js)。但最近看到了另一个文档工具Docsify,它也添加了包含功能,它足够简单,以至于看几遍例子就完全学会,虽然也有缺点,SEO方面,但内部接口文档,你会在乎这个么?下面是一个例子整合Restdoc与Docsify

创建服务

首先,创建一个简单的Spring Boot服务,以及暴露一个用户接口

@RestController
@SpringBootApplication
public class RestdocDocsifyApplication {

    public static void main(String[] args) {
        SpringApplication.run(RestdocDocsifyApplication.class, args);
    }

    @GetMapping("/")
    public String index(){
        return "Server is running!";
    }

    @GetMapping("/user")
    public User user(){
        return new User("Jone",1,20);
    }

}

创建测试用例

这个测试用例是集成测试

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
public class RestdocDocsifyApplicationTests {

    @Resource
    private WebTestClient webTestClient;

    @Test
    public void contextLoads() {
        this.webTestClient.get().uri("/").accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus().isOk()
                .expectBody(String.class)
                .isEqualTo("Server is running!");
    }

    @Test
    public void getUser() {
        this.webTestClient.get().uri("/user").accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus().isOk()
                .expectBody();
    }
}

整合Restdoc

  1. 添加自动配置注解@AutoConfigureRestDocs
  2. 为每个WebTestClient添加文档参数说明.consumeWith(document())
    整合之后的结果如下
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
@AutoConfigureRestDocs(outputDir = "docs/snippets")
@Import(CustomRestDocsConfiguration.class)
public class RestdocDocsifyApplicationTests {

    @Resource
    private WebTestClient webTestClient;

    @Test
    public void getUser() {
        this.webTestClient.get().uri("/user").accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus().isOk()
                .expectBody()
                .consumeWith(document("user",responseFields(
                        fieldWithPath("name").description("The user's name"),
                        fieldWithPath("sex").description("The user's sex"),
                        fieldWithPath("age").description("The user's age"))
                ));
    }
}

其中outputDir定义输出目录,指向Docsify文档目录,方便部署(注意添加Git忽略配置),@Import(CustomRestDocsConfiguration.class)导入自定义配置,目的是修改模板为Markdown,代码如下

@TestConfiguration
public class CustomRestDocsConfiguration implements RestDocsWebTestClientConfigurationCustomizer {
    @Override
    public void customize(WebTestClientRestDocumentationConfigurer configurer) {
        configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
    }
}

创建Docsify文件

Docsify的一些入门,可以查看官网,这里已经当你会基本的操作了。首先创建一个index.html,您可以使用命令行生成,或者直接Copy下面的代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Spring-Cloud Docs</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="description" content="Description">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
</head>

<body>
<div id="app"></div>
<script>
    window.$docsify = {
        name: 'Restdoc-Docsify Examples',
        repo: 'JiangTJ/restdoc-docsify',
        loadSidebar: true,
        autoHeader: true,
        auto2top: true,
        subMaxLevel: 2
    }
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
<script src="//unpkg.com/prismjs/components/prism-java.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-http.min.js"></script>
</body>

</html>

你可以调整window.$docsify参数,这里将loadSidebar置为了true,为的是每个需求服务分在不同的文件里
同样的需要为其添加主页README.md和侧边栏_sidebar.md

  • README.md
# Welcome Page

## How to use
mvn test
docsify serve docs
browse `localhost:3000`   
click sidebar `User Api`
  • _sidebar.md
* [User Api](user.md)

编写一个用户服务,使用文档嵌入,将代码片段包括进去

  • user.md
### curl-request
[curl-request](snippets/user/curl-request.md ':include')

### http-request
[http-request](snippets/user/http-request.md ':include')

### http-response
[http-response](snippets/user/http-response.md ':include')

### httpie-request
[httpie-request](snippets/user/httpie-request.md ':include')

### request-body
[request-body](snippets/user/request-body.md ':include')

### response-body
[response-body](snippets/user/response-body.md ':include')

### response-fields
[response-fields](snippets/user/response-fields.md ':include')

运行

  1. 运行maven测试mvn test生成代码片段
  2. 执行命令行docsify serve docs,浏览器打开localhost:3000就可以预览刚才编写的文档了(事实上该命令只是将docs下的文件直接放置在web服务器中,如果使用CI可以很方便的部署该文档服务)

不足

Docsify足够简单,Restdoc在测试阶段生成文档的方式既校验了代码,又校验文档,这种方式还有什么不足呢?在以下两方面

  • 无法很好的生成pdf文件
  • Mock接口

如果你所在的公司非常“传统”,对于doc或者pdf之类的文件很执着,那Asciidoctor更适合您,多学一门语言而已,但Asciidoctor生成的pdf是真的漂亮。另外一个Mock接口,是为了在完成前,前端可以直接调用Mock接口进行调试,这是一个很好的实践,具体如何做到,你可以尝试一下,方式应该是多种多样的

参考

本文作者:Mr.J
本文链接: https://www.dnocm.com/articles/almond/restdoc-and-docsify/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容