作者 | 柯然(邪影)
来源|阿里巴巴云原生公众号
背景
Swagger 是一个规范和完整的前端框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。Swagger 规范也逐渐发展成为了 OpenAPI 规范。
Springfox 是一个集成了 Swagger,基于 Sring MVC/Spring Webflux 实现的一个 Swagger 描述文件生成框架,通过使用它定义的一些描述接口的注解自动生成 Swagger 的描述文件,使 Swagger 能够展示并调用接口。
相信很多人都听说和使用过 Swagger 和 Springfox,这里就不再赘述了。
Dubbo-Admin 中有接口测试功能,但是缺少接口描述的文档,所以该测试功能比较适合接口开发人员用于测试接口。而其他人想要使用该功能就必须先通过接口开发者编写的文档或者其他方式,了解清楚接口信息才能使用该功能测试接口。
Dubbo 这边有没有集合文档展示和测试功能,可以不用写文档就能把接口直接给调用方,类似 Swagger/Springfox 的工具呢?
之前做过一些调研,找到一些类似的工具:
- 有些是基于 Springfox 做的,直接一个文本域放 JSON,与目前 Admin 中的测试功能大同小异。
- 有些是直接基于 Swagger 的 Java 版 OpenApI 规范生成工具做的,能把一些基础数据类型的简单参数作为表单项展示。
它们都有一个共同点:会把你的提供者变为 Web 项目。当然有些提供者是通过 web 容器加载启动的,甚至也有和 web 工程在一起的,那就无所谓了。
但也有非 web 的提供者,为了文档我得把它变为 web 项目吗?(还要引入一堆 Web 框架的依赖?比如 Spring MVC?)或者说生产环境打包时,删除它的引用和代码里的相关注解? 有没有简单点的方式呢?
OpenAPI 中没有 RPC 的规范,Swagger 是 OpenAPI 的实现,所以也不支持 RPC 相关调用。Springfox 是通过 Swagger 实现的 RESTful API 的工具,而 RESTful 又是基于 Web 的,Dubbo 没法直接使用。我们最终选择了自己实现:
- 提供一些描述接口信息的简单注解。
- 在提供者启动时解析注解并缓存解析结果。
- 在提供者增加几个 Dubbo-Api-Docs 使用的获取接口信息的接口。
- 在 Dubbo Admin 侧通过 Dubbo 泛化调用实现 Http 方式调用 Dubbo 接口的网关。
- 在 Dubbo Admin 侧实现接口信息展示和调用接口功能。
下列情况中的参数直接展示为表单项,其他的展示为 JSON。
- 方法参数为基础数据类型的
- 方法参数为一个 Bean,Bena 中属性为基础数据类型的
- 很少的第三方依赖,甚至大部分都是你项目里本身就使用的。
- 可以通过 profile 决定是否加载,打包时简单地修改 profile 就能区分生产和测试,甚至 profile 你本来就使用了。
今天,我很高兴的宣布:Dubbo 用户也可以享受类似 Swagger 的体验了 -- Dubbo-Api-Docs 发布了。
简介
Dubbo-Api-Docs 是一个展示 dubbo 接口文档,测试接口的工具。
使用 Dubbo-Api-Docs 分为两个主要步骤:
- 在 dubbo 项目引入 Dubbo-Api-Docs 相关 jar 包,并增加类似 Swagger 的注解。
- 在 Dubbo-Admin 中查看接口描述并测试。
通过以上两个步骤,即可享受类似 Swagger 的体验,并且可以在生产环境中关闭 Dubbo-Api-Docs 的扫描。
Dubbo-Api-Docs 目前通过直连服务节点的方式获取该服务的接口列表。测试接口时,可以直连也可以通过注册中心,未来会增加通过注册中心获取服务列表的方式,并根据 Dubbo 的升级规划增加新的功能支持,也会根据社区的需求增加功能。
Dubbo-Api-Docs 会在服务提供者启动完毕后,扫描 docs 相关注解并将处理结果缓存,并增加一些 Dubbo-Api-Docs 相关的 Dubbo 提供者接口。缓存的数据在将来可能会放到 Dubbo 元数据中心中。
当前版本: 2.7.8.1
org.apache.dubbo
dubbo-api-docs-annotations
${dubbo-version}
org.apache.dubbo
dubbo-api-docs-core
${dubbo-version}
快速入门
1. dubbo 提供者项目的方法参数中加上 Dubbo-Api-Docs 注解
- 如果 dubbo 提供者的接口和方法参数在一个单独的 jar 项目中,则在该项目中引入: dubbo-api-docs-annotations。
- dubbo 提供者项目引入 dubbo-api-docs-core。
- 在提供者项目的项目启动类(标注了 @SpringBootApplication 的类),或者配制类(标注了 @Configuration 的类)中增加注解 @EnableDubboApiDocs,以启用 Dubbo Api Docs 功能。
为避免增加生产环境中的资源占用,建议单独创建一个配制类用于启用 Dubbo-Api-Docs,并配合 @Profile("dev") 注解使用。>
当然,Dubbo-Api-Docs 仅在项目启动时多消耗了点 CPU 资源,并使用了一点点内存用于缓存,将来会考虑将缓存中的内容放到元数据中心。
下面以 dubbo-api-docs-examples 项目中的部分服务接口为例:
git clone -b 2.7.x https://github.com/apache/dubbo-spi-extensions.git
进入 dubbo-spi-extensions/dubbo-api-docs/dubbo-api-docs-examples 目录。
dubbo-api-docs-examples 中有两个子模块:
- examples-api:一个 jar 包项目,其中包含服务的接口和接口参数 Bean。
- examples-provider:提供者服务端,包含 spring boot 启动器和服务的实现。
下面我们在这两个子模块中增加 Dubbo-Api-Docs:
examples-api:
maven 引入:
org.apache.dubbo
dubbo-api-docs-annotations
2.7.8
org.apache.dubbo.apidocs.examples.params 中有两个 Bean,我们来为它们添加 docs 注解。
- QuickStartRequestBean 作为参数 Bean,添加 @RequestParam。
public class QuickStartRequestBean {
@RequestParam(value = "You name", required = true, description = "please enter your full name", example = "Zhang San")
private String name;
@RequestParam(value = "You age", defaultValue = "18")
private int age;
@RequestParam("Are you a main?")
private boolean man;
// getter/setter略...
}
- QuickStartRespBean 作为响应 Bean,添加 @ResponseProperty。
public class QuickStartRespBean {
@ResponseProperty(value = "Response code", example = "500")
private int code;
@ResponseProperty("Response message")
private String msg;
// getter/setter略...
}
由于我们只挑选了部分接口作为演示,到此这些接口涉及的 docs 注解添加完毕。
examples-provider:
maven 引入:
org.apache.dubbo
dubbo-api-docs-core
2.7.8
我们挑选一个接口作为演示:
org.apache.dubbo.apidocs.examples.api.impl.QuickStartDemoImpl 中的 quickStart 方法。
QuickStartDemoImpl 实现了 api 包中的 org.apache.dubbo.apidocs.examples.api.IQuickStartDemo 接口。
- 在 QuickStartDemoImpl 中:
@DubboService
@ApiModule(value = "quick start demo", apiInterface = IQuickStartDemo.class, version = "v0.1")
public class QuickStartDemoImpl implements IQuickStartDemo {
@ApiDoc(value = "quick start demo", version = "v0.1", description = "this api is a quick start demo", responseClassDescription="A quick start response bean")
@Override
public QuickStartRespBean quickStart(@RequestParam(value = "strParam", required = true) String strParam, QuickStartRequestBean beanParam) {
return new QuickStartRespBean(200, "hello " + beanParam.getName() + ", " + beanParam.toString());
}
}
到此 docs 相关注解已添加完毕,下面我们来开启 Dubbo-Api-Docs。新增一个配制类,位置任意,只要能被 spring boot 扫描到就行。
我们在 org.apache.dubbo.apidocs.examples.cfg 包中新增一个配制类 DubboDocConfig:
@Configuration
@Profile("dev") // 配合 Profile 一起使用, 在 profile 为 dev 时才会加载该配制类
@EnableDubboApiDocs // 开启 Dubbo-Api-Docs
public class DubboDocConfig {
}
到此 Dubbo-Api-Docs 相关的东西已经添加完毕。
dubbo-api-docs-examples 中有更多更为详尽的例子,下文中有注解的详细说明。下面我们来看一下增加 Dubbo-Api-Docs 后的效果图:
2. 启动提供者项目
- 示例使用 nacos 作为注册中心,下载并启动 nacos。
- 在上面的例子中,我们启动 examples-provider 项目中的 org.apache.dubbo.apidocs.examples.ExampleApplication。
在 examples-provider 目录中:
mvn spring-boot:run
3. 下载 dubbo-admin
dubbo-admin 仓库
dubbo-admin 需要下载 develop 分支源码启动。
git clone -b develop https://github.com/apache/dubbo-admin.git
4. 启动访问 dubbo-admin
参考 dubbo-admin 里的说明启动:
1. 在 dubbo-admin-server/src/main/resources/application.properties 中修改注册中心地址
2. 编译 mvn clean package
3. 启动:
mvn --projects dubbo-admin-server spring-boot:run
或者
cd dubbo-admin-distribution/target; java -jar dubbo-admin-0.1.jar
4. 浏览器访问: http://localhost:8080
5. 默认帐号密码都是: root
5. 进入"接口文档"模块
- 在 “dubbo 提供者 IP” 和 “dubbo提供者端口” 中分别输入提供者所在机器 IP 和端口,点击右侧 “加载接口列表” 按钮。
- 左侧接口列表中加载出接口列表,点击任意接口,右边展示出该接口信息及参数表单。
- 填入表单内容后,点击最下方测试按钮。
- 响应部分展示了响应示例及实际响应结果。
源码仓库
Dubbo-Api-Docs 根据功能拆分,分别在两个仓库中:
1. dubbo-spi-extensions
dubbo-spi-extensions 仓库地址
该仓库存放 dubbo 的一些非核心功能的扩展,Dubbo-Api-Docs 作为该仓库中的一个子模块,由于该仓库属于 Dubbo 3.0 中规划的一部分,而 Dubbo-Api-Docs 是基于 Dubbo 2.7.x 开发的,所以在该仓库中增加了 2.7.x 分支,Dubbo-Api-Docs 就在该分支下。
该仓库中包含了 Dubbo-Api-Docs 的文档相关注解、注解扫描能力和使用示例:
- dubbo-api-docs-annotations:文档生成的相关注解。考虑到实际情况中 dubbo api 的接口类和接口参数会规划为一个单独的 jar 包,所以注解也独立为一个 jar 包。本文后面会对注解做详细说明。
- dubbo-api-docs-core:负责解析注解,生成文档信息并缓存。前面提到的 Dubbo-Api-Docs 相关接口也在该包中。
- dubbo-api-docs-examples:使用示例。
2. Dubbo-Admin
Dubbo-Admin 仓库地址
文档的展示及测试放在了 dubbo admin 项目中。
注解说明
- @EnableDubboApiDocs:配制注解,启用 dubbo api docs 功能。
@ApiModule:类注解,dubbo 接口模块信息,用于标注一个接口类模块的用途。
- value:模块名称
- apiInterface:提供者实现的接口
- version:模块版本
@ApiDoc:方法注解,dubbo 接口信息,用于标注一个接口的用途。
- value:接口名称
- description:接口描述(可使用 html 标签)
- version:接口版本
- responseClassDescription:响应的数据的描述
@RequestParam:类属性/方法参数注解,标注请求参数。
- value:参数名
- required:是否必传参数
- description:参数描述
- example:参数示例
- defaultValue:参数默认值
allowableValues:允许的值,设置该属性后界面上将对参数生成下拉列表
- 注:使用该属性后将生成下拉选择框
- boolean 类型的参数不用设置该属性,将默认生成 true/false 的下拉列表
- 枚举类型的参数会自动生成下拉列表,如果不想开放全部的枚举值,可以单独设置此属性
@ResponseProperty:类属性注解,标注响应参数。
- value:参数名
- example:示例
使用注意
- 响应 bean(接口的返回类型)支持自定义泛型,但只支持一个泛型占位符。
- 关于 Map 的使用:Map 的 key 只能用基本数据类型。如果 Map 的 key 不是基础数据类型,生成的就不是标准 json 格式,会出异常。
- 接口的同步/异步取自 org.apache.dubbo.config.annotation.Service#async / org.apache.dubbo.config.annotation.DubboService#async。
示例说明
dubbo-spi-extensions / Dubbo-Api-Docs 中的 dubbo-api-docs-examples 目录中为示例工程:
- examples-api:jar 包项目,包含服务提供者的接口类及参数 Bean。
- examples-provider:使用 dubbo-spring-boot-starter 的提供者项目,注册中心使用 nacos。
- examples-provider-sca:使用 spring-cloud-starter-dubbo 的提供者项目,注册中心使用 nacos。
示例使用步骤
- 示例使用 nacos 作为注册中心,下载并启动 nacos。
- 任意启动 examples-provider 和 examples-provider-sca 中的任意一个,当然也可以两个都启动。examples-provider 使用 20881 端口 examples-provider-sca 使用 20882 端口。两个项目都是 spring boot 项目,启动类在 org.apache.dubbo.apidocs.examples 包下。
- 启动 Dubbo-Admin,浏览器访问:http://localhost:8080。
- 进入 dubbo-admin 中的 “接口文档” 模块。
- 在 “dubbo 提供者 IP” 和 “dubbo 提供者端口” 中分别输入提供者所在机器 IP 和端口,点击右侧 “加载接口列表” 按钮。
- 左侧接口列表中加载出接口列表,点击任意接口,右边展示出该接口信息及参数表单。
- 填入表单内容后,点击最下方测试按钮。
- 响应部分展示了响应示例及实际响应结果。
如果你对 Dubbo Api Docs 的建设有兴趣,欢迎你钉钉搜索群号:34403965,加入 Dubbo Api Docs 共建小组;也欢迎你钉钉搜索群号:21976540,加入 Dubbo 开源讨论群。