Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增强泛化调用,支持List<POJO>做参数情况下的泛化调用 #1043

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ public interface CommonClient {
* build request with interfaceName, methodName and arguments
*/
Request buildRequest(String interfaceName, String methodName, Object[] arguments);

}
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,5 @@ public Request buildRequest(String methodName, Object[] arguments) {
public Request buildRequest(String interfaceName, String methodName, Object[] arguments) {
return MotanClientUtil.buildRequest(interfaceName, methodName, arguments);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,9 @@ public Request buildRequest(String methodName, Object[] arguments) {
public Request buildRequest(String interfaceName, String methodName, Object[] arguments) {
return MotanClientUtil.buildRequest(interfaceName, methodName, arguments);
}

public Request buildRequestV1(String interfaceName, String methodName, Object[] arguments,String parametersDesc) {
return MotanClientUtil.buildRequestV1(interfaceName, methodName, arguments,parametersDesc);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.weibo.api.motan.exception.MotanServiceException;
import com.weibo.api.motan.util.ExceptionUtil;
import com.weibo.api.motan.util.LoggerUtil;
import com.weibo.api.motan.util.PojoUtils;

import java.lang.reflect.Method;

Expand Down Expand Up @@ -62,7 +63,10 @@ public Response invoke(Request request) {

boolean defaultThrowExceptionStack = URLParamType.transExceptionStack.getBooleanValue();
try {
Object value = method.invoke(proxyImpl, request.getArguments());
//如果是List<T>做参数,在泛化调用的情况下,这里需要做特殊处理
//TODO 这里默认无法感知到是不是泛化调用过来的请求
Object[] arguments = PojoUtils.realize(request.getArguments(),method.getParameterTypes(),method.getGenericParameterTypes());
Object value = method.invoke(proxyImpl,arguments);
response.setValue(value);
} catch (Exception e) {
if (e.getCause() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ private void processLazyDeserialize(Request request, Method method) {
&& request.getArguments()[0] instanceof DeserializableObject
&& request instanceof DefaultRequest) {
try {
//反序列化操作
Object[] args = ((DeserializableObject) request.getArguments()[0]).deserializeMulti(method.getParameterTypes());
((DefaultRequest) request).setArguments(args);
} catch (IOException e) {
Expand Down
53 changes: 53 additions & 0 deletions motan-core/src/main/java/com/weibo/api/motan/util/ClassUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.weibo.api.motan.util;

/**
* @author dinglang
* @since 2023/9/4
*/
public class ClassUtils {
public static ClassLoader getClassLoader(Class<?> clazz) {
ClassLoader cl = null;
if (!clazz.getName().startsWith("org.apache.dubbo")) {
cl = clazz.getClassLoader();
}
if (cl == null) {
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (Exception ignored) {
// Cannot access thread context ClassLoader - falling back to system class loader...
}
if (cl == null) {
// No thread context class loader -> use class loader of this class.
cl = clazz.getClassLoader();
if (cl == null) {
// getClassLoader() returning null indicates the bootstrap ClassLoader
try {
cl = ClassLoader.getSystemClassLoader();
} catch (Exception ignored) {
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
}
}
}
}

return cl;
}

/**
* Return the default ClassLoader to use: typically the thread context
* ClassLoader, if available; the ClassLoader that loaded the ClassUtils
* class will be used as fallback.
* <p>
* Call this method if you intend to use the thread context ClassLoader in a
* scenario where you absolutely need a non-null ClassLoader reference: for
* example, for class path resource loading (but not necessarily for
* <code>Class.forName</code>, which accepts a <code>null</code> ClassLoader
* reference as well).
*
* @return the default ClassLoader (never <code>null</code>)
* @see java.lang.Thread#getContextClassLoader()
*/
public static ClassLoader getClassLoader() {
return getClassLoader(ClassUtils.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@

package com.weibo.api.motan.util;

import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

public class CompatibleTypeUtils {

private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

/**
* the text to parse such as "2007-12-03T10:15:30"
*/
private static final int ISO_LOCAL_DATE_TIME_MIN_LEN = 19;

private CompatibleTypeUtils() {
}

/**
* Compatible type convert. Null value is allowed to pass in. If no conversion is needed, then the original value
* will be returned.
* <p>
* Supported compatible type conversions include (primary types and corresponding wrappers are not listed):
* <ul>
* <li> String -> char, enum, Date
* <li> byte, short, int, long -> byte, short, int, long
* <li> float, double -> float, double
* </ul>
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static Object compatibleTypeConvert(Object value, Class<?> type) {
if (value == null || type == null || type.isAssignableFrom(value.getClass())) {
return value;
}

if (value instanceof String) {
String string = (String) value;
if (char.class.equals(type) || Character.class.equals(type)) {
if (string.length() != 1) {
throw new IllegalArgumentException(String.format("CAN NOT convert String(%s) to char!" +
" when convert String to char, the String MUST only 1 char.", string));
}
return string.charAt(0);
}
if (type.isEnum()) {
return Enum.valueOf((Class<Enum>) type, string);
}
if (type == BigInteger.class) {
return new BigInteger(string);
}
if (type == BigDecimal.class) {
return new BigDecimal(string);
}
if (type == Short.class || type == short.class) {
return new Short(string);
}
if (type == Integer.class || type == int.class) {
return new Integer(string);
}
if (type == Long.class || type == long.class) {
return new Long(string);
}
if (type == Double.class || type == double.class) {
return new Double(string);
}
if (type == Float.class || type == float.class) {
return new Float(string);
}
if (type == Byte.class || type == byte.class) {
return new Byte(string);
}
if (type == Boolean.class || type == boolean.class) {
return Boolean.valueOf(string);
}
if (type == Date.class || type == java.sql.Date.class || type == java.sql.Timestamp.class
|| type == java.sql.Time.class) {
try {
Date date = new SimpleDateFormat(DATE_FORMAT).parse(string);
if (type == java.sql.Date.class) {
return new java.sql.Date(date.getTime());
}
if (type == java.sql.Timestamp.class) {
return new java.sql.Timestamp(date.getTime());
}
if (type == java.sql.Time.class) {
return new java.sql.Time(date.getTime());
}
return date;
} catch (ParseException e) {
throw new IllegalStateException("Failed to parse date " + value + " by format "
+ DATE_FORMAT + ", cause: " + e.getMessage(), e);
}
}
if (type == LocalDateTime.class) {
if (StringUtils.isEmpty(string)) {
return null;
}
return LocalDateTime.parse(string);
}
if (type == LocalDate.class) {
if (StringUtils.isEmpty(string)) {
return null;
}
return LocalDate.parse(string);
}
if (type == LocalTime.class) {
if (StringUtils.isEmpty(string)) {
return null;
}

if (string.length() >= ISO_LOCAL_DATE_TIME_MIN_LEN) {
return LocalDateTime.parse(string).toLocalTime();
} else {
return LocalTime.parse(string);
}
}
if (type == Class.class) {
try {
return ReflectUtil.name2class(string);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
if (char[].class.equals(type)) {
// Process string to char array for generic invoke
// See
// - https://github.com/apache/dubbo/issues/2003
int len = string.length();
char[] chars = new char[len];
string.getChars(0, len, chars, 0);
return chars;
}
}
if (value instanceof Number) {
Number number = (Number) value;
if (type == byte.class || type == Byte.class) {
return number.byteValue();
}
if (type == short.class || type == Short.class) {
return number.shortValue();
}
if (type == int.class || type == Integer.class) {
return number.intValue();
}
if (type == long.class || type == Long.class) {
return number.longValue();
}
if (type == float.class || type == Float.class) {
return number.floatValue();
}
if (type == double.class || type == Double.class) {
return number.doubleValue();
}
if (type == BigInteger.class) {
return BigInteger.valueOf(number.longValue());
}
if (type == BigDecimal.class) {
return new BigDecimal(number.toString());
}
if (type == Date.class) {
return new Date(number.longValue());
}
if (type == boolean.class || type == Boolean.class) {
return 0 != number.intValue();
}
}
if (value instanceof Collection) {
Collection collection = (Collection) value;
if (type.isArray()) {
int length = collection.size();
Object array = Array.newInstance(type.getComponentType(), length);
int i = 0;
for (Object item : collection) {
Array.set(array, i++, item);
}
return array;
}
if (!type.isInterface()) {
try {
Collection result = (Collection) type.getDeclaredConstructor().newInstance();
result.addAll(collection);
return result;
} catch (Throwable ignored) {
}
}
if (type == List.class) {
return new ArrayList<Object>(collection);
}
if (type == Set.class) {
return new HashSet<Object>(collection);
}
}
if (value.getClass().isArray() && Collection.class.isAssignableFrom(type)) {
int length = Array.getLength(value);
Collection collection;
if (!type.isInterface()) {
try {
collection = (Collection) type.getDeclaredConstructor().newInstance();
} catch (Exception e) {
collection = new ArrayList<Object>(length);
}
} else if (type == Set.class) {
collection = new HashSet<Object>(Math.max((int) (length/.75f) + 1, 16));
} else {
collection = new ArrayList<Object>(length);
}
for (int i = 0; i < length; i++) {
collection.add(Array.get(value, i));
}
return collection;
}
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public static Request buildRequest(String interfaceName, String methodName, Obje
return buildRequest(interfaceName, methodName, arguments, null);
}

public static Request buildRequestV1(String interfaceName, String methodName, Object[] arguments,String parametersDesc) {
return buildRequest(interfaceName, methodName, parametersDesc,arguments, null);
}

public static Request buildRequest(String interfaceName, String methodName, Object[] arguments, Map<String, String> attachments) {
return buildRequest(interfaceName, methodName, null, arguments, attachments);
}
Expand Down
Loading