This is an automated email from the ASF dual-hosted git repository.
xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 0df2440 [type:fixbug] sofa plugin register metadata and parameters
resolve [fix pr#2103] (#2112)
0df2440 is described below
commit 0df24404d2e5d173e707f9b0a0cd5932ae4e2976
Author: likeguo <[email protected]>
AuthorDate: Wed Sep 22 18:12:13 2021 +0800
[type:fixbug] sofa plugin register metadata and parameters resolve [fix
pr#2103] (#2112)
* fixbug/sofa-plugin: Fix the param resolve bug
* fixbug/sofa-plugin: Fix the param resolve bug
---
.../client/sofa/SofaServiceBeanPostProcessor.java | 20 +++-
.../src/main/http/sofa-test-api.http | 46 ++++----
.../sofa/param/SofaParamResolveServiceImpl.java | 130 +++++++++++++++------
.../param/SofaBodyParamResolveServiceTest.java | 24 ++--
4 files changed, 145 insertions(+), 75 deletions(-)
diff --git
a/shenyu-client/shenyu-client-sofa/src/main/java/org/apache/shenyu/client/sofa/SofaServiceBeanPostProcessor.java
b/shenyu-client/shenyu-client-sofa/src/main/java/org/apache/shenyu/client/sofa/SofaServiceBeanPostProcessor.java
index c8ddc53..be563c1 100644
---
a/shenyu-client/shenyu-client-sofa/src/main/java/org/apache/shenyu/client/sofa/SofaServiceBeanPostProcessor.java
+++
b/shenyu-client/shenyu-client-sofa/src/main/java/org/apache/shenyu/client/sofa/SofaServiceBeanPostProcessor.java
@@ -19,7 +19,6 @@ package org.apache.shenyu.client.sofa;
import com.alipay.sofa.runtime.service.component.Service;
import com.alipay.sofa.runtime.spring.factory.ServiceFactoryBean;
-
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.commons.lang3.StringUtils;
import
org.apache.shenyu.client.core.disruptor.ShenyuClientRegisterEventPublisher;
@@ -38,6 +37,8 @@ import
org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Objects;
import java.util.Properties;
@@ -52,7 +53,7 @@ public class SofaServiceBeanPostProcessor implements
BeanPostProcessor {
private static final Logger LOG =
LoggerFactory.getLogger(SofaServiceBeanPostProcessor.class);
- private ShenyuClientRegisterEventPublisher publisher =
ShenyuClientRegisterEventPublisher.getInstance();
+ private final ShenyuClientRegisterEventPublisher publisher =
ShenyuClientRegisterEventPublisher.getInstance();
private final ExecutorService executorService;
@@ -119,9 +120,18 @@ public class SofaServiceBeanPostProcessor implements
BeanPostProcessor {
String configRuleName = shenyuSofaClient.ruleName();
String ruleName = ("".equals(configRuleName)) ? path : configRuleName;
String methodName = method.getName();
- Class<?>[] parameterTypesClazz = method.getParameterTypes();
- String parameterTypes =
Arrays.stream(parameterTypesClazz).map(Class::getName)
- .collect(Collectors.joining(","));
+ String parameterTypes = Arrays.stream(method.getParameters())
+ .map(parameter -> {
+ StringBuilder result = new
StringBuilder(parameter.getType().getName());
+ final Type type = parameter.getParameterizedType();
+ if (type instanceof ParameterizedType) {
+ final Type[] actualTypeArguments =
((ParameterizedType) type).getActualTypeArguments();
+ for (Type actualTypeArgument : actualTypeArguments) {
+
result.append("#").append(actualTypeArgument.getTypeName());
+ }
+ }
+ return result.toString();
+ }).collect(Collectors.joining(","));
return MetaDataRegisterDTO.builder()
.appName(appName)
.serviceName(serviceName)
diff --git
a/shenyu-examples/shenyu-examples-sofa/shenyu-examples-sofa-service/src/main/http/sofa-test-api.http
b/shenyu-examples/shenyu-examples-sofa/shenyu-examples-sofa-service/src/main/http/sofa-test-api.http
index 0d4639b..3f29522 100644
---
a/shenyu-examples/shenyu-examples-sofa/shenyu-examples-sofa-service/src/main/http/sofa-test-api.http
+++
b/shenyu-examples/shenyu-examples-sofa/shenyu-examples-sofa-service/src/main/http/sofa-test-api.http
@@ -35,8 +35,10 @@ Accept: application/json
Content-Type: application/json
{
- "id": 123,
- "name": "test"
+ "sofaSimpleTypeBean": {
+ "id": 123,
+ "name": "test"
+ }
}
### shengyu getway proxy findByIdsAndName
@@ -145,17 +147,19 @@ Accept: application/json
Content-Type: application/json
{
- "sofaSimpleTypeBean": {
- "id": "123",
- "name": "test"
- },
- "idLists": [
- 123,
- 124
- ],
- "idMaps": {
- "abc": "abc",
- "cbd": "cbd"
+ "sofaComplexTypeBean": {
+ "sofaSimpleTypeBean": {
+ "id": "123",
+ "name": "test"
+ },
+ "idLists": [
+ 123,
+ 124
+ ],
+ "idMaps": {
+ "abc": "abc",
+ "cbd": "cbd"
+ }
}
}
@@ -204,12 +208,14 @@ Content-Type: application/json
}
}
],
- "testKey1": {
- "id": "123",
- "name": "test"
- },
- "testKey2": {
- "id": "123",
- "name": "test"
+ "sofaSimpleTypeBeanMap": {
+ "testKey1": {
+ "id": "123",
+ "name": "test"
+ },
+ "testKey2": {
+ "id": "123",
+ "name": "test"
+ }
}
}
diff --git
a/shenyu-plugin/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/param/SofaParamResolveServiceImpl.java
b/shenyu-plugin/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/param/SofaParamResolveServiceImpl.java
index e0c244e..e6bf5bb 100644
---
a/shenyu-plugin/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/param/SofaParamResolveServiceImpl.java
+++
b/shenyu-plugin/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/param/SofaParamResolveServiceImpl.java
@@ -17,6 +17,8 @@
package org.apache.shenyu.plugin.sofa.param;
+import com.alipay.hessian.generic.model.GenericCollection;
+import com.alipay.hessian.generic.model.GenericMap;
import com.alipay.hessian.generic.model.GenericObject;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
@@ -24,13 +26,10 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.shenyu.common.utils.GsonUtils;
-import org.apache.shenyu.plugin.api.utils.BodyParamUtils;
-import java.util.Arrays;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
/**
* The type Default generic param resolve service.
@@ -39,47 +38,92 @@ public class SofaParamResolveServiceImpl implements
SofaParamResolveService {
@Override
public Pair<String[], Object[]> buildParameter(final String body, final
String parameterTypes) {
- String[] parameterTypesAndGeneric = StringUtils.split(parameterTypes,
"#");
- String[] parameters = StringUtils.split(parameterTypesAndGeneric[0],
",");
- if (isSingleCustomizeType(parameters)) {
- return BodyParamUtils.buildSingleParameter(body, parameterTypes);
+ final String[] parameterTypeStrings =
StringUtils.split(parameterTypes, ",");
+ List<String> parameterTypeArr = new
ArrayList<>(parameterTypeStrings.length);
+ List<Object> values = new ArrayList<>();
+ final List<Object> params = new
ArrayList<>(GsonUtils.getInstance().toObjectMap(body).values());
+ for (int paramIndex = 0; paramIndex < parameterTypeStrings.length;
paramIndex++) {
+ final String[] parameter =
StringUtils.split(parameterTypeStrings[paramIndex], "#");
+ parameterTypeArr.add(parameter[0]);
+ values.add(convertToParameterValue(params.get(paramIndex),
parameter));
}
- LinkedList<String> genericTypes = new LinkedList<>();
- if (parameterTypesAndGeneric.length > 1) {
-
genericTypes.addAll(Arrays.asList(StringUtils.split(parameterTypesAndGeneric[1],
",")));
+ return new ImmutablePair<>(parameterTypeArr.toArray(new String[0]),
values.toArray());
+ }
+
+ /**
+ * convert to parameter value.
+ *
+ * @param value value support [json object string, json array
string,string]
+ * @param parameterType parameter type support
[javaPackage.ClassName#GenericType1#GenericType2], split is ,
+ * @return GenericObject, GenericMap, List, string, array...
+ * @see com.alipay.hessian.generic.model
+ */
+ @SuppressWarnings("all")
+ private Object convertToParameterValue(final Object value, final String[]
parameterType) {
+ if (isSingleType(parameterType)) {
+ return value;
}
- Map<String, Object> paramMap =
GsonUtils.getInstance().toObjectMap(body);
- Object[] objects = paramMap.values().stream().map(each -> {
- if (each instanceof JsonObject) {
- return GsonUtils.getInstance().convertToMap(each.toString());
- } else if (each instanceof JsonArray) {
- if (genericTypes.isEmpty()) {
- return GsonUtils.getInstance().fromList(each.toString(),
Object.class);
- }
- String type = genericTypes.pop();
- return convertToGenericObjects(type, each);
- } else {
- return each;
+ if (value instanceof JsonObject && parameterType[0].contains("Map")) {
+ final Map<String, Object> mapValue =
GsonUtils.getInstance().convertToMap(value.toString());
+ if (parameterType.length == 1) {
+ // no generic info
+ return mapValue;
}
- }).toArray();
- return new ImmutablePair<>(parameters, objects);
+ assert parameterType.length == 3;
+ // generic map
+ final GenericMap genericMap = new GenericMap(parameterType[2]);
+ mapValue.replaceAll((k, v) ->
convertToGenericObject(parameterType[2], mapValue.get(k)));
+ genericMap.setMap(mapValue);
+ return genericMap;
+ }
+ if (value instanceof JsonObject) {
+ return convertToGenericObject(parameterType[0], value);
+ }
+ if (value instanceof JsonArray) {
+ if (parameterType.length == 1) {
+ // no generic info
+ return GsonUtils.getInstance().fromList(value.toString(),
Object.class);
+ }
+ // generic collection
+ final GenericCollection genericCollection = new
GenericCollection(parameterType[1]);
+
genericCollection.setCollection(convertToGenericObjects(parameterType[1],
(Iterable<Object>) value));
+ return genericCollection;
+ }
+ return value;
+ }
+
+ /**
+ * convert json object to {@link GenericObject}.
+ *
+ * @param paramType param type string
+ * @param paramValue param value (if is object, auto to convert string)
+ * @return {@link GenericObject},if is single customize type return
paramValue
+ * @see GenericObject
+ * @see #isSingleType(String)
+ */
+ private static Object convertToGenericObject(final String paramType, final
Object paramValue) {
+ if (isSingleType(paramType)) {
+ return paramValue;
+ }
+ final Map<String, Object> mapValue =
GsonUtils.getInstance().convertToMap(paramValue.toString());
+ GenericObject genericObject = new GenericObject(paramType);
+ mapValue.forEach(genericObject::putField);
+ return genericObject;
}
/**
* Convert to GenericObject.
*
- * @param type generic type.
- * @param param actual parameter.
+ * @param type generic type.
+ * @param params actual parameters.
* @return list of GenericObject.
*/
- @SuppressWarnings("all")
- private static List<GenericObject> convertToGenericObjects(final String
type, final Object param) {
- List<Map> mapList = GsonUtils.getInstance().fromList(param.toString(),
Map.class);
- return mapList.stream().map(map -> {
- GenericObject genericObject = new GenericObject(type);
- map.forEach((key, value) -> genericObject.putField((String) key,
value));
- return genericObject;
- }).collect(Collectors.toList());
+ private static List<Object> convertToGenericObjects(final String type,
final Iterable<Object> params) {
+ List<Object> list = new ArrayList<>();
+ for (Object param : params) {
+ list.add(convertToGenericObject(type, param));
+ }
+ return list;
}
/**
@@ -88,7 +132,19 @@ public class SofaParamResolveServiceImpl implements
SofaParamResolveService {
* @param parameter parameter array.
* @return only one parameter and it's customized type return true
otherwise return false.
*/
- private static boolean isSingleCustomizeType(final String[] parameter) {
- return parameter.length == 1 && !parameter[0].startsWith("java") &&
!parameter[0].startsWith("[Ljava");
+ private static boolean isSingleType(final String[] parameter) {
+ return parameter.length == 1 && isSingleType(parameter[0]);
}
+
+ /**
+ * is single type.<br>
+ * single type is package[java.xxx or [Ljava.xxx]
+ *
+ * @param parameterType parameter type.
+ * @return type is single type
+ */
+ private static boolean isSingleType(final String parameterType) {
+ return parameterType.startsWith("java");
+ }
+
}
diff --git
a/shenyu-plugin/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/param/SofaBodyParamResolveServiceTest.java
b/shenyu-plugin/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/param/SofaBodyParamResolveServiceTest.java
index 75ddd8b..d710caa 100644
---
a/shenyu-plugin/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/param/SofaBodyParamResolveServiceTest.java
+++
b/shenyu-plugin/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/param/SofaBodyParamResolveServiceTest.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.plugin.sofa.param;
+import com.alipay.hessian.generic.model.GenericObject;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Test;
@@ -93,32 +94,29 @@ public final class SofaBodyParamResolveServiceTest {
Pair<String[], Object[]> pair = impl.buildParameter(body,
parameterTypes);
assertThat(pair.getLeft().length, is(1));
assertThat(pair.getRight().length, is(1));
- Map map = (Map) pair.getRight()[0];
- map = (Map) map.get("student");
- assertNull(map.get("id"));
- assertNull(map.get("name"));
+ GenericObject student = (GenericObject) pair.getRight()[0];
+ assertNull(student.getField("id"));
+ assertNull(student.getField("name"));
body = "{\"students\":[{\"id\":null,\"name\":null}]}";
parameterTypes =
"org.apache.shenyu.web.rpc.DubboMultiParameterResolveServiceImplTest.Student[]";
pair = impl.buildParameter(body, parameterTypes);
assertThat(pair.getLeft().length, is(1));
assertThat(pair.getRight().length, is(1));
- map = (Map) pair.getRight()[0];
- List list = (List) map.get("students");
- map = (Map) list.get(0);
+ List list = (List) pair.getRight()[0];
+ Map map = (Map) list.get(0);
assertNull(map.get("id"));
assertNull(map.get("name"));
- body =
"{\"dubboTest\":{\"id\":null,\"name\":null},\"idLists\":[null,null],\"idMaps\":{\"id2\":null,\"id1\":null}}";
+ body =
"{\"complexBean\":{\"dubboTest\":{\"id\":null,\"name\":null},\"idLists\":[null,null],\"idMaps\":{\"id2\":null,\"id1\":null}}}";
parameterTypes =
"org.apache.shenyu.web.rpc.DubboMultiParameterResolveServiceImplTest.ComplexBean";
pair = impl.buildParameter(body, parameterTypes);
assertThat(pair.getLeft().length, is(1));
assertThat(pair.getRight().length, is(1));
- map = (Map) pair.getRight()[0];
- Map dubboTest = (Map) map.get("dubboTest");
- assertNull(dubboTest.get("id"));
- assertNull(dubboTest.get("name"));
- list = (List) map.get("idLists");
+ GenericObject dubboTest = (GenericObject) pair.getRight()[0];
+ assertNull(dubboTest.getField("id"));
+ assertNull(dubboTest.getField("name"));
+ list = (List) dubboTest.getField("idLists");
assertNull(list.get(0));
assertNull(list.get(1));