Swagger的离线文档
一、引言
众所周知,Swagger需要在微服务运行的时候才能查看文档,那么在开发过程中,由于频繁地调试项目,Swagger文档将处于几乎无法使用的情况。那么使用如何离线文档呢?
二、离线文档的选型
1、Swagger2Markup:这是一个开源项目,项目的主页为:
https://github.com/Swagger2Markup/swagger2markup
具体用法可参照:
https://cloud.tencent.com/developer/article/1332445
2、自研把/v2/api-docs 返回的Json加载到静态展现页面或者转换成需要的文件格式。
三、现有方案离线文档的问题
离线文档生成的触发时机均为两个时机:
(1)手动触发离线文档的生成;
(2)Maven打包时候离线文档生成;
本文作者和小伙伴们希望在开发的过程中就能够自动生成和更新离线文档。
四、实现方案
访问/v2/api-docs,我们得到如下的Json结构
其中,tags为控制器Controller列表,paths为请求的接口,definitions为自定义的实体类。
也就是说swagger是一个接口把所有的内容都返回给前端了。那么我们保存下这个json给前端展示时候使用就大功告成。这时候问题来了,能够获取到这个接口数据的时机是什么呢?
打开swagger源码查看Controller,如下图所示:
接口调用的是这个方法,在这里我们可以看到:
Documentation documentation = documentationCache.documentationByGroup(groupName);
这里使用了一个缓存,而这个缓存是在什么时间形成的呢?我们继续查找源码,如下所示:
那么这个start又是在什么地方执行的呢?我们继续查看源码。在SpringApplication的run当中至关重要的一个步骤是refreshContext,而在这个过程中主要分为以下几个步骤:
我们可以简单地分为三大步骤(1)bean初始化准备(2)bean初始化(3)初始化后操作。那么上面的start是在哪里运行的呢?答案是:
this.finishRefresh();
我们查看这部分的代码,红线框内为文档插件的调用:
因此,在任何Bean本身的生命周期事件都无法作为触发获取swagger api的时机。那么从上述代码来看只能ContextRefreeshedEvent进行处理,这个答案是可以的。具体方式如下:
class A implements
ApplicationListener
然而笔者使用了另外一种方式来处理,可能有绕路的嫌疑,然而其中来源于阿里组件seata的思路可作为参考。
1、增加DocumentationPluginsBootstrapper的子类,并增加注册观察者方法以及重写start方法,如下图所示:
2、替换DocumentationPluginsBootstrapper这个类型的Bean,如下图所示:
3、处理onComplete(),这里就不再累赘了,获取数据方式同swagger Controller,而把这个数据转换成web或者文件,Swagger2Markup或许也是做得更好的,如若要推送到远程服务器使用http或sftp协议均可。
4、定义注解,同时引入配置类(Configuration + DocumentListener)
使用时候仅仅需要在Application上加入该注解,yml文件添加相关的推送配置即可。
最后发一个最终效果: