Swagger 自动生成 Dubbo 服务的接口文档,以及测试调用
管她前浪,还是后浪?
能浪的浪,才是好浪!
每天 8:55 更新文章,每天掉亿点点头发...
源码精品专栏
-
1. 概述 -
2. Swagger Dubbo -
3. 接入 Knife4j 作为 Swagger UI 界面 -
4. 接入 YApi 统一管理 -
666. 彩蛋
1. 概述
在使用 SpringMVC 构建 HTTP API 时,我们可以通过 Swagger 自动生成 HTTP 接口文档,通过 Swagger UI 界面上进行 HTTP 接口调试。如下图所示:
秃头提示:对 Swagger 不太了解的胖友,可以去阅读下艿艿写的 《芋道 Spring Boot API 接口文档 Swagger 入门》 文章。
开发体验杠杠的好!但是在使用 Dubbo 构建 RPC API 时,简直想要自闭。常常面临的痛苦是:
-
隔壁团队的老王,不肯给 Dubbo 写 接口文档,只能从他的 Dubbo API 的 jar
包中寻寻觅觅想要的接口,贼不方便~ -
自己编写的每个 Dubbo API 接口,都需要写个 Controller 或者 Test 类去调用测试, 接口调试非常麻烦~
在一个逐步自闭到要爆炸的下午,艿艿做了一波 Dubbo 接口文档与接口调试的调研,想要尝试这块的痛点。结果比想象中顺利且简单,这不趁着这无聊到抠脚的周末,整理下分享给胖友。
🚀 这么良心,不考虑给艿艿点个赞么?!
芳芳都说好!!!
2. Swagger Dubbo
哈哈哈~实际上,我们还是可以通过 Swagger 实现 Dubbo 的接口文档和接口调试这两个功能。效果如下图:
2.1 小小改造
dubbo-swagger 最新版本 v2.0.1
,并不支持 Dubbo 2.7.0
开始的版本,因此我们需要做一点点小小的改造。具体的改造点如下:
良心艿:怕麻烦的胖友,可以看艿艿 fork 出来的仓库 https://github.com/YunaiV/swagger-dubbo,给改的明明白白了,直接能用。
-
-
合并 PR#50 的代码,支持 Dubbo 2.7.0
开始的版本。 -
-
合并 PR#46 的代码,使 Swagger UI 界面正确展示 POJO 类型的参数。
2.2 快速入门
swagger-dubbo
项目提供了 Spring Boot + Dubbo 的示例 dubbo-provider-springboot
,我们来一起看一看。
不过 dubbo-provider-springboot
示例暂时有一点点小“问题”,我们需要稍微修正下。
2.2.1 修改依赖
示例使用 Dubbo 的版本是 2.6.0
,而我们希望使用 Dubbo 的版本是 2.7.0
开始,因此需要略微修改 pom.xml
如下:
<!-- 去除 Dubbo 2.6.0 的依赖 -->
<!-- <dependency>-->
<!-- <groupId>com.alibaba</groupId>-->
<!-- <artifactId>dubbo</artifactId>-->
<!-- <version>2.6.0</version>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>org.springframework</groupId>-->
<!-- <artifactId>spring</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.zookeeper</groupId>-->
<!-- <artifactId>zookeeper</artifactId>-->
<!-- <version>3.5.2-alpha</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.curator</groupId>-->
<!-- <artifactId>curator-framework</artifactId>-->
<!-- <version>4.0.1</version>-->
<!-- </dependency>-->
<!-- 引入 Dubbo 2.7.0 的依赖 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.4.1</version>
</dependency>
<!-- 使用 Zookeeper 作为注册中心 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>4.0.1</version>
</dependency>
2.2.2 修改配置文件
修改 application.properties
配置文件,增加如下配置项:
swagger.dubbo.application.groupId=com.deepoove
swagger.dubbo.application.artifactId=dubbo-provider-springboot
swagger.dubbo.application.version=2.0.2-SNAPSHOT
通过 swagger.dubbo.application
配置项,可以知道该 Dubbo 服务的 API jar
包的 groupId
、artifactId
、version
信息。
友情提示:
swagger-dubbo
还提供了其它配置项,一般默认即可。感兴趣的胖友,可以看看 SwaggerDubboProperties 配置类。
2.2.3 简单测试
下面,我们来运行下 dubbo-provider-springboot
示例项目,感受下 swagger-dubbo
的具体功能。
第一步,本地运行一个 ZooKeeper 服务,作为注册中心。
第二步,执行 Application 类,将 Dubbo 服务提供者进行启动。启动成功的日志如下:
14:12:24.180 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8077 (http) with context path ''
14:12:24.184 [main] INFO c.d.d.p.springboot.Application - Started Application in 3.443 seconds (JVM running for 4.109)
这里,我们已经可以看到当前 Dubbo 服务所提供的 RPC 接口文档。
友情提示:访问的 Swagger UI 界面,就是我们在示例项目的
resources/static/distv2
目录下的静态资源。
第四步,我们可以任一选择一个 Dubbo API 接口,填写参数后,点击「Try it out!」按钮进行 RPC 接口调试。如下图所示:
通过接口调试的功能,我们可以方便的测试。
友情提示:可能有胖友会好奇,
swagger-dubbo
是如何实现接口调试的功能的呢?答案可以到 DubboHttpController 类中去寻找。简单来说,就是使用 Dubbo 提供的 Java API 获得到对应 Dubbo Consumer 对象,将 HTTP 请求参数映射成 Dubbo RPC 请求参数,最终进行调用。
3. 接入 Knife4j 作为 Swagger UI 界面
由于 dubbo-swagger
项目并未将其提供的 Swagger UI 界面封装成一个 jar
包,导致集成 dubbo-swagger
的 Dubbo 项目需要在其 resources
目录下,添加相应的 Swagger UI 的静态资源。例如说:
显然,这么做是非常不优雅的,因为后续无法方便的更新 Swagger UI 的静态资源。那么,应该怎么办呢?这里艿艿先演示一种解决方案,也是目前团队所采用的,接入 Knife4j 作为 Swagger UI 界面。
秃头提示:Knife4j 是基于 Swagger 的增强解决方案,提供更强大的 Swagger 的功能,以及更易用的 Swagger UI 界面。
下面,我们继续在 dubbo-provider-springboot
示例项目上,进行改造接入。
3.1 修改依赖
修改 pom.xml
文件,引入 Knife4j Starter 依赖。具体如下:
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.5</version>
</dependency>
3.2 创建 SwaggerConfiguration
创建 SwaggerConfiguration 配置类,自定义 SwaggerResourcesProvider Bean。代码如下:
@Configuration
@EnableSwagger2 // 标记项目启用 Swagger API 接口文档
public class SwaggerConfiguration {
@Bean
@Primary
public SwaggerResourcesProvider newSwaggerResourcesProvider(Environment env, DocumentationCache documentationCache) {
return new InMemorySwaggerResourcesProvider(env, documentationCache) {
@Override
public List<SwaggerResource> get() {
// 1. 调用 InMemorySwaggerResourcesProvider
List<SwaggerResource> resources = super.get();
// 2. 添加 swagger-dubbo 的资源地址
SwaggerResource dubboSwaggerResource = new SwaggerResource();
dubboSwaggerResource.setName("dubbo");
dubboSwaggerResource.setSwaggerVersion("2.0");
dubboSwaggerResource.setUrl("/swagger-dubbo/api-docs");
dubboSwaggerResource.setLocation("/swagger-dubbo/api-docs"); // 即将废弃,和 url 属性等价。
resources.add(0, dubboSwaggerResource);
return resources;
}
};
}
}
艿艿先暂时不解释为什么要这么做,因为涉及到 Swagger 运行机制相关的知识,略微有点小复杂~~稍后,在「3.4 再看 SwaggerConfiguration」小节,我们在一起遨游这块知识的海洋。
3.3 简单测试
是不是相比 swagger-dubbo
提供的 Swagger UI 界面更加优秀。
我们再来看看接口文档和接口调试的界面,如下图所示:
-
接口文档 -
接口调试
重要提示:此时,我们可以将
resources
目录下的 Swagger UI 的静态资源删除。艿艿这里不删除的原因,还是方便大家体验对比 = =
3.4 再看 SwaggerConfiguration
为什么我们要在 SwaggerConfiguration 配置类中,自定义一个 SwaggerResourcesProvider Bean 呢?原因是,它和 Swagger UI 界面的运行机制有关。
① Swagger UI 界面采用前后端分离的架构,通过请求 Swagger 定义的接口元数据 HTTP API,获得到每个接口的信息,展示成接口文档。
可能有点难懂,我们来看看 dubbo-swagger
项目在 dubbo-provider-springboot
示例项目中,自定义实现的接口元数据 HTTP API的返回结果,如下图所示:
-
在 paths
数组中,每一个元素对应一个 接口的信息。而这些 接口的信息,是通过扫描 Swagger 的注解所获取到。
课外作业:对
dubbo-swagger
项目实现的接口元数据 HTTP API,可以后续看看 SwaggerDubboController 类的代码,比较简单。
② 在理解完 Swagger 定义的接口元数据 HTTP API 之后,再来看看 Swagger 定义的资源 HTTP API。Swagger Resource 资源的作用,用于将我们使用 SpringMVC 实现的 HTTP API 进行分组。并且,每个资源对应一个接口元数据 HTTP API,用于获取该分组的接口元数据。
可能有点懵逼,我们来看看 dubbo-provider-springboot
示例项目中,资源 HTTP API的返回结果,如下图所示:
-
【 蓝色部分】Swagger 默认实现了一套 Swagger 资源的逻辑,通过 InMemorySwaggerResourcesProvider 的 #get()
方法,进行获取。我们在使用 SpringMVC 实现的 HTTP API 接口,就属于该 Swagger 资源。 -
【 红色部分】 swagger-dubbo
自定义了一套 Swagger 资源的逻辑,所以我们需要 手动添加一个名字为dubbo
的 Swagger Resource 分组,集成到 Swagger 体系中。
现在,胖友是不是能够理解 SwaggerConfiguration 配置类的作用了。
可能胖友会有一个疑惑,为什么我们在使用 swagger-dubbo
提供的 Swagger UI 界面时,不用创建 SwaggerConfiguration 配置类呢?因为它不考虑存在多 Swagger Resource 资源的情况,直接请求 swagger-dubbo
提供的接口元数据 HTTP API。如下图所示:
3.5 其它解决方案
除了接入 Knife4j 作为 Swagger UI 界面的方案外,还有两种方案:
① 方案一,将 swagger-dubbo
提供的 Swagger UI 的静态资源,部署到 Nginx 下。这样,我们就可以访问 Nginx 下的 Swagger UI 界面,填写需要查看 Dubbo 服务的接口元数据 HTTP API 即可。如下图所示:
② 方案二,将 swagger-dubbo
提供的 Swagger UI 的静态资源,打包成名字为 swagger-dubbo-ui
的 jar
包。这样,每个 Dubbo 服务提供者的项目,引入该 jar
包即可。具体可参考 Knife4j 的 knife4j-spring-ui
的做法,如下图所示:
4. 接入 YApi 统一管理
随着 Dubbo 服务越来越多,我们需要一个 API 平台能够查看到所有的 Dubbo 服务的 RPC API 接口信息。目前,艿艿比较推荐和使用的 YApi 平台,主要原因是 YApi 可以采集 Swagger 提供的接口元数据 HTTP API,自动进行同步接口信息的同步。
秃头提示:对 YApi 不太了解的胖友,可以去阅读下艿艿写的 《芋道 Spring Boot API 接口文档 Swagger 入门》 的「4. 更强大的 YApi」小节。
具体的效果,胖友可以看看如下图:
-
项目列表 -
项目详情
dubbo-swagger
提供的接口元数据 HTTP API,路径是 /swagger-dubbo/api-docs
。至于如何配置定时采集,可参考如下图:
666. 彩蛋
至此,我们通过多个开源项目的组合,实现 Dubbo 的接口文档和接口调试的功能。简单来总结下:
-
基于 Swagger Dubbo 项目,实现 Dubbo RPC API 的 接口文档和 接口调试的功能。 -
基于 Knife4j 项目,提供更强大的 Dubbo Swagger UI 界面。 -
基于 YApi 项目,作为统一的 API 管理平台,可以查看 所有 Dubbo 项目的 API 接口文档、进行 接口调试。
当然,如果我们要将该方案落地到公司的 Dubbo 项目中,还有一些事情需要去做:
-
1、将修改后的 dubbo-swagger
项目,重新编译打包,推送到公司的 Nexus 私服。毕竟,咱也不知道dubbo-swagger
项目啥时候会支持 Dubbo2.7.0
开始的版本。 -
2、编写公司的 Swagger Dubbo Starter,将对 Knife4j 的整合进行自动配置。 -
3、尝试基于 YApi 提供的 mock 功能,实现 Dubbo 服务的 mock 能力,以便更好的并行开发。
End~继续抠脚。
我是艿艿,一个每天徘徊在煞笔与牛啤的死胖子。
已在知识星球更新源码解析如下:
最近更新《芋道 SpringBoot 2.X 入门》系列,已经 20 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。
提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。
兄弟,艿一口,点个赞!👇