You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2021/01/30 11:28:23 UTC

[dubbo-spi-extensions] 11/39: 新增dubbo-api-docs项目

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch 2.7.x
in repository https://gitbox.apache.org/repos/asf/dubbo-spi-extensions.git

commit 0745a05e2c7ef5cba86a89b2f5a83ea1b0f2a26d
Author: qq213539 <21...@qq.com>
AuthorDate: Fri Oct 30 16:45:25 2020 +0800

    新增dubbo-api-docs项目
---
 dubbo-api-docs/README.md                           | 132 ++++++++
 dubbo-api-docs/README_ch.md                        | 130 ++++++++
 dubbo-api-docs/dubbo-api-docs-annotations/pom.xml  |  35 +++
 .../apache/dubbo/apidocs/annotations/ApiDoc.java   |  55 ++++
 .../dubbo/apidocs/annotations/ApiModule.java       |  50 +++
 .../dubbo/apidocs/annotations/RequestParam.java    |  70 +++++
 .../apidocs/annotations/ResponseProperty.java      |  47 +++
 dubbo-api-docs/dubbo-api-docs-core/pom.xml         |  71 +++++
 .../apache/dubbo/apidocs/EnableDubboApiDocs.java   |  40 +++
 .../core/DubboApiDocsAnnotationScanner.java        | 346 +++++++++++++++++++++
 .../dubbo/apidocs/core/DubboApiDocsCache.java      | 106 +++++++
 .../dubbo/apidocs/core/beans/HtmlTypeEnum.java     |  62 ++++
 .../apache/dubbo/apidocs/core/beans/ParamBean.java |  93 ++++++
 .../core/providers/DubboDocProviderImpl.java       |  47 +++
 .../apidocs/core/providers/IDubboDocProvider.java  |  50 +++
 .../apache/dubbo/apidocs/utils/ClassTypeUtil.java  | 307 ++++++++++++++++++
 .../apache/dubbo/apidocs/utils/SimpleTypeImpl.java |  23 ++
 .../dubbo-api-docs-examples/examples-api/pom.xml   |  40 +++
 .../dubbo/apidocs/examples/api/IAsyncDemo.java     |  89 ++++++
 .../dubbo/apidocs/examples/api/ISyncDemo.java      |  97 ++++++
 .../apidocs/examples/params/DemoParamBean1.java    |  76 +++++
 .../examples/params/DemoParamBean1SubBean1.java    |  45 +++
 .../apidocs/examples/params/DemoParamBean2.java    |  39 +++
 .../dubbo/apidocs/examples/params/TestBean.java    |  33 ++
 .../dubbo/apidocs/examples/params/TestEnum.java    |  30 ++
 .../apidocs/examples/responses/BaseResponse.java   |  48 +++
 .../apidocs/examples/responses/DemoRespBean1.java  |  60 ++++
 .../examples-provider-sca/pom.xml                  |  35 +++
 .../examples-provider/pom.xml                      |  80 +++++
 .../dubbo/apidocs/examples/ExampleApplication.java |  41 +++
 .../apidocs/examples/api/impl/AsyncDemoImpl.java   |  99 ++++++
 .../apidocs/examples/api/impl/SyncDemoImpl.java    | 116 +++++++
 .../dubbo/apidocs/examples/cfg/DubboDocConfig.java |  33 ++
 .../src/main/resources/application.yml             |  15 +
 dubbo-api-docs/dubbo-api-docs-examples/pom.xml     |  53 ++++
 dubbo-api-docs/pom.xml                             | 210 +++++++++++++
 36 files changed, 2903 insertions(+)

diff --git a/dubbo-api-docs/README.md b/dubbo-api-docs/README.md
new file mode 100644
index 0000000..1a61dab
--- /dev/null
+++ b/dubbo-api-docs/README.md
@@ -0,0 +1,132 @@
+# dubboDoc
+
+[中文](./README_ch.md)
+
+Dubbo api documents, test tools, generate documents according to annotations, and provide test functions
+
+Only some annotations are needed to generate documents similar to swagger, without turning a non web's dubbo project into a web project.
+
+Welcome everyone to make complaints about it~
+
+At present, the function of the first version is relatively rough (the interface is also rough), and the user experience is not very good. It will be gradually optimized later, and all kinds of PR are welcome~
+
+
+
+```
+When testing Dubbo providers, I always thought that if Dubbo had a document + testing 
+tool similar to swagger
+I've also found that several of them are based on springfox, and will add some restful 
+interfaces to Dubbo project,if your Dubbo service itself is started through a web container 
+or mixed with web projects, that's fine.
+But my Dubbo projects are all non web projects. For those with obsessive-compulsive disorder, 
+it is a little unacceptable to turn the project into a web project for the purpose of documentation,
+so I have the idea of doing it myself...
+```
+## Version planning
+### First edition
+* Parsing annotations and generating UI
+* Unfriendly user interface (without handling some exceptions)
+### Second edition
+* Replace the JSON text area with a proper JSON editor, and verify the JSON format
+* Add tabs
+* It can save the test and facilitate the next direct loading test
+* Some exceptions are handled as friendly text prompts
+* Add remark.md and show it in the front end
+* Add changelog.md and show it in the front end
+### Follow up edition
+* Demand  based on own use and issue planning
+* Planning according to Dubbo upgrading
+## Registry center suppor
+* In theory, all registries supported by Dubbo support
+
+## How to use?
+1. Dubbo doc annotation added to method parameters of Dubbo project
+   * Dubbo provider project introduces Dubbo doc core
+   * If Dubbo's interface and parameters are a separate jar package project, introduce Dubbo doc annotations
+
+### Current Version: Same as Dubbo version
+```
+<dependency>
+    <groupId>org.apache.dubbo</groupId>
+    <artifactId>dubbo-api-docs-annotations</artifactId>
+    <version>${dubbo-version}</version>
+</dependency>
+
+<dependency>
+    <groupId>org.apache.dubbo</groupId>
+    <artifactId>dubbo-api-docs-core</artifactId>
+    <version>${dubbo-version}</version>
+</dependency>
+```
+2.Download dubbo-doc-ui-server [Download](https://github.com/KeRan213539/dubboDoc/releases)
+
+3. Start dubbo-doc-ui-server
+
+4. Visit: http:// localhost:8888
+   * Port can be modified in application.yml
+   * swagger-ui http:// localhost:8888/swagger-ui.html
+### Annotation use
+* @DubboApiModule class annotation: dubbo API module information, used to mark the purpose of an interface class module
+    * value: module name
+    * apiInterface: Provider implemented interface
+    * version: module version
+* @DubboApi method annotation: dubbo API information, used to mark the purpose of an dubbo API
+    * value: API name
+    * description: API description(HTML tags available)
+    * version: API version
+    * responseClassDescription: response class description
+* @RequestParam class property/method Parameter annotation: mark request parameters
+    * value: parameter name
+    * required: true/false required parameter
+    * description: parameter description
+    * example: parameter example
+    * defaultValue: parameter default value
+    * allowableValues: Allowed values. After setting this property, a drop-down list will be generated for the parameter
+        * Note: a drop-down selection box will be generated after using this property
+        * Parameters of boolean type do not need to be set with this property. A drop-down list of true / false will be generated by default
+        * Parameters of enumeration type will automatically generate a drop-down list. If you do not want to open all enumeration values, you can set this property separately.
+* @ResponseProperty Class attribute annotation: mark response parameters
+    * value: parameter name
+    * example: example
+### dubbo-doc-ui
+* Get API list direct connection: 
+> Because Dubbo services with different functions may be registered in the same registration center, 
+> but the name of the interface used by Dubbo doc is the same, so the interface of Dubbo doc uses direct 
+connection to obtain the list of different interfaces of different functions.
+
+* The test can be connected directly or through the registration center
+### swagger-ui TODO
+
+### Use note
+* The response bean (the return type of the interface) supports custom generics, but only one generic placeholder.
+* About the use of Map: the key of map can only use the basic data type. If the key of map is not the basic data type, the generated key is not in the standard JSON format, and an exception will occur
+* The API's synchronous / asynchronous is from org.apache.dubbo.config.annotation.Service.async
+
+## Project structure
+* dubbo-doc-annotations: Document generation annotation project
+* dubbo-doc-core: Responsible for annotation analysis and document information acquisition interface (Dubbo API)
+* dubbo-doc-ui-server: Web service, responsible for displaying doc and providing testing function
+* dubbo-doc-console: The front-end project will be packaged into Dubbo doc UI server project when it is published
+* dubbo-doc-examples: Use example
+* readmeImgs: Pictures used by README.md
+
+## Major dependent version
+* spring-boot: 2.3.4.RELEASE
+* dubbo: apache dubbo 2.7.8
+* icework in front(iceworks 4.0)
+
+## What did Dubbo Doc do ?
+### Annotations
+* Define annotations to describe interfaces and parameters
+### In Dubbo projects that need to generate documentation and tests
+* Parsing annotations and caching
+* Add Dubbo API used by Dubbo doc to obtain interface information
+###  dubbo-doc-ui-server
+* Web service
+* Restful API used by front-end UI to obtain interface information (interface list, information of specified interface)
+* Request the restful API of the Dubbo service (using the method of Dubbo generalization call)
+* Save the test and display it next time (implemented in the Second Edition)
+### dubbo-doc-console(Package to dubbo-doc-ui-server when publishing)
+* Get the interface list and display it according to the specified Dubbo service IP and port (direct connection Dubbo service)
+* Get the interface information according to the specified interface and generate the form with DOC (similar to swagger)
+* Show API request response
\ No newline at end of file
diff --git a/dubbo-api-docs/README_ch.md b/dubbo-api-docs/README_ch.md
new file mode 100644
index 0000000..91351ef
--- /dev/null
+++ b/dubbo-api-docs/README_ch.md
@@ -0,0 +1,130 @@
+# dubboDoc
+
+[English](./README.md)
+
+[Gitee镜像](https://gitee.com/213539/dubboDoc)
+
+dubbo 接口文档、测试工具,根据注解生成文档,并提供测试功能.
+
+功能参考 swagger+springfox, 只需要加一些注解就能生成类似swagger的文档, 不会把非web的dubbo项目变为web项目.
+
+欢迎大家吐槽~
+
+目前第一版功能比较粗糙(界面也粗糙),用户体验不是很好,后面会慢慢优化,也欢迎各种PR~
+
+```
+在测试dubbo提供者的时候,一直在想如果dubbo有一个类似swagger的文档+测试工具就好了.
+也找了一下,找到的几个都是基于springfox的,会在dubbo项目中加一些restful接口,
+如果你的dubbo服务本身就是通过web容器启动或者混合有web项目那还好.
+但是我这边的dubbo项目都是非web项目,对于有强迫症的我来说,为了文档要把项目变成web项目有点无法接受,就有了自己动手的想法...
+```
+## 版本规划
+### 第一版
+* 解析注解并生成界面
+* 不太友好的使用界面(没有处理一些异常)
+### 第二版
+* 放json的文本域找一个合适的json编辑器替换,校验json格式
+* 增加标签页
+* 能保存测试,方便下次直接加载测试
+* 部分异常处理为友好的文字提示
+* 增加 remark.md 并在前端展示
+* 增加 changelog.md 并在前端展示
+### 后续版本
+* 根据自用产生的需求和issue规划
+* 根据dubbo升级情况规划
+## 注册中心支持
+* 理论上dubbo支持的所有注册中心都支持
+
+## 如何使用?
+1. dubbo项目的方法参数中加上 dubbo doc注解
+   * dubbo提供者项目引入 dubbo-doc-core
+   * 如果dubbo的接口和参数是一个单独的jar包项目,引入dubbo-doc-annotations
+   
+### 当前版本: 同Dubbo版本号
+```
+<dependency>
+    <groupId>org.apache.dubbo</groupId>
+    <artifactId>dubbo-api-docs-annotations</artifactId>
+    <version>${dubbo-version}</version>
+</dependency>
+
+<dependency>
+    <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-api-docs-core</artifactId>
+    <version>${dubbo-version}</version>
+</dependency>
+```
+2.下载 dubbo-doc-ui-server [下载地址](https://github.com/KeRan213539/dubboDoc/releases)
+
+[国内用户可到码云下载](https://gitee.com/213539/dubboDoc/releases)
+
+3. 启动 dubbo-doc-ui-server
+
+4. 访问: http:// localhost:8888
+   * application.yml 中可以修改端口
+   * swagger-ui http:// localhost:8888/swagger-ui.html
+### 注解使用
+* @DubboApiModule 类注解: dubbo接口模块信息,用于标注一个接口类模块的用途
+    * value: 模块名称
+    * apiInterface: 提供者实现的接口
+    * version: 模块版本
+* @DubboApi 方法注解: dubbo 接口信息,用于标注一个接口的用途
+    * value: 接口名称
+    * description: 接口描述(可使用html标签)
+    * version: 接口版本
+    * responseClassDescription: 响应的数据的描述
+* @RequestParam 类属性/方法参数注解:标注请求参数
+    * value: 参数名
+    * required: 是否必传参数
+    * description: 参数描述
+    * example: 参数示例
+    * defaultValue: 参数默认值
+    * allowableValues: 允许的值,设置该属性后界面上将对参数生成下拉列表
+        * 注:使用该属性后将生成下拉选择框
+        * boolean 类型的参数不用设置该属性,将默认生成 true/false 的下拉列表
+        * 枚举类型的参数会自动生成下拉列表,如果不想开放全部的枚举值,可以单独设置此属性.
+* @ResponseProperty 类属性注解: 标注响应参数
+    * value: 参数名
+    * example: 示例
+### dubbo-doc-ui
+* 获取接口列表直连: 由于可能不同功能的dubbo服务都会注册到同一个注册中心,但是dubbo doc
+使用的接口名是一样的,所以dubbo doc的接口采用直连方式以获取到不同功能服务的不同接口列表
+* 测试可以直连或者走注册中心
+### swagger-ui TODO
+
+### 使用注意
+* 响应bean(接口的返回类型)支持自定义泛型, 但只支持一个泛型占位符
+* 关于Map的使用:Map的key只能用基本数据类型.如果Map的key不是基础数据类型,生成的
+就不是标准json格式,会出异常
+* 接口的同步/异步取自 org.apache.dubbo.config.annotation.Service.async
+
+## 项目结构
+* dubbo-doc-annotations: 文档生成辅助注解项目
+* dubbo-doc-core: 负责注解解析,文档信息获取接口(dubbo接口)
+* dubbo-doc-ui-server: web服务,负责展示doc,并提供测试功能
+* dubbo-doc-console: 前端项目, 发布时会打包到 dubbo-doc-ui-server 项目中
+* dubbo-doc-examples: 使用示例
+* readmeImgs: README.md 用到的图片
+
+## 主要依赖版本
+* spring-boot: 2.3.4.RELEASE
+* dubbo: apache dubbo 2.7.8
+* 前端使用飞冰(iceworks 4.0)
+
+## Dubbo Doc 做了什么?
+### 注解
+* 定义一些注解用于描述接口和参数的注解
+### 在需要生成文档和测试的 dubbo 项目中
+* 解析注解并缓存
+* 增加dubbo doc使用的获取接口信息的 dubbo 接口
+###  dubbo-doc-ui-server
+* web服务
+* 前端ui使用的获取接口信息的 web 接口(接口列表, 指定接口的信息)
+* 请求 dubbo 服务的web接口(使用 dubbo 泛化调用的方式)
+* 保存测试,并可在下次展现(第二版实现)
+### dubbo-doc-console(发布时打包到 dubbo-doc-ui-server 中)
+* 根据指定的dubbo服务IP和端口获取接口列表并展示(直连dubbo服务)
+* 根据指定的接口获取接口信息并生成带doc的表单(类似swagger)
+* 展示接口请求的响应
+
+![界面](https://github.com/KeRan213539/dubboDoc/blob/develop/readmeImgs/DubboDoc.png)
\ No newline at end of file
diff --git a/dubbo-api-docs/dubbo-api-docs-annotations/pom.xml b/dubbo-api-docs/dubbo-api-docs-annotations/pom.xml
new file mode 100644
index 0000000..3437ad5
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-annotations/pom.xml
@@ -0,0 +1,35 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.dubbo</groupId>
+        <artifactId>dubbo-api-docs</artifactId>
+        <version>2.7.9-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>dubbo-api-docs-annotations</artifactId>
+
+    <dependencies>
+        
+    </dependencies>
+
+
+</project>
diff --git a/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/ApiDoc.java b/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/ApiDoc.java
new file mode 100644
index 0000000..f55c4c9
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/ApiDoc.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * dubbo api docs annotation,use to label of api.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 14:46
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+@Documented
+public @interface ApiDoc {
+
+    /**
+     * api name.
+     */
+    String value();
+
+    /**
+     * api description(HTML tags available).
+     */
+    String description() default "";
+
+    /**
+     * api version.
+     */
+    String version() default "";
+
+    /**
+     * response class description.
+     */
+    String responseClassDescription() default "";
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/ApiModule.java b/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/ApiModule.java
new file mode 100644
index 0000000..27d2bdc
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/ApiModule.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * api module, used to mark the purpose of an interface class module.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 14:51
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@Documented
+public @interface ApiModule {
+
+    /**
+     * module name
+     */
+    String value();
+
+    /**
+     * dubbo api interface class
+     */
+    Class<?> apiInterface();
+
+    /**
+     * module version
+     */
+    String version() default "";
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/RequestParam.java b/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/RequestParam.java
new file mode 100644
index 0000000..a42f765
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/RequestParam.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Dimension request parameter.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 14:48
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.PARAMETER})
+@Documented
+@Inherited
+public @interface RequestParam {
+
+    /**
+     * param name
+     */
+    String value();
+
+    /**
+     * required
+     */
+    boolean required() default false;
+
+    /**
+     * description(HTML tags available)
+     */
+    String description() default "";
+
+    /**
+     * example(HTML tags available)
+     */
+    String example() default "";
+
+    /**
+     * default value
+     */
+    String defaultValue() default "";
+
+    /**
+     * Allowed values. After setting this property, a drop-down list will be generated for the parameter <br />
+     * Note: a drop-down selection box will be generated after using this property<br />
+     * 1. Parameters of boolean type do not need to be set with this property. A drop-down list of true / false will be generated by default<br />
+     * 2. Parameters of enumeration type will automatically generate a drop-down list. If you do not want to open all enumeration values, you can set this property separately.
+     */
+    String[] allowableValues() default {};
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/ResponseProperty.java b/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/ResponseProperty.java
new file mode 100644
index 0000000..f18c184
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-annotations/src/main/java/org/apache/dubbo/apidocs/annotations/ResponseProperty.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Dimension response property.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 14:50
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+@Documented
+@Inherited
+public @interface ResponseProperty {
+
+    /**
+     * property name
+     */
+    String value();
+
+    /**
+     * example
+     */
+    String example() default "";
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-core/pom.xml b/dubbo-api-docs/dubbo-api-docs-core/pom.xml
new file mode 100644
index 0000000..c251cd2
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-core/pom.xml
@@ -0,0 +1,71 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.dubbo</groupId>
+        <artifactId>dubbo-api-docs</artifactId>
+        <version>2.7.9-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>dubbo-api-docs-core</artifactId>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-api-docs-annotations</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo</artifactId>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot</artifactId>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>compile</scope>
+        </dependency>
+
+    </dependencies>
+
+
+</project>
diff --git a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/EnableDubboApiDocs.java b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/EnableDubboApiDocs.java
new file mode 100644
index 0000000..435a056
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/EnableDubboApiDocs.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs;
+
+import org.apache.dubbo.apidocs.core.DubboApiDocsAnnotationScanner;
+
+import org.springframework.context.annotation.Import;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Enable dubbo api doc.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 17:48
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@Documented
+@Inherited
+@Import({DubboApiDocsAnnotationScanner.class})
+public @interface EnableDubboApiDocs {
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/DubboApiDocsAnnotationScanner.java b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/DubboApiDocsAnnotationScanner.java
new file mode 100644
index 0000000..a089805
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/DubboApiDocsAnnotationScanner.java
@@ -0,0 +1,346 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.core;
+
+import org.apache.dubbo.apidocs.core.beans.HtmlTypeEnum;
+import org.apache.dubbo.apidocs.core.beans.ParamBean;
+import org.apache.dubbo.apidocs.core.providers.DubboDocProviderImpl;
+import org.apache.dubbo.apidocs.core.providers.IDubboDocProvider;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.apache.dubbo.config.annotation.Service;
+import org.apache.dubbo.apidocs.annotations.*;
+import org.apache.dubbo.apidocs.utils.ClassTypeUtil;
+
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Scan and process dubbo doc annotations.
+ *
+ * @author klw(213539 @ qq.com)
+ * 2020/10/29 17:55
+ */
+@Slf4j
+@Import({DubboDocProviderImpl.class})
+public class DubboApiDocsAnnotationScanner implements ApplicationListener<ApplicationReadyEvent> {
+
+    @Autowired
+    private ApplicationContext applicationContext;
+
+    @Autowired
+    private ApplicationConfig application;
+
+    @Autowired
+    private RegistryConfig registry;
+
+    @Autowired
+    private ProtocolConfig protocol;
+
+    @Override
+    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
+        // Register dubbo doc provider
+        IDubboDocProvider dubboDocProvider = applicationContext.getBean(IDubboDocProvider.class);
+        exportDubboService(IDubboDocProvider.class, dubboDocProvider, false);
+
+        log.info("================= Dubbo API Docs--Start scanning and processing doc annotations ================");
+
+        Map<String, Object> apiModules = applicationContext.getBeansWithAnnotation(ApiModule.class);
+        apiModules.forEach((key, apiModuleTemp) -> {
+            Class<?> apiModuleClass;
+            if (AopUtils.isAopProxy(apiModuleTemp)) {
+                apiModuleClass = AopUtils.getTargetClass(apiModuleTemp);
+            } else {
+                apiModuleClass = apiModuleTemp.getClass();
+            }
+            ApiModule moduleAnn = apiModuleClass.getAnnotation(ApiModule.class);
+            if (!apiModuleClass.isAnnotationPresent(Service.class) && !apiModuleClass.isAnnotationPresent(DubboService.class)) {
+                log.warn(
+                        "【Warning】{} @ApiModule annotation is used, but it is not a dubbo provider (without {} annotation)",
+                        apiModuleClass.getName(), Service.class.getName() + " or " + DubboService.class.getName());
+                return;
+            }
+            boolean async;
+            if (apiModuleClass.isAnnotationPresent(Service.class)) {
+                Service dubboService = apiModuleClass.getAnnotation(Service.class);
+                async = dubboService.async();
+            } else {
+                DubboService dubboService = apiModuleClass.getAnnotation(DubboService.class);
+                async = dubboService.async();
+            }
+            Map<String, Object> moduleCacheItem = new HashMap<>(4);
+            DubboApiDocsCache.addApiModule(moduleAnn.apiInterface().getCanonicalName(), moduleCacheItem);
+            //module name
+            moduleCacheItem.put("moduleChName", moduleAnn.value());
+            //interface name containing package path
+            moduleCacheItem.put("moduleClassName", moduleAnn.apiInterface().getCanonicalName());
+            //module version
+            moduleCacheItem.put("moduleVersion", moduleAnn.version());
+
+            Method[] apiModuleMethods = apiModuleClass.getMethods();
+            // API basic information list in module cache
+            List<Map<String, Object>> moduleApiList = new ArrayList<>(apiModuleMethods.length);
+            moduleCacheItem.put("moduleApiList", moduleApiList);
+            for (Method method : apiModuleMethods) {
+                if (method.isAnnotationPresent(ApiDoc.class)) {
+                    processApiDocAnnotation(method, moduleApiList, moduleAnn, async, moduleCacheItem);
+                }
+            }
+        });
+        log.info("================= Dubbo API Docs-- doc annotations scanning and processing completed ================");
+    }
+
+    private void processApiDocAnnotation(Method method, List<Map<String, Object>> moduleApiList, ApiModule moduleAnn,
+                                         boolean async, Map<String, Object> moduleCacheItem) {
+        ApiDoc dubboApi = method.getAnnotation(ApiDoc.class);
+
+        // API basic information in API list in module
+        Map<String, Object> apiListItem = new HashMap<>(4);
+        moduleApiList.add(apiListItem);
+        //API method name
+        apiListItem.put("apiName", method.getName());
+        //API name
+        apiListItem.put("apiChName", dubboApi.value());
+        // API description
+        apiListItem.put("description", dubboApi.description());
+        //API version
+        apiListItem.put("apiVersion", dubboApi.version());
+        //Description of API return data
+        apiListItem.put("apiRespDec", dubboApi.responseClassDescription());
+
+        // Interface parameters and response information
+        Map<String, Object> apiParamsAndResp = new HashMap<>(2);
+        DubboApiDocsCache.addApiParamsAndResp(
+                moduleAnn.apiInterface().getCanonicalName() + "." + method.getName(), apiParamsAndResp);
+
+        Class<?>[] argsClass = method.getParameterTypes();
+        Annotation[][] argsAnns = method.getParameterAnnotations();
+        Parameter[] parameters = method.getParameters();
+        List<Map<String, Object>> paramList = new ArrayList<>(argsClass.length);
+        apiParamsAndResp.put("async", async);
+        apiParamsAndResp.put("apiName", method.getName());
+        apiParamsAndResp.put("apiChName", dubboApi.value());
+        apiParamsAndResp.put("apiVersion", dubboApi.version());
+        apiParamsAndResp.put("apiRespDec", dubboApi.responseClassDescription());
+        apiParamsAndResp.put("apiModelClass", moduleCacheItem.get("moduleClassName"));
+        apiParamsAndResp.put("params", paramList);
+        apiParamsAndResp.put("response", ClassTypeUtil.calss2Json(method.getGenericReturnType(), method.getReturnType()));
+        for (int i = 0; i < argsClass.length; i++) {
+            Class<?> argClass = argsClass[i];
+            Annotation[] argAnns = argsAnns[i];
+            Map<String, Object> prarmListItem = new HashMap<>(2);
+            paramList.add(prarmListItem);
+            prarmListItem.put("prarmType", argClass.getCanonicalName());
+            prarmListItem.put("prarmIndex", i);
+            RequestParam requestParam = null;
+            // Handling @RequestParam annotations on parameters
+            for (Annotation ann : argAnns) {
+                if (ann instanceof RequestParam) {
+                    requestParam = (RequestParam) ann;
+                }
+            }
+            ParamBean paramBean = this.processHtmlType(argClass, requestParam, null);
+            if (paramBean == null) {
+                // Not a basic type, handling properties in method parameters
+                List<ParamBean> apiParamsList = processField(argClass);
+                if (apiParamsList != null && !apiParamsList.isEmpty()) {
+                    prarmListItem.put("prarmInfo", apiParamsList);
+                }
+            } else {
+                // Is the basic type
+                Parameter methodParameter = parameters[i];
+                prarmListItem.put("name", methodParameter.getName());
+                prarmListItem.put("htmlType", paramBean.getHtmlType().name());
+                prarmListItem.put("allowableValues", paramBean.getAllowableValues());
+                if (requestParam != null) {
+
+                    // Handling requestparam annotations on parameters
+                    prarmListItem.put("nameCh", requestParam.value());
+                    prarmListItem.put("description", requestParam.description());
+                    prarmListItem.put("example", requestParam.example());
+                    prarmListItem.put("defaultValue", requestParam.defaultValue());
+                    prarmListItem.put("required", requestParam.required());
+                } else {
+                    prarmListItem.put("required", false);
+                }
+            }
+        }
+    }
+
+    /**
+     * For the attributes in the method parameters, only one layer is processed.
+     * The deeper layer is directly converted to JSON, and the deeper layer is up to 5 layers
+     */
+    private List<ParamBean> processField(Class<?> argClass) {
+
+        List<ParamBean> apiParamsList = new ArrayList(16);
+        // get all fields
+        List<Field> allFields = ClassTypeUtil.getAllFields(null, argClass);
+        for (Field field : allFields) {
+            ParamBean paramBean = new ParamBean();
+            paramBean.setName(field.getName());
+            paramBean.setJavaType(field.getType().getCanonicalName());
+            RequestParam requestParam = null;
+            if (field.isAnnotationPresent(RequestParam.class)) {
+                // Handling @RequestParam annotations on properties
+                requestParam = field.getAnnotation(RequestParam.class);
+                paramBean.setNameCh(requestParam.value());
+                paramBean.setRequired(requestParam.required());
+                paramBean.setDescription(requestParam.description());
+                paramBean.setExample(requestParam.example());
+                paramBean.setDefaultValue(requestParam.defaultValue());
+            } else {
+                paramBean.setRequired(false);
+            }
+
+            if (this.processHtmlType(field.getType(), requestParam, paramBean) == null) {
+                // Not a basic type, handle as JSON
+                Object objResult = ClassTypeUtil.initClassTypeWithDefaultValue(
+                        field.getGenericType(), field.getType(), 0);
+                if (!ClassTypeUtil.isBaseType(objResult)) {
+                    paramBean.setHtmlType(HtmlTypeEnum.TEXT_AREA);
+                    paramBean.setSubParamsJson(JSON.toJSONString(objResult, ClassTypeUtil.FAST_JSON_FEATURES));
+                }
+            }
+            apiParamsList.add(paramBean);
+        }
+        return apiParamsList;
+    }
+
+    /**
+     * Determine what HTML form elements to use.
+     * 2020/10/29 18:24
+     *
+     * @param classType  classType
+     * @param annotation annotation
+     * @param prarm      prarm
+     * @return org.apache.dubbo.apidocs.core.beans.ParamBean
+     */
+    private ParamBean processHtmlType(Class<?> classType, RequestParam annotation, ParamBean prarm) {
+        if (prarm == null) {
+            prarm = new ParamBean();
+        }
+        if (annotation != null) {
+            prarm.setAllowableValues(annotation.allowableValues());
+        }
+        // Is there any allowed values
+        boolean hasAllowableValues = (prarm.getAllowableValues() != null && prarm.getAllowableValues().length > 0);
+        // Processed or not
+        boolean processed = false;
+        if (Integer.class.isAssignableFrom(classType)) {
+            prarm.setHtmlType(HtmlTypeEnum.NUMBER_INTEGER);
+            processed = true;
+        } else if (Byte.class.isAssignableFrom(classType)) {
+            prarm.setHtmlType(HtmlTypeEnum.TEXT_BYTE);
+            processed = true;
+        } else if (Long.class.isAssignableFrom(classType)) {
+            prarm.setHtmlType(HtmlTypeEnum.NUMBER_INTEGER);
+            processed = true;
+        } else if (Double.class.isAssignableFrom(classType)) {
+            prarm.setHtmlType(HtmlTypeEnum.NUMBER_DECIMAL);
+            processed = true;
+        } else if (Float.class.isAssignableFrom(classType)) {
+            prarm.setHtmlType(HtmlTypeEnum.NUMBER_DECIMAL);
+            processed = true;
+        } else if (String.class.isAssignableFrom(classType)) {
+            prarm.setHtmlType(HtmlTypeEnum.TEXT);
+            processed = true;
+        } else if (Character.class.isAssignableFrom(classType)) {
+            prarm.setHtmlType(HtmlTypeEnum.TEXT_CHAR);
+            processed = true;
+        } else if (Short.class.isAssignableFrom(classType)) {
+            prarm.setHtmlType(HtmlTypeEnum.NUMBER_INTEGER);
+            processed = true;
+        }
+        if (processed) {
+            // Processed, time to return
+            if (hasAllowableValues) {
+                // Allowed values has value, change to select
+                prarm.setHtmlType(HtmlTypeEnum.SELECT);
+            }
+            return prarm;
+        }
+
+        // haven't dealt with it. Go on
+        if (Boolean.class.isAssignableFrom(classType)) {
+            prarm.setHtmlType(HtmlTypeEnum.SELECT);
+            // Boolean can only be true / false. No matter what the previous allowed value is, it is forced to replace
+            prarm.setAllowableValues(new String[]{"true", "false"});
+            processed = true;
+        } else if (Enum.class.isAssignableFrom(classType)) {
+            // process enum
+            prarm.setHtmlType(HtmlTypeEnum.SELECT);
+            if (!hasAllowableValues) {
+                // If there is no optional value, it is taken from the enumeration.
+                //TODO If there is an optional value, it is necessary
+                // to check whether the optional value matches the enumeration. It is add it later
+                Object[] enumConstants = classType.getEnumConstants();
+                String[] enumAllowableValues = new String[enumConstants.length];
+                try {
+                    Method getNameMethod = classType.getMethod("name");
+                    for (int i = 0; i < enumConstants.length; i++) {
+                        Object obj = enumConstants[i];
+                        enumAllowableValues[i] = (String) getNameMethod.invoke(obj);
+                    }
+                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+                    log.error("", e);
+                }
+                prarm.setAllowableValues(enumAllowableValues);
+            }
+            processed = true;
+        }
+        if (processed) {
+            return prarm;
+        }
+        return null;
+    }
+
+    /**
+     * export dubbo service for dubbo doc
+     */
+    private <I, T> void exportDubboService(Class<I> serviceClass, T serviceImplInstance, boolean async) {
+        ServiceConfig<T> service = new ServiceConfig<>();
+        service.setApplication(application);
+        service.setRegistry(registry);
+        service.setProtocol(protocol);
+        service.setInterface(serviceClass);
+        service.setRef(serviceImplInstance);
+        service.setAsync(async);
+//        service.setVersion("1.0.0");
+        service.export();
+    }
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/DubboApiDocsCache.java b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/DubboApiDocsCache.java
new file mode 100644
index 0000000..e3b5b6d
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/DubboApiDocsCache.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.core;
+
+import org.apache.dubbo.apidocs.utils.ClassTypeUtil;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * dubbo doc cache.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 17:40
+ */
+public class DubboApiDocsCache {
+
+    /**
+     * module cache.
+     */
+    private static Map<String, Map<String, Object>> apiModulesCache = new ConcurrentHashMap<>(16);
+    /**
+     * module cache.
+     */
+    private static Map<String, String> apiModulesStrCache = new ConcurrentHashMap<>(16);
+
+    /**
+     * API details cache in module.
+     */
+    private static Map<String, Map<String, Object>> apiParamsAndRespCache = new ConcurrentHashMap<>(16);
+    /**
+     * API details cache in module.
+     */
+    private static Map<String, String> apiParamsAndRespStrCache = new ConcurrentHashMap<>(16);
+
+    private static String allApiModuleInfo = null;
+
+    public static void addApiModule(String key, Map<String, Object> moduleCacheItem){
+        apiModulesCache.put(key, moduleCacheItem);
+    }
+
+    public static void addApiParamsAndResp(String key, Map<String, Object> apiParamsAndResp){
+        apiParamsAndRespCache.put(key, apiParamsAndResp);
+    }
+
+    public static Map<String, Object> getApiModule(String key){
+        return apiModulesCache.get(key);
+    }
+
+    public static String getApiModuleStr(String key){
+        String result = apiModulesStrCache.get(key);
+        if(result == null){
+            Map<String, Object> temp = apiModulesCache.get(key);
+            if(temp != null) {
+                result = JSON.toJSONString(temp, ClassTypeUtil.FAST_JSON_FEATURES);
+                apiModulesStrCache.put(key, result);
+            }
+        }
+        return result;
+    }
+
+    public static Map<String, Object> getApiParamsAndResp(String key){
+        return apiParamsAndRespCache.get(key);
+    }
+
+    public static String getApiParamsAndRespStr(String key){
+        String result = apiParamsAndRespStrCache.get(key);
+        if(result == null){
+            Map<String, Object> temp = apiParamsAndRespCache.get(key);
+            if(temp != null) {
+                result = JSON.toJSONString(temp, ClassTypeUtil.FAST_JSON_FEATURES);
+                apiParamsAndRespStrCache.put(key, result);
+            }
+        }
+        return result;
+    }
+
+    public static String getAllApiModuleInfo(){
+        if(allApiModuleInfo == null){
+            List<Map<String, Object>> tempList = new ArrayList<>(apiModulesCache.size());
+            apiModulesCache.forEach((k, v) -> {
+                tempList.add(v);
+            });
+            allApiModuleInfo = JSON.toJSONString(tempList, ClassTypeUtil.FAST_JSON_FEATURES);
+        }
+        return allApiModuleInfo;
+    }
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/beans/HtmlTypeEnum.java b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/beans/HtmlTypeEnum.java
new file mode 100644
index 0000000..37303d6
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/beans/HtmlTypeEnum.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.core.beans;
+
+/**
+ * html type enum.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 16:56
+ */
+public enum HtmlTypeEnum {
+
+    /**
+     * Textbox.
+     */
+    TEXT,
+
+    /**
+     * Textbox, This type will be converted to byte before calling dubbo API.
+     */
+    TEXT_BYTE,
+
+    /**
+     * Textbox, will be limited to one character. This type will be converted to char before calling dubbo API.
+     */
+    TEXT_CHAR,
+
+    /**
+     * Numeric input box, integer.
+     */
+    NUMBER_INTEGER,
+
+    /**
+     * Numeric input box, decimal.
+     */
+    NUMBER_DECIMAL,
+
+    /**
+     * Drop down selection box.
+     */
+    SELECT,
+
+    /**
+     * Text area, which is generally used to show the JSON string of the Java Bean contained in the parameter.
+     */
+    TEXT_AREA,
+    ;
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/beans/ParamBean.java b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/beans/ParamBean.java
new file mode 100644
index 0000000..abac9a8
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/beans/ParamBean.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.core.beans;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * Parameter bean corresponding to {@link org.apache.dubbo.apidocs.annotations.RequestParam}, for caching.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 17:32
+ */
+@Getter
+@Setter
+public class ParamBean {
+
+    /**
+     * parameter name.
+     */
+    private String name;
+
+    /**
+     * parameter name, for display.
+     */
+    private String nameCh;
+
+    /**
+     * required.
+     */
+    private Boolean required;
+
+    /**
+     * description.
+     */
+    private String description;
+
+    /**
+     * example.
+     */
+    private String example;
+
+    /**
+     * default value.
+     */
+    private String defaultValue;
+
+    /**
+     * java type of parameter.
+     */
+    private String javaType;
+
+    /**
+     * What HTML elements should this parameter display.
+     */
+    private HtmlTypeEnum htmlType;
+
+    /**
+     * allowed values
+     */
+    private String[] allowableValues;
+
+    /**
+     * If the parameter in a request bean is not a basic data type,
+     * the {@link #subParams} will have a value.
+     * Because the HTML form is not easy to display this parameter,
+     * it will be displayed as a text area, and the JSON string of this parameter will be filled in.
+     */
+    @JSONField(serialize = false)
+    private List<ParamBean> subParams;
+
+    /**
+     * JSON string corresponding to {@link #subParams}.
+     */
+    private String subParamsJson;
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/providers/DubboDocProviderImpl.java b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/providers/DubboDocProviderImpl.java
new file mode 100644
index 0000000..d8cfb2b
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/providers/DubboDocProviderImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.core.providers;
+
+import org.apache.dubbo.apidocs.core.DubboApiDocsCache;
+import org.apache.dubbo.config.annotation.DubboService;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * The api implementation of Dubbo doc.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 17:38
+ */
+@Slf4j
+@DubboService
+public class DubboDocProviderImpl implements IDubboDocProvider {
+
+    @Override
+    public String apiModuleList() {
+        return DubboApiDocsCache.getAllApiModuleInfo();
+    }
+
+    @Override
+    public String apiModuleInfo(String apiInterfaceClassName) {
+        return DubboApiDocsCache.getApiModuleStr(apiInterfaceClassName);
+    }
+
+    @Override
+    public String apiParamsResponseInfo(String apiInterfaceClassNameMethodName) {
+        return DubboApiDocsCache.getApiParamsAndRespStr(apiInterfaceClassNameMethodName);
+    }
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/providers/IDubboDocProvider.java b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/providers/IDubboDocProvider.java
new file mode 100644
index 0000000..38899dc
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/providers/IDubboDocProvider.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.core.providers;
+
+/**
+ * The api used by Dubbo doc, get the parsed API information.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 16:57
+ */
+public interface IDubboDocProvider {
+
+    /**
+     * Get basic information of all modules, excluding API parameter information.
+     * 2020/10/30 16:38
+     * @param
+     * @return java.lang.String
+     */
+    String apiModuleList();
+
+    /**
+     * Get module information according to the complete class name of Dubbo provider interface.
+     * 2020/10/30 16:38
+     * @param apiInterfaceClassName
+     * @return java.lang.String
+     */
+    String apiModuleInfo(String apiInterfaceClassName);
+
+    /**
+     * Get method parameters and return information according to the complete class name and method name of Dubbo provider interface.
+     * 2020/10/30 16:38
+     * @param apiInterfaceClassNameMethodName
+     * @return java.lang.String
+     */
+    String apiParamsResponseInfo(String apiInterfaceClassNameMethodName);
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/utils/ClassTypeUtil.java b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/utils/ClassTypeUtil.java
new file mode 100644
index 0000000..cdb872c
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/utils/ClassTypeUtil.java
@@ -0,0 +1,307 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
+
+import java.lang.reflect.*;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import org.apache.dubbo.apidocs.annotations.*;
+
+/**
+ * Java class tool class, special for Dubbo doc.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 18:08
+ */
+@Slf4j
+public class ClassTypeUtil {
+
+    /**
+     * fastjson features
+     */
+    public static SerializerFeature[] FAST_JSON_FEATURES = {
+            //Whether to output the field with null value. The default value is false.
+            SerializerFeature.WriteMapNullValue,
+            //If the list field is null, the output is [], not null
+            SerializerFeature.WriteNullListAsEmpty,
+            //If the character type field is null, the output is' ', not null
+            SerializerFeature.WriteNullStringAsEmpty,
+            //If the Boolean field is null, the output is false instead of null
+            SerializerFeature.WriteNullBooleanAsFalse,
+            // Null number output 0
+            SerializerFeature.WriteNullNumberAsZero,
+            //Eliminate the problem of circular reference to the same object.
+            // The default value is false (it may enter a dead cycle if not configured)
+            SerializerFeature.DisableCircularReferenceDetect,
+            // Use. Name() to handle enumeration
+            SerializerFeature.WriteEnumUsingName
+    };
+
+    private static final int PROCESS_COUNT_MAX = 10;
+
+    private static final String GENERIC_START_SYMBOL = "<";
+
+    public static String calss2Json(Type genericType, Class<?> classType) {
+        Object obj = initClassTypeWithDefaultValue(genericType, classType, 0);
+        return JSON.toJSONString(obj, FAST_JSON_FEATURES);
+    }
+
+    /**
+     * Instantiate class and its fields.
+     * 2020/10/29 18:08
+     * @param genericType genericType
+     * @param classType classType
+     * @param processCount processCount
+     * @return java.lang.Object
+     */
+    public static Object initClassTypeWithDefaultValue(Type genericType, Class<?> classType, int processCount) {
+        if (processCount >= PROCESS_COUNT_MAX) {
+            log.warn("The depth of bean has exceeded 10 layers, the deeper layer will be ignored! " +
+                    "Please modify the parameter structure or check whether there is circular reference in bean!");
+            return null;
+        }
+        processCount++;
+
+        Object initResult = initClassTypeWithDefaultValueNoProceeField(genericType, classType, processCount);
+        if (null != initResult) {
+            return initResult;
+        }
+
+        Map<String, Object> result = new HashMap<>(16);
+        // get all fields
+        List<Field> allFields = getAllFields(null, classType);
+        for (Field field2 : allFields) {
+            if ("serialVersionUID".equals(field2.getName())) {
+                continue;
+            }
+            if (String.class.isAssignableFrom(field2.getType())) {
+                if (field2.isAnnotationPresent(RequestParam.class)) {
+                    RequestParam requestParam = field2.getAnnotation(RequestParam.class);
+                    result.put(field2.getName(), requestParam.value());
+                } else if (field2.isAnnotationPresent(ResponseProperty.class)) {
+                    ResponseProperty responseProperty = field2.getAnnotation(ResponseProperty.class);
+                    StringBuilder strValue = new StringBuilder(responseProperty.value());
+                    if (StringUtils.isNotBlank(responseProperty.example())) {
+                        strValue.append("【example: ").append(responseProperty.example()).append("】");
+                    }
+                    result.put(field2.getName(), strValue.toString());
+                } else {
+                    // It's string, but there's no annotation
+                    result.put(field2.getName(), initClassTypeWithDefaultValue(field2.getGenericType(), field2.getType(), processCount));
+                }
+            } else {
+                // Check if the type of the property is generic
+                if ("T".equals(field2.getGenericType().getTypeName())) {
+                    // The type of the attribute is generic. Find the generic from the definition of
+                    // the class in which the attribute is located
+                    ParameterizedType pt = (ParameterizedType) genericType;
+                    Type[] actualTypeArguments = pt.getActualTypeArguments();
+                    if (actualTypeArguments.length > 0) {
+                        if (actualTypeArguments.length == 1) {
+                            result.put(field2.getName(), initClassTypeWithDefaultValue(
+                                    makeParameterizedType(actualTypeArguments[0].getTypeName()),
+                                    makeClass(pt.getActualTypeArguments()[0].getTypeName()), processCount));
+                        } else {
+                            log.warn("{}#{} generics are not supported temporarily. " +
+                                    "This property will be ignored", classType.getName(), field2.getName());
+                        }
+                    } else {
+                        result.put(field2.getName(), initClassTypeWithDefaultValue(field2.getGenericType(), field2.getType(), processCount));
+                    }
+                } else {
+                    // Not generic
+                    result.put(field2.getName(), initClassTypeWithDefaultValue(field2.getGenericType(), field2.getType(), processCount));
+                }
+            }
+        }
+        return result;
+    }
+
+    private static Object initClassTypeWithDefaultValueNoProceeField(Type genericType, Class<?> classType, int processCount) {
+        if (Integer.class.isAssignableFrom(classType)) {
+            return 0;
+        } else if (Byte.class.isAssignableFrom(classType)) {
+            return (byte) 0;
+        } else if (Long.class.isAssignableFrom(classType)) {
+            return 0L;
+        } else if (Double.class.isAssignableFrom(classType)) {
+            return 0.0D;
+        } else if (Float.class.isAssignableFrom(classType)) {
+            return 0.0F;
+        } else if (String.class.isAssignableFrom(classType)) {
+            return "";
+        } else if (Character.class.isAssignableFrom(classType)) {
+            return 'c';
+        } else if (Short.class.isAssignableFrom(classType)) {
+            return (short) 0;
+        } else if (Boolean.class.isAssignableFrom(classType)) {
+            return false;
+        } else if (Date.class.isAssignableFrom(classType)) {
+            return "【" + Date.class.getName() + "】yyyy-MM-dd HH:mm:ss";
+        } else if (LocalDate.class.isAssignableFrom(classType)) {
+            return "【" + LocalDate.class.getName() + "】yyyy-MM-dd";
+        } else if (LocalDateTime.class.isAssignableFrom(classType)) {
+            return "【" + LocalDateTime.class.getName() + "】yyyy-MM-dd HH:mm:ss";
+        } else if (Enum.class.isAssignableFrom(classType)) {
+            Object[] enumConstants = classType.getEnumConstants();
+            StringBuilder sb = new StringBuilder("|");
+            try {
+                Method getName = classType.getMethod("name");
+                for (Object obj : enumConstants) {
+                    sb.append(getName.invoke(obj)).append("|");
+                }
+            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+                log.error("", e);
+            }
+            return sb.toString();
+        } else if (classType.isArray()) {
+            Class<?> arrType = classType.getComponentType();
+            Object obj = initClassTypeWithDefaultValue(null, arrType, processCount);
+            return new Object[]{obj};
+        } else if (Collection.class.isAssignableFrom(classType)) {
+            List<Object> list = new ArrayList<>(1);
+            if (genericType == null) {
+                list.add(new Object());
+                return list;
+            }
+            Object obj;
+            if (genericType instanceof ParameterizedType) {
+                ParameterizedType pt = (ParameterizedType) genericType;
+                String subTypeName = pt.getActualTypeArguments()[0].getTypeName();
+                obj = initClassTypeWithDefaultValue(makeParameterizedType(subTypeName), makeClass(subTypeName), processCount);
+                list.add(obj);
+            }
+            return list;
+        } else if (Map.class.isAssignableFrom(classType)) {
+            Map<String, Object> map = new HashMap<>(1);
+            if (genericType == null) {
+                map.put("", new Object());
+                return map;
+            }
+            if (genericType instanceof ParameterizedType) {
+                ParameterizedType pt = (ParameterizedType) genericType;
+                String subTypeName = pt.getActualTypeArguments()[1].getTypeName();
+                Object objValue = initClassTypeWithDefaultValue(makeParameterizedType(subTypeName), makeClass(subTypeName), processCount);
+                map.put("", objValue);
+            }
+            return map;
+        } else if (CompletableFuture.class.isAssignableFrom(classType)) {
+            // process CompletableFuture
+            if (genericType == null) {
+                return new Object();
+            }
+            ParameterizedType pt = (ParameterizedType) genericType;
+            String typeName = pt.getActualTypeArguments()[0].getTypeName();
+            return initClassTypeWithDefaultValue(makeParameterizedType(typeName), makeClass(typeName), processCount);
+        }
+        return null;
+    }
+
+    /**
+     * Check if it is a basic data type.
+     * 2020/10/29 18:09
+     * @param o
+     * @return boolean
+     */
+    public static boolean isBaseType(Object o) {
+        if (o instanceof Integer ||
+                o instanceof Byte ||
+                o instanceof Long ||
+                o instanceof Double ||
+                o instanceof Float ||
+                o instanceof Character ||
+                o instanceof Short ||
+                o instanceof Boolean ||
+                o instanceof String) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Get all fields in the class.
+     * 2020/10/29 18:10
+     * @param fieldList fieldList
+     * @param classz classz
+     * @return java.util.List<java.lang.reflect.Field>
+     */
+    public static List<Field> getAllFields(List<Field> fieldList, Class<?> classz) {
+        if (classz == null) {
+            return fieldList;
+        }
+        if (fieldList == null) {
+            fieldList = new ArrayList<>(Arrays.asList(classz.getDeclaredFields()));
+        } else {
+            fieldList.addAll(Arrays.asList(classz.getDeclaredFields()));
+        }
+        return getAllFields(fieldList, classz.getSuperclass());
+    }
+
+    public static ParameterizedType makeParameterizedType(String typeName) {
+        if (typeName.indexOf(GENERIC_START_SYMBOL) == -1) {
+            return null;
+        }
+        try {
+            Class<?> typeClass;
+            typeClass = Class.forName(typeName.substring(0, typeName.indexOf("<")));
+            String subTypeNames = typeName.substring((typeName.indexOf("<") + 1), (typeName.length() - 1));
+            String[] subTypeNamesArray = subTypeNames.split(",");
+            Type[] subTypes = makeSubClass(subTypeNamesArray);
+            return ParameterizedTypeImpl.make(typeClass, subTypes, null);
+        } catch (ClassNotFoundException e) {
+            log.warn("Exception getting generics in completabilefuture", e);
+            return null;
+        }
+    }
+
+    public static Class<?> makeClass(String className) {
+        className = className.trim();
+        try {
+            if (className.indexOf(GENERIC_START_SYMBOL) == -1) {
+                // CompletableFuture 中的类没有泛型
+                return Class.forName(className);
+            } else {
+                return Class.forName(className.substring(0, className.indexOf("<")));
+            }
+        } catch (ClassNotFoundException e) {
+            log.warn("Exception getting generics in completabilefuture", e);
+            return null;
+        }
+    }
+
+    private static Type[] makeSubClass(String... classNames) {
+        Type[] types;
+        if (classNames != null) {
+            types = new Type[classNames.length];
+            for (int i = 0; i < classNames.length; i++) {
+                String className = classNames[i];
+                types[i] = new SimpleTypeImpl(className);
+            }
+        } else {
+            types = new Type[0];
+        }
+        return types;
+    }
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/utils/SimpleTypeImpl.java b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/utils/SimpleTypeImpl.java
new file mode 100644
index 0000000..a71a468
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/utils/SimpleTypeImpl.java
@@ -0,0 +1,23 @@
+package org.apache.dubbo.apidocs.utils;
+
+import java.lang.reflect.Type;
+
+/**
+ * Simple implementation of {@link Type}.
+ * @author klw(213539@qq.com)
+ * 2020/10/29 14:55
+ */
+public class SimpleTypeImpl implements Type {
+
+    private String typeName;
+
+    public SimpleTypeImpl(String typeName){
+        this.typeName = typeName;
+    }
+
+    @Override
+    public String getTypeName(){
+        return typeName;
+    }
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/pom.xml b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/pom.xml
new file mode 100644
index 0000000..252a1df
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/pom.xml
@@ -0,0 +1,40 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.dubbo.examples.apidocs</groupId>
+        <artifactId>dubbo-api-docs-examples</artifactId>
+        <version>2.7.9-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>examples-api</artifactId>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-api-docs-annotations</artifactId>
+        </dependency>
+        
+    </dependencies>
+
+
+</project>
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/api/IAsyncDemo.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/api/IAsyncDemo.java
new file mode 100644
index 0000000..1d953aa
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/api/IAsyncDemo.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.api;
+
+import org.apache.dubbo.apidocs.examples.params.DemoParamBean1;
+import org.apache.dubbo.apidocs.examples.params.DemoParamBean2;
+import org.apache.dubbo.apidocs.examples.responses.DemoRespBean1;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * asynchronous demo.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 10:13
+ */
+public interface IAsyncDemo {
+
+    /**
+     * @author klw(213539@qq.com)
+     * request and response parameters are beans
+     * @Date 2020/2/4 0:01
+     * @param: param
+     * @return top.klw8.alita.examples.dubbodoc.responses.DemoRespBean1
+     */
+    CompletableFuture<DemoRespBean1> demoApi1(DemoParamBean1 param1, DemoParamBean2 param2);
+
+    /**
+     * @author klw(213539@qq.com)
+     * Map without generics
+     */
+    CompletableFuture<Map> demoApi6();
+
+    /**
+     * @author klw(213539@qq.com)
+     * Map generic with Object
+     */
+    CompletableFuture<Map<Object, Object>> demoApi7();
+
+    /**
+     * @author klw(213539@qq.com)
+     * List without generics
+     */
+    CompletableFuture<List> demoApi10();
+
+    /**
+     * @author klw(213539@qq.com)
+     * List generic with Object
+     */
+    CompletableFuture<List<Object>> demoApi9();
+
+    /**
+     * @author klw(213539@qq.com)
+     * Object
+     */
+    CompletableFuture<Object> demoApi8();
+
+    /**
+     * @author klw(213539@qq.com)
+     * Integer
+     */
+    CompletableFuture<Integer> demoApi11();
+
+
+    /**
+     * @author klw(213539@qq.com)
+     * many generics
+     * @Date 2020/7/30 17:02
+     * @param:
+     * @return java.util.concurrent.CompletableFuture<java.util.List<java.util.List<java.lang.String>>>
+     */
+    CompletableFuture<List<List<String>>> demoApi12();
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/api/ISyncDemo.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/api/ISyncDemo.java
new file mode 100644
index 0000000..f842140
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/api/ISyncDemo.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.api;
+
+import org.apache.dubbo.apidocs.examples.params.DemoParamBean1;
+import org.apache.dubbo.apidocs.examples.params.DemoParamBean2;
+import org.apache.dubbo.apidocs.examples.responses.BaseResponse;
+import org.apache.dubbo.apidocs.examples.responses.DemoRespBean1;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * synchronization demo.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 10:13
+ */
+public interface ISyncDemo {
+
+    /**
+     * request and response parameters are beans
+     * @Date 2020/2/4 0:01
+     * @param: param
+     * @return top.klw8.alita.examples.dubbodoc.responses.DemoRespBean1
+     */
+    DemoRespBean1 demoApi1(DemoParamBean1 param1, DemoParamBean2 param2);
+
+    /**
+     * request and response parameters are Strings
+     * @Date 2020/2/4 0:02
+     * @param: prarm1
+     * @param: prarm2
+     * @return java.lang.String
+     */
+    String demoApi2(String prarm1, String prarm2);
+
+    /**
+     * Without Dubbo doc annotation, no document will be generated
+     * @Date 2020/2/4 0:22
+     * @param: prarm1
+     * @return java.lang.String
+     */
+    String demoApi3(String prarm1);
+
+    /**
+     * Nonparametric method with Dubbo doc annotation
+     * @Date 2020/2/4 0:02
+     * @param:
+     * @return java.lang.String
+     */
+    String demoApi4();
+
+    /**
+     * Use generics in response
+     */
+    BaseResponse<DemoRespBean1> demoApi5();
+
+    /**
+     * Map without generics
+     */
+    Map demoApi6();
+
+    /**
+     * Map generic with Object
+     */
+    Map<Object, Object> demoApi7();
+
+    /**
+     * List without generics
+     */
+    List demoApi10();
+
+    /**
+     * List generic with Object
+     */
+    List<Object> demoApi9();
+
+    /**
+     * Object
+     */
+    Object demoApi8();
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/DemoParamBean1.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/DemoParamBean1.java
new file mode 100644
index 0000000..8617515
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/DemoParamBean1.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.params;
+
+import org.apache.dubbo.apidocs.annotations.RequestParam;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * demo request bean.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 9:58
+ */
+@Getter
+@Setter
+public class DemoParamBean1 {
+
+    @RequestParam("Name")
+    private String name;
+
+    @RequestParam("Age")
+    private Integer age;
+
+    private Boolean man;
+
+    @RequestParam("====subBean")
+    private List<DemoParamBean1SubBean1> subBean;
+
+    @RequestParam("Map")
+    private Map<String, DemoParamBean1SubBean1> subBean2;
+
+    @RequestParam("Array")
+    private String[] strArray;
+
+    @RequestParam("Array 2")
+    private DemoParamBean1SubBean1[] strArray2;
+
+    @RequestParam("Enumeration for test")
+    private TestEnum testEnum;
+
+    private DemoParamBean1SubBean1 subBean3;
+
+    @RequestParam("Map without generics")
+    private Map map1;
+
+    @RequestParam("Map generic with Object")
+    private Map<Object, Object> map2;
+
+    @RequestParam("List without generics")
+    private List list1;
+
+    @RequestParam("List generic with Object")
+    private List<Object> list2;
+
+    @RequestParam("Object")
+    private Object obj1;
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/DemoParamBean1SubBean1.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/DemoParamBean1SubBean1.java
new file mode 100644
index 0000000..d12f73f
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/DemoParamBean1SubBean1.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.params;
+
+import org.apache.dubbo.apidocs.annotations.RequestParam;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Attribute bean in DemoParamBean1.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 9:49
+ */
+@Getter
+@Setter
+public class DemoParamBean1SubBean1 {
+
+    @RequestParam("Sub Name")
+    private String subName;
+
+    @RequestParam("Sub Age")
+    private Integer subAge;
+
+    private TestEnum testEnum;
+
+    // Circular reference for test
+//    @RequestParam("====bean")
+//    private DemoParamBean1 bean;
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/DemoParamBean2.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/DemoParamBean2.java
new file mode 100644
index 0000000..52a64ba
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/DemoParamBean2.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.params;
+
+import org.apache.dubbo.apidocs.annotations.RequestParam;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * demo request bean 2.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 9:57
+ */
+@Getter
+@Setter
+public class DemoParamBean2 {
+
+    @RequestParam(value = "Name 2", allowableValues = {"San Zhang", "Si Li"})
+    private String name2;
+
+    @RequestParam("Age 2")
+    private Double age2;
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/TestBean.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/TestBean.java
new file mode 100644
index 0000000..267ff7f
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/TestBean.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.params;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * test.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 9:57
+ */
+@Getter
+@Setter
+public class TestBean {
+
+    private DemoParamBean1 demoParamBean1;
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/TestEnum.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/TestEnum.java
new file mode 100644
index 0000000..38bb180
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/TestEnum.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.params;
+
+/**
+ * Enumeration for test.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 9:48
+ */
+public enum TestEnum {
+
+    TEST_ENUM_1,
+    TEST_ENUM_2,
+    TEST_ENUM_3;
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/responses/BaseResponse.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/responses/BaseResponse.java
new file mode 100644
index 0000000..59ef44b
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/responses/BaseResponse.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.responses;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+/**
+ * BaseResponse.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 9:46
+ */
+@Getter
+@Setter
+@ToString
+public class BaseResponse<T> implements java.io.Serializable {
+
+    /**
+     * response code.
+     */
+    private String code;
+
+    /**
+     * response message.
+     */
+    private String message;
+
+    /**
+     * response data.
+     */
+    private T data;
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/responses/DemoRespBean1.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/responses/DemoRespBean1.java
new file mode 100644
index 0000000..e8aec9c
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/responses/DemoRespBean1.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.responses;
+
+import org.apache.dubbo.apidocs.annotations.ResponseProperty;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * demo response bean 1.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 9:56
+ */
+@Getter
+@Setter
+public class DemoRespBean1 {
+
+    @ResponseProperty("Response code")
+    private String code;
+
+    @ResponseProperty("Response message")
+    private String message;
+
+    @ResponseProperty(value = "Response message 2", example = "This is response message 2")
+    private String message2;
+
+    @ResponseProperty("Map without generics")
+    private Map map1;
+
+    @ResponseProperty("Map generic with Object")
+    private Map<Object, Object> map2;
+
+    @ResponseProperty("List without generics")
+    private List list1;
+
+    @ResponseProperty("List generic with Object")
+    private List<Object> list2;
+
+    @ResponseProperty("Object")
+    private Object obj1;
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-provider-sca/pom.xml b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider-sca/pom.xml
new file mode 100644
index 0000000..00d09d5
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider-sca/pom.xml
@@ -0,0 +1,35 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.dubbo.examples.apidocs</groupId>
+        <artifactId>dubbo-api-docs-examples</artifactId>
+        <version>2.7.9-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>examples-provider-sca</artifactId>
+
+    <dependencies>
+
+    </dependencies>
+
+
+</project>
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/pom.xml b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/pom.xml
new file mode 100644
index 0000000..acc63d4
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/pom.xml
@@ -0,0 +1,80 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.dubbo.examples.apidocs</groupId>
+        <artifactId>dubbo-api-docs-examples</artifactId>
+        <version>2.7.9-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>examples-provider</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-api-docs-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo.examples.apidocs</groupId>
+            <artifactId>examples-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-registry-nacos</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>log4j</artifactId>
+                    <groupId>log4j</groupId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.dubbo</groupId>
+                    <artifactId>dubbo-remoting-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>dubbo-common</artifactId>
+                    <groupId>org.apache.dubbo</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-spring-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-logging</artifactId>
+        </dependency>
+    </dependencies>
+
+
+</project>
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/ExampleApplication.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/ExampleApplication.java
new file mode 100644
index 0000000..6d4039f
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/ExampleApplication.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples;
+
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+/**
+ * example dubbo provider service application.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 14:54
+ */
+@SpringBootApplication
+@EnableDubbo(scanBasePackages = {"org.apache.dubbo.apidocs.examples.api"})
+public class ExampleApplication {
+
+    public static void main(String[] args) {
+        new SpringApplicationBuilder(ExampleApplication.class)
+                // Non web applications
+                .web(WebApplicationType.NONE)
+                .run(args);
+    }
+
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/api/impl/AsyncDemoImpl.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/api/impl/AsyncDemoImpl.java
new file mode 100644
index 0000000..9706290
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/api/impl/AsyncDemoImpl.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.api.impl;
+
+import org.apache.dubbo.apidocs.annotations.ApiDoc;
+import org.apache.dubbo.apidocs.annotations.ApiModule;
+import org.apache.dubbo.apidocs.examples.api.IAsyncDemo;
+import org.apache.dubbo.apidocs.examples.params.DemoParamBean1;
+import org.apache.dubbo.apidocs.examples.params.DemoParamBean2;
+import org.apache.dubbo.apidocs.examples.responses.DemoRespBean1;
+import org.apache.dubbo.config.annotation.DubboService;
+
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+
+/**
+ * Asynchronous demo implementation.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 14:54
+ */
+@DubboService(async = true)
+@ApiModule(value = "Asynchronous demo", apiInterface = IAsyncDemo.class)
+public class AsyncDemoImpl implements IAsyncDemo {
+
+    public static final ScheduledExecutorService EXECUTOR = new ScheduledThreadPoolExecutor(
+            Runtime.getRuntime().availableProcessors() * 40 * 3,
+            new BasicThreadFactory.Builder().namingPattern("dubbo-async-executor-pool-%d").daemon(true).build());
+
+    @ApiDoc("request and response parameters are beans")
+    @Override
+    public CompletableFuture<DemoRespBean1> demoApi1(DemoParamBean1 param1, DemoParamBean2 param2) {
+        DemoRespBean1 result = new DemoRespBean1();
+        result.setCode("123456789");
+        result.setMessage("called demoApi1 msg1");
+        result.setMessage2("called demoApi1 msg2");
+        return CompletableFuture.supplyAsync(() -> result, EXECUTOR);
+    }
+
+    @Override
+    @ApiDoc(value = "Map without generics", responseClassDescription="Map without generics")
+    public CompletableFuture<Map> demoApi6() {
+        return null;
+    }
+
+    @Override
+    @ApiDoc(value = "Map generic with Object", responseClassDescription="Map generic with Object")
+    public CompletableFuture<Map<Object, Object>> demoApi7() {
+        return null;
+    }
+
+    @Override
+    @ApiDoc(value = "List without generics", responseClassDescription="List without generics")
+    public CompletableFuture<List> demoApi10() {
+        return null;
+    }
+
+    @Override
+    @ApiDoc(value = "List generic with Object", responseClassDescription="List generic with Object")
+    public CompletableFuture<List<Object>> demoApi9() {
+        return null;
+    }
+
+    @Override
+    @ApiDoc(value = "Object", responseClassDescription="Object")
+    public CompletableFuture<Object> demoApi8() {
+        return null;
+    }
+
+    @Override
+    @ApiDoc(value = "Integer", responseClassDescription="Integer")
+    public CompletableFuture<Integer> demoApi11() {
+        return null;
+    }
+
+    @Override
+    @ApiDoc(value = "many generics", responseClassDescription="many generics")
+    public CompletableFuture<List<List<String>>> demoApi12(){
+        return null;
+    }
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/api/impl/SyncDemoImpl.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/api/impl/SyncDemoImpl.java
new file mode 100644
index 0000000..243a2e3
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/api/impl/SyncDemoImpl.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.api.impl;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.apache.dubbo.apidocs.annotations.ApiDoc;
+import org.apache.dubbo.apidocs.annotations.ApiModule;
+import org.apache.dubbo.apidocs.annotations.RequestParam;
+import org.apache.dubbo.apidocs.examples.api.ISyncDemo;
+import org.apache.dubbo.apidocs.examples.params.DemoParamBean1;
+import org.apache.dubbo.apidocs.examples.params.DemoParamBean2;
+import org.apache.dubbo.apidocs.examples.responses.BaseResponse;
+import org.apache.dubbo.apidocs.examples.responses.DemoRespBean1;
+import org.apache.dubbo.config.annotation.DubboService;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Synchronous demo implementation.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 14:57
+ */
+@Slf4j
+@DubboService
+@ApiModule(value = "Synchronous demo", apiInterface = ISyncDemo.class)
+public class SyncDemoImpl implements ISyncDemo {
+
+    @ApiDoc("request and response parameters are beans")
+    @Override
+    public DemoRespBean1 demoApi1(DemoParamBean1 param1, DemoParamBean2 param2) {
+        log.info("called demoApi1");
+        DemoRespBean1 result = new DemoRespBean1();
+        result.setCode("123456789");
+        result.setMessage("called demoApi1 msg1");
+        result.setMessage2("called demoApi1 msg2");
+        return result;
+    }
+
+    @ApiDoc(value = "request and response parameters are Strings", responseClassDescription="A string")
+    @Override
+    public String demoApi2(@RequestParam(value = "Parameter 1", required = true) String prarm1, String prarm2) {
+        log.info(" called demoApi2");
+        return "demoApi2";
+    }
+
+    @Override
+    public String demoApi3(String prarm1) {
+        return null;
+    }
+
+    @ApiDoc(value = "Nonparametric method with Dubbo doc annotation", responseClassDescription="A string")
+    @Override
+    public String demoApi4() {
+        return "asdfasdfsdafds";
+    }
+
+    @ApiDoc(value = " Use generics in response", responseClassDescription=" Use generics in response")
+    @Override
+    public BaseResponse<DemoRespBean1> demoApi5(){
+        BaseResponse<DemoRespBean1> response = new BaseResponse<>();
+        DemoRespBean1 responseData = new DemoRespBean1();
+        responseData.setCode("2222");
+        responseData.setMessage("msg1");
+        responseData.setMessage2("msg2");
+        response.setData(responseData);
+        response.setCode("1111");
+        response.setMessage("msg");
+        return response;
+    }
+
+    @Override
+    @ApiDoc(value = "Map without generics", responseClassDescription="Map without generics")
+    public Map demoApi6() {
+        return null;
+    }
+
+    @Override
+    @ApiDoc(value = "Map generic with Object", responseClassDescription="Map generic with Object")
+    public Map<Object, Object> demoApi7() {
+        return null;
+    }
+
+    @Override
+    @ApiDoc(value = "List without generics", responseClassDescription="List without generics")
+    public List demoApi10() {
+        return null;
+    }
+
+    @Override
+    @ApiDoc(value = "List generic with Object", responseClassDescription="List generic with Object")
+    public List<Object> demoApi9() {
+        return null;
+    }
+
+    @Override
+    @ApiDoc(value = "Object", responseClassDescription="Object")
+    public Object demoApi8() {
+        return null;
+    }
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/cfg/DubboDocConfig.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/cfg/DubboDocConfig.java
new file mode 100644
index 0000000..29c0401
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/cfg/DubboDocConfig.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.apidocs.examples.cfg;
+
+import org.apache.dubbo.apidocs.EnableDubboApiDocs;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+/**
+ * dubbo doc config.
+ * @author klw(213539@qq.com)
+ * 2020/10/30 14:58
+ */
+@Configuration
+@EnableDubboApiDocs
+@Profile("dev")
+public class DubboDocConfig {
+}
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/resources/application.yml b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/resources/application.yml
new file mode 100644
index 0000000..87423b4
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/resources/application.yml
@@ -0,0 +1,15 @@
+spring:
+  application:
+    name: dubbo-doc-example-provider
+  profiles:
+    active: dev
+dubbo:
+  registry:
+    address: nacos://127.0.0.1:8848
+  provider:
+    timeout: 2000
+  protocol:
+    port: 20881
+    name: dubbo
+  application:
+    name: dubbo-doc-example-provider
\ No newline at end of file
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/pom.xml b/dubbo-api-docs/dubbo-api-docs-examples/pom.xml
new file mode 100644
index 0000000..bf7686b
--- /dev/null
+++ b/dubbo-api-docs/dubbo-api-docs-examples/pom.xml
@@ -0,0 +1,53 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.dubbo</groupId>
+        <artifactId>dubbo-api-docs</artifactId>
+        <version>2.7.9-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <groupId>org.apache.dubbo.examples.apidocs</groupId>
+    <artifactId>dubbo-api-docs-examples</artifactId>
+
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+    <description>Dubbo interface documentation examples</description>
+    
+    <modules>
+        <module>examples-api</module>
+        <module>examples-provider</module>
+        <module>examples-provider-sca</module>
+    </modules>
+
+    <dependencyManagement>
+        <dependencies>
+            <!-- Internal libs -->
+            <dependency>
+                <groupId>org.apache.dubbo.examples.apidocs</groupId>
+                <artifactId>examples-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+
+</project>
diff --git a/dubbo-api-docs/pom.xml b/dubbo-api-docs/pom.xml
new file mode 100644
index 0000000..44c810c
--- /dev/null
+++ b/dubbo-api-docs/pom.xml
@@ -0,0 +1,210 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.dubbo</groupId>
+        <artifactId>dubbo-parent</artifactId>
+        <version>2.7.9-SNAPSHOT</version>
+        <relativePath />
+    </parent>
+    <artifactId>dubbo-api-docs</artifactId>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+    <description>Dubbo interface documentation, testing tools</description>
+    <properties>
+        <revision>2.7.9-SNAPSHOT</revision>
+        <project.build.jdkVersion>1.8</project.build.jdkVersion>
+        <argLine>-Dfile.encoding=UTF-8</argLine>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <skipJunitTest>true</skipJunitTest>
+
+        <skip_maven_deploy>true</skip_maven_deploy>
+        <lombok.version>1.18.12</lombok.version>
+        <maven-flatten-version>1.1.0</maven-flatten-version>
+
+        <spring-boot.version>2.3.4.RELEASE</spring-boot.version>
+        <dubbo-spring-boot.version>2.7.8</dubbo-spring-boot.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <!-- Internal libs -->
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-api-docs-annotations</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-api-docs-core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-registry-nacos</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.projectlombok</groupId>
+                <artifactId>lombok</artifactId>
+                <version>${lombok.version}</version>
+                <scope>compile</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-spring-boot-starter</artifactId>
+                <version>${dubbo-spring-boot.version}</version>
+            </dependency>
+
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+    </dependencies>
+
+    <modules>
+        <module>dubbo-api-docs-annotations</module>
+        <module>dubbo-api-docs-core</module>
+        <module>dubbo-api-docs-examples</module>
+    </modules>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>flatten-maven-plugin</artifactId>
+                <version>${maven-flatten-version}</version>
+                <configuration>
+                    <updatePomFile>true</updatePomFile>
+                    <flattenMode>resolveCiFriendliesOnly</flattenMode>
+                    <pomElements>
+                        <dependencies>expand</dependencies>
+                    </pomElements>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>flatten</id>
+                        <phase>process-resources</phase>
+                        <goals>
+                            <goal>flatten</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>flatten.clean</id>
+                        <phase>clean</phase>
+                        <goals>
+                            <goal>clean</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${project.build.jdkVersion}</source>
+                    <target>${project.build.jdkVersion}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                    <compilerArguments>
+                        <verbose/>
+                    </compilerArguments>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-resources-plugin</artifactId>
+                <configuration>
+                    <!-- We are not suppose to setup the customer resources here -->
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.projectlombok</groupId>
+                <artifactId>lombok-maven-plugin</artifactId>
+                <version>1.18.6.0</version>
+                <executions>
+                    <execution>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>delombok</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skip>${skipJunitTest}</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>2.2.1</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>jar-no-fork</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>2.9.1</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <show>private</show>
+                    <nohelp>true</nohelp>
+                    <charset>UTF-8</charset>
+                    <encoding>UTF-8</encoding>
+                    <docencoding>UTF-8</docencoding>
+                    <additionalparam>-Xdoclint:none</additionalparam>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>