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/02/07 07:32:59 UTC

[dubbo-spi-extensions] branch 2.7.x updated: fix #16

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


The following commit(s) were added to refs/heads/2.7.x by this push:
     new fcfc6a6  fix #16
     new b9e8f43  Merge pull request #17 from KeRan213539/fix-16
fcfc6a6 is described below

commit fcfc6a6f58d62a8f8485abe47281dce3b75d9a51
Author: 邪影oO <21...@qq.com>
AuthorDate: Sun Feb 7 14:58:52 2021 +0800

    fix #16
---
 .../org/apache/dubbo/apidocs/core/Constants.java   |   5 +
 .../core/DubboApiDocsAnnotationScanner.java        |  22 ++--
 .../apache/dubbo/apidocs/utils/ClassTypeUtil.java  | 117 +++++++++++++++++----
 .../apidocs/examples/api/IQuickStartDemo.java      |   2 +-
 .../examples/params/QuickStartRequestBase.java     |  50 +++++++--
 .../examples-provider/pom.xml                      |   6 ++
 .../examples/api/impl/QuickStartDemoImpl.java      |   5 +-
 .../src/main/resources/application.yml             |   6 +-
 8 files changed, 170 insertions(+), 43 deletions(-)

diff --git a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/Constants.java b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/Constants.java
index 9533619..1acf828 100644
--- a/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/Constants.java
+++ b/dubbo-api-docs/dubbo-api-docs-core/src/main/java/org/apache/dubbo/apidocs/core/Constants.java
@@ -75,5 +75,10 @@ public class Constants {
 
     public static final String ENUM_VALUES_SEPARATOR = "|";
 
+    public static final Object EMPTY_OBJECT_INSTANCE = new Object();
+
+    public static final String STRING_EMPTY = "";
+
+    public static final String STRING_KEY = "key";
 
 }
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
index f9fb930..f8bb60e 100644
--- 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
@@ -64,6 +64,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+
 import static org.apache.dubbo.apidocs.core.Constants.DOT;
 import static org.apache.dubbo.apidocs.core.Constants.METHOD_PARAM_INDEX_BOUNDARY_LEFT;
 import static org.apache.dubbo.apidocs.core.Constants.METHOD_PARAM_INDEX_BOUNDARY_RIGHT;
@@ -112,9 +113,9 @@ public class DubboApiDocsAnnotationScanner implements ApplicationListener<Applic
             }
             ApiModule moduleAnn = apiModuleClass.getAnnotation(ApiModule.class);
             if (!apiModuleClass.isAnnotationPresent(Service.class) && !apiModuleClass.isAnnotationPresent(DubboService.class)) {
-                LOG.warn( "【Warning】" + apiModuleClass.getName() + " @ApiModule annotation is used, " +
-                                "but it is not a dubbo provider (without " + Service.class.getName() + " or " +
-                                DubboService.class.getName() + " annotation)");
+                LOG.warn("【Warning】" + apiModuleClass.getName() + " @ApiModule annotation is used, " +
+                        "but it is not a dubbo provider (without " + Service.class.getName() + " or " +
+                        DubboService.class.getName() + " annotation)");
                 return;
             }
             boolean async;
@@ -193,7 +194,8 @@ public class DubboApiDocsAnnotationScanner implements ApplicationListener<Applic
         for (int i = 0; i < argsClass.length; i++) {
             Class<?> argClass = argsClass[i];
             Type parameterType = parametersTypes[i];
-            methodParamInfoSb.append(METHOD_PARAM_INDEX_BOUNDARY_LEFT).append(i).append(METHOD_PARAM_INDEX_BOUNDARY_RIGHT).append(argClass.getCanonicalName());
+            methodParamInfoSb.append(METHOD_PARAM_INDEX_BOUNDARY_LEFT).append(i)
+                    .append(METHOD_PARAM_INDEX_BOUNDARY_RIGHT).append(argClass.getCanonicalName());
             if (i + 1 < argsClass.length) {
                 methodParamInfoSb.append(METHOD_PARAMETER_SEPARATOR);
             }
@@ -253,7 +255,7 @@ public class DubboApiDocsAnnotationScanner implements ApplicationListener<Applic
             ParameterizedTypeImpl parameterTypeImpl = (ParameterizedTypeImpl) parameterType;
             TypeVariable<? extends Class<?>>[] typeVariables = parameterTypeImpl.getRawType().getTypeParameters();
             Type[] actualTypeArguments = parameterTypeImpl.getActualTypeArguments();
-            genericTypeAndNamesMap =  new HashMap<>(typeVariables.length);
+            genericTypeAndNamesMap = new HashMap<>(typeVariables.length);
             for (int i = 0; i < typeVariables.length; i++) {
                 genericTypeAndNamesMap.put(typeVariables[i].getTypeName(), actualTypeArguments[i].getTypeName());
             }
@@ -292,15 +294,17 @@ public class DubboApiDocsAnnotationScanner implements ApplicationListener<Applic
                     paramBean.setRequired(false);
                 }
 
-                ParamBean tempParamBean = this.processHtmlType(null == genericType ? field.getType() : genericType, requestParam, paramBean);
+                ParamBean tempParamBean = this.processHtmlType(null == genericType ?
+                        field.getType() : genericType, requestParam, paramBean);
                 if (tempParamBean == null || HtmlTypeEnum.TEXT_AREA.equals(tempParamBean.getHtmlType())) {
                     Object objResult;
                     if (null == genericType) {
                         objResult = ClassTypeUtil.initClassTypeWithDefaultValue(
-                                field.getGenericType(), field.getType(), 0);
+                                field.getGenericType(), field.getType(), 0, genericTypeAndNamesMap);
                     } else {
                         objResult = ClassTypeUtil.initClassTypeWithDefaultValue(
-                                ClassTypeUtil.makeParameterizedType(genericTypeName), genericType, 0, true);
+                                ClassTypeUtil.makeParameterizedType(genericTypeName), genericType, 0,
+                                true, genericTypeAndNamesMap);
                     }
                     if (!ClassTypeUtil.isBaseType(objResult)) {
                         paramBean.setHtmlType(HtmlTypeEnum.TEXT_AREA);
@@ -327,7 +331,7 @@ public class DubboApiDocsAnnotationScanner implements ApplicationListener<Applic
             }
 
             Object objResult = ClassTypeUtil.initClassTypeWithDefaultValue(
-                    parameterType, argClass, 0);
+                    parameterType, argClass, 0, genericTypeAndNamesMap);
             if (!ClassTypeUtil.isBaseType(objResult)) {
                 paramBean.setHtmlType(HtmlTypeEnum.TEXT_AREA);
                 paramBean.setSubParamsJson(JSON.toJSONString(objResult, ClassTypeUtil.FAST_JSON_FEATURES));
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
index b30f7d1..fe94569 100644
--- 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
@@ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils;
 import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
@@ -54,6 +55,9 @@ import static org.apache.dubbo.apidocs.core.Constants.SQUARE_BRACKET_RIGHT;
 import static org.apache.dubbo.apidocs.core.Constants.RESPONSE_STR_EXAMPLE;
 import static org.apache.dubbo.apidocs.core.Constants.ENUM_VALUES_SEPARATOR;
 import static org.apache.dubbo.apidocs.core.Constants.METHOD_NAME_NAME;
+import static org.apache.dubbo.apidocs.core.Constants.EMPTY_OBJECT_INSTANCE;
+import static org.apache.dubbo.apidocs.core.Constants.STRING_EMPTY;
+import static org.apache.dubbo.apidocs.core.Constants.STRING_KEY;
 
 /**
  * Java class tool class, special for Dubbo doc.
@@ -88,7 +92,20 @@ public class ClassTypeUtil {
     private static final String GENERIC_START_SYMBOL = "<";
 
     public static String calss2Json(Type genericType, Class<?> classType) {
-        Object obj = initClassTypeWithDefaultValue(genericType, classType, 0);
+        Map<String, String> genericTypeAndNamesMap;
+        if (genericType instanceof ParameterizedTypeImpl) {
+            ParameterizedTypeImpl parameterTypeImpl = (ParameterizedTypeImpl) genericType;
+            TypeVariable<? extends Class<?>>[] typeVariables = parameterTypeImpl.getRawType().getTypeParameters();
+            Type[] actualTypeArguments = parameterTypeImpl.getActualTypeArguments();
+            genericTypeAndNamesMap = new HashMap<>(typeVariables.length);
+            for (int i = 0; i < typeVariables.length; i++) {
+                genericTypeAndNamesMap.put(typeVariables[i].getTypeName(), actualTypeArguments[i].getTypeName());
+            }
+        } else {
+            genericTypeAndNamesMap = Collections.EMPTY_MAP;
+        }
+
+        Object obj = initClassTypeWithDefaultValue(genericType, classType, 0, genericTypeAndNamesMap);
         return JSON.toJSONString(obj, FAST_JSON_FEATURES);
     }
 
@@ -100,8 +117,10 @@ public class ClassTypeUtil {
      * @param processCount processCount
      * @return java.lang.Object
      */
-    public static Object initClassTypeWithDefaultValue(Type genericType, Class<?> classType, int processCount) {
-        return initClassTypeWithDefaultValue(genericType, classType, processCount, false);
+    public static Object initClassTypeWithDefaultValue(Type genericType, Class<?> classType, int processCount,
+                                                       Map<String, String> methodPrarmGenericTypeAndNamesMap) {
+        return initClassTypeWithDefaultValue(genericType, classType, processCount, false,
+                methodPrarmGenericTypeAndNamesMap);
     }
 
     /**
@@ -114,7 +133,8 @@ public class ClassTypeUtil {
      * @return java.lang.Object
      */
     public static Object initClassTypeWithDefaultValue(Type genericType, Class<?> classType, int processCount,
-                                                       boolean isBuildClassAttribute) {
+                                                       boolean isBuildClassAttribute,
+                                                       Map<String, String> methodPrarmGenericTypeAndNamesMap) {
         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!");
@@ -122,7 +142,8 @@ public class ClassTypeUtil {
         }
         processCount++;
 
-        Object initResult = initClassTypeWithDefaultValueNoProceeField(genericType, classType, processCount);
+        Object initResult = initClassTypeWithDefaultValueNoProceeField(genericType, classType, processCount,
+                methodPrarmGenericTypeAndNamesMap);
         if (null != initResult) {
             return initResult;
         }
@@ -158,12 +179,14 @@ public class ClassTypeUtil {
                     ResponseProperty responseProperty = field2.getAnnotation(ResponseProperty.class);
                     StringBuilder strValue = new StringBuilder(responseProperty.value());
                     if (StringUtils.isNotBlank(responseProperty.example())) {
-                        strValue.append(SQUARE_BRACKET_LEFT).append(RESPONSE_STR_EXAMPLE).append(responseProperty.example()).append(SQUARE_BRACKET_RIGHT);
+                        strValue.append(SQUARE_BRACKET_LEFT).append(RESPONSE_STR_EXAMPLE)
+                                .append(responseProperty.example()).append(SQUARE_BRACKET_RIGHT);
                     }
                     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));
+                    result.put(field2.getName(), initClassTypeWithDefaultValue(field2.getGenericType(), field2.getType(),
+                            processCount, methodPrarmGenericTypeAndNamesMap));
                 }
             } else {
                 // Check if the type of the property is generic
@@ -171,17 +194,25 @@ public class ClassTypeUtil {
                 if (StringUtils.isNotBlank(genericTypeName)) {
                     // The type of the attribute is generic. Find the generic from the definition of
                     // the class in which the attribute is located
-                    result.put(field2.getName(), initClassTypeWithDefaultValue(makeParameterizedType(genericTypeName), makeClass(genericTypeName), processCount, true));
+                    result.put(field2.getName(), initClassTypeWithDefaultValue(makeParameterizedType(genericTypeName),
+                            makeClass(genericTypeName),
+                            processCount, true, methodPrarmGenericTypeAndNamesMap));
                 } else {
                     // Not generic
-                    result.put(field2.getName(), initClassTypeWithDefaultValue(field2.getGenericType(), field2.getType(), processCount));
+                    result.put(field2.getName(), initClassTypeWithDefaultValue(field2.getGenericType(), field2.getType(),
+                            processCount, methodPrarmGenericTypeAndNamesMap));
                 }
             }
         }
         return result;
     }
 
-    public static Object initClassTypeWithDefaultValueNoProceeField(Type genericType, Class<?> classType, int processCount) {
+    public static Object initClassTypeWithDefaultValueNoProceeField(
+            Type genericType, Class<?> classType, int processCount,
+            Map<String, String> methodPrarmGenericTypeAndNamesMap) {
+        if (null == classType) {
+            return EMPTY_OBJECT_INSTANCE;
+        }
         if (Integer.class.isAssignableFrom(classType) || int.class.isAssignableFrom(classType)) {
             return 0;
         } else if (Byte.class.isAssignableFrom(classType) || byte.class.isAssignableFrom(classType)) {
@@ -193,7 +224,7 @@ public class ClassTypeUtil {
         } else if (Float.class.isAssignableFrom(classType) || float.class.isAssignableFrom(classType)) {
             return 0.0F;
         } else if (String.class.isAssignableFrom(classType)) {
-            return "";
+            return STRING_EMPTY;
         } else if (Character.class.isAssignableFrom(classType) || char.class.isAssignableFrom(classType)) {
             return 'c';
         } else if (Short.class.isAssignableFrom(classType) || short.class.isAssignableFrom(classType)) {
@@ -219,44 +250,88 @@ public class ClassTypeUtil {
             }
             return sb.toString();
         } else if (classType.isArray()) {
-            Class<?> arrType = classType.getComponentType();
-            Object obj = initClassTypeWithDefaultValue(null, arrType, processCount);
+            Object obj;
+            if (null != genericType && genericType instanceof GenericArrayType) {
+                GenericArrayType pt = (GenericArrayType) genericType;
+                String subTypeName = pt.getGenericComponentType().getTypeName();
+
+                boolean isBuildClassAttribute = false;
+                if (null != methodPrarmGenericTypeAndNamesMap) {
+                    String subTypeGenericTypeName = methodPrarmGenericTypeAndNamesMap.get(subTypeName);
+                    if (StringUtils.isNotBlank(subTypeGenericTypeName)) {
+                        subTypeName = subTypeGenericTypeName;
+                        isBuildClassAttribute = true;
+                    }
+                }
+
+                obj = initClassTypeWithDefaultValue(makeParameterizedType(subTypeName), makeClass(subTypeName),
+                        processCount, isBuildClassAttribute, methodPrarmGenericTypeAndNamesMap);
+            } else {
+                Class<?> arrType = classType.getComponentType();
+                obj = initClassTypeWithDefaultValue(null, arrType, processCount, methodPrarmGenericTypeAndNamesMap);
+            }
             return new Object[]{obj};
         } else if (Collection.class.isAssignableFrom(classType)) {
             List<Object> list = new ArrayList<>(1);
-            if (genericType == null) {
-                list.add(new Object());
+            if (null == genericType) {
+                list.add(EMPTY_OBJECT_INSTANCE);
                 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);
+
+                boolean isBuildClassAttribute = false;
+                if (null != methodPrarmGenericTypeAndNamesMap) {
+                    String subTypeGenericTypeName = methodPrarmGenericTypeAndNamesMap.get(subTypeName);
+                    if (StringUtils.isNotBlank(subTypeGenericTypeName)) {
+                        subTypeName = subTypeGenericTypeName;
+                        isBuildClassAttribute = true;
+                    }
+                }
+
+                obj = initClassTypeWithDefaultValue(makeParameterizedType(subTypeName), makeClass(subTypeName),
+                        processCount, isBuildClassAttribute, methodPrarmGenericTypeAndNamesMap);
                 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());
+                map.put(STRING_KEY, EMPTY_OBJECT_INSTANCE);
                 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);
+
+                boolean isBuildClassAttribute = false;
+                if (null != methodPrarmGenericTypeAndNamesMap) {
+                    String subTypeGenericTypeName = methodPrarmGenericTypeAndNamesMap.get(subTypeName);
+                    if (StringUtils.isNotBlank(subTypeGenericTypeName)) {
+                        subTypeName = subTypeGenericTypeName;
+                        isBuildClassAttribute = true;
+                    } else {
+                        map.put(STRING_KEY, EMPTY_OBJECT_INSTANCE);
+                        return map;
+                    }
+                }
+
+                Object objValue = initClassTypeWithDefaultValue(makeParameterizedType(subTypeName), makeClass(subTypeName),
+                        processCount, isBuildClassAttribute, methodPrarmGenericTypeAndNamesMap);
+                map.put(STRING_KEY, objValue);
             }
             return map;
         } else if (CompletableFuture.class.isAssignableFrom(classType)) {
             // process CompletableFuture
             if (genericType == null) {
-                return new Object();
+                return EMPTY_OBJECT_INSTANCE;
             }
             ParameterizedType pt = (ParameterizedType) genericType;
             String typeName = pt.getActualTypeArguments()[0].getTypeName();
-            return initClassTypeWithDefaultValue(makeParameterizedType(typeName), makeClass(typeName), processCount);
+            return initClassTypeWithDefaultValue(makeParameterizedType(typeName), makeClass(typeName),
+                    processCount, methodPrarmGenericTypeAndNamesMap);
         } else if (BigDecimal.class.isAssignableFrom(classType)) {
             return 0;
         } else if (BigInteger.class.isAssignableFrom(classType)) {
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/api/IQuickStartDemo.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/api/IQuickStartDemo.java
index 199925f..4094e82 100644
--- a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/api/IQuickStartDemo.java
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/api/IQuickStartDemo.java
@@ -48,7 +48,7 @@ public interface IQuickStartDemo {
      * @param beanParam
      * @return org.apache.dubbo.apidocs.examples.params.QuickStartRespBean
      */
-    QuickStartRespBean quickStart2(Map<String, DemoParamBean4> beanList, QuickStartRequestBase<QuickStartRequestBean, DemoParamBean4> beanParam);
+    QuickStartRespBean quickStart2(Map<String, DemoParamBean4> beanList, QuickStartRequestBase<QuickStartRequestBean, InnerClassRequestBean<DemoParamBean4>> beanParam);
 
     /**
      * quick start demo3, request use multiple generic.
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/QuickStartRequestBase.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/QuickStartRequestBase.java
index fd37785..265339c 100644
--- a/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/QuickStartRequestBase.java
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-api/src/main/java/org/apache/dubbo/apidocs/examples/params/QuickStartRequestBase.java
@@ -18,6 +18,9 @@ package org.apache.dubbo.apidocs.examples.params;
 
 import org.apache.dubbo.apidocs.annotations.RequestParam;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * QuickStartRequestBase.
  *
@@ -30,10 +33,16 @@ public class QuickStartRequestBase<E, T> implements java.io.Serializable {
     @RequestParam(value = "Request method", required = true)
     private String method;
 
-    private T body;
+    private List<List<T>> body;
 
     private E body3;
 
+    private List<T> body4;
+
+    private Map<String, T> body5;
+
+    private T[] body6;
+
     private QuickStartRequestBean body2;
 
     public String getMethod() {
@@ -44,14 +53,6 @@ public class QuickStartRequestBase<E, T> implements java.io.Serializable {
         this.method = method;
     }
 
-    public T getBody() {
-        return body;
-    }
-
-    public void setBody(T body) {
-        this.body = body;
-    }
-
     public QuickStartRequestBean getBody2() {
         return body2;
     }
@@ -68,4 +69,35 @@ public class QuickStartRequestBase<E, T> implements java.io.Serializable {
         this.body3 = body3;
     }
 
+    public List<List<T>> getBody() {
+        return body;
+    }
+
+    public void setBody(List<List<T>> body) {
+        this.body = body;
+    }
+
+    public List<T> getBody4() {
+        return body4;
+    }
+
+    public void setBody4(List<T> body4) {
+        this.body4 = body4;
+    }
+
+    public Map<String, T> getBody5() {
+        return body5;
+    }
+
+    public void setBody5(Map<String, T> body5) {
+        this.body5 = body5;
+    }
+
+    public T[] getBody6() {
+        return body6;
+    }
+
+    public void setBody6(T[] body6) {
+        this.body6 = body6;
+    }
 }
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
index 9f16669..71521a1 100644
--- a/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/pom.xml
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/pom.xml
@@ -92,6 +92,12 @@
             <groupId>org.apache.curator</groupId>
             <artifactId>curator-recipes</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-monitor-default</artifactId>
+            <version>${dubbo.version}</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/api/impl/QuickStartDemoImpl.java b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/api/impl/QuickStartDemoImpl.java
index 5bbd30e..f02ae82 100644
--- a/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/api/impl/QuickStartDemoImpl.java
+++ b/dubbo-api-docs/dubbo-api-docs-examples/examples-provider/src/main/java/org/apache/dubbo/apidocs/examples/api/impl/QuickStartDemoImpl.java
@@ -31,6 +31,7 @@ import org.apache.dubbo.config.annotation.DubboService;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -51,7 +52,7 @@ public class QuickStartDemoImpl implements IQuickStartDemo {
 
     @ApiDoc(value = "quick start demo, request use generic.", version = "v0.1", description = "quick start demo, request use generic.", responseClassDescription="A quick star response bean")
     @Override
-    public QuickStartRespBean quickStart2(Map<String, DemoParamBean4> beanList, QuickStartRequestBase<QuickStartRequestBean, DemoParamBean4> beanParam) {
+    public QuickStartRespBean quickStart2(Map<String, DemoParamBean4> beanList, QuickStartRequestBase<QuickStartRequestBean, InnerClassRequestBean<DemoParamBean4>> beanParam) {
         return new QuickStartRespBean(200, "【" + beanParam.getMethod() + "】hello " + beanParam.getBody3() + ", " + beanParam.toString());
     }
 
@@ -65,7 +66,7 @@ public class QuickStartDemoImpl implements IQuickStartDemo {
     @Override
     public QuickStartRequestBase quickStart4(BigDecimal number, QuickStartRequestBean2 beanParam) {
         QuickStartRequestBase response = new QuickStartRequestBase();
-        response.setBody("body");
+        response.setBody(Arrays.asList("body2-1", "body2-2"));
         response.setBody3("body3");
         response.setMethod("test");
         return response;
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
index dbb4a3b..10a1831 100644
--- 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
@@ -22,9 +22,10 @@ spring:
     active: dev
 dubbo:
   registry:
-    address: nacos://127.0.0.1:8848
+    address: zookeeper://127.0.0.1:2181
   provider:
     timeout: 2000
+    filter: metrics
   protocol:
     port: 20881
     name: dubbo
@@ -34,6 +35,9 @@ dubbo:
     address: zookeeper://127.0.0.1:2181
   config-center:
     address: zookeeper://127.0.0.1:2181
+  metrics:
+    port: ${dubbo.protocol.port}
+    protocol: dubbo
 demo:
   apiversion:
     quickstart: v0.1
\ No newline at end of file