我想从前端传一个完整的类的方法信息到后台, 然后让后端可以直接反射调用
目前是这样设计的, 传的参数结构大概是这样子
classloaderName : 类加载器名称
className: 类名称
methodName : 方法名
params: 参数列表 List
参数结构为:
type: 参数类型 String
name: 参数名称 String
value : 参数值 jsonString , 当是普通类型时为 {"value": 参数值} , 复杂类型时为 {"value": 参数JSON}
但现在遇到的问题是
- 泛型怎么传到后端
- 后端对于普通类型的转换问题
目前我的核心代码如下
/**
* 调用上传类的方法
* @param invokeMethodRequest
* @return
* @throws ClassNotFoundException
*/
public InvokeMethodResponse invokeMethod(InvokeMethodRequest invokeMethodRequest) throws ClassNotFoundException {
final ClassLoader classloader = classloaderService.getClassloader(invokeMethodRequest.getClassloaderName());
// 查找方法信息
List<Class<?>> paramTypes = new ArrayList<>();
for (InvokeMethodRequest.MethodParam param : invokeMethodRequest.getParams()) {
final String paramType = param.getParamType();
final Class<?> type = TypeSupport.getType(paramType, classloader);
paramTypes.add(type);
}
final Class<?> invokeClass = classloader.loadClass(invokeMethodRequest.getClassName());
final Method method = ReflectionUtils.findMethod(invokeClass, invokeMethodRequest.getMethodName(), paramTypes.toArray(new Class<?>[0]));
if (method == null){
final String paramTypeSimpleNames = paramTypes.stream().map(Class::getSimpleName).collect(Collectors.joining(","));
log.error("类[{}]调用方法[{}],参数类型列表[{}], 未找到方法",invokeClass.getSimpleName(),invokeMethodRequest.getMethodName(), paramTypeSimpleNames);
throw new ToolException("调用方法 "+ invokeMethodRequest.getMethodName()+ " 不存在");
}
// 组装参数信息
Object[] paramValues = new Object[invokeMethodRequest.getParams().size()];
for (int i = 0; i < invokeMethodRequest.getParams().size(); i++) {
InvokeMethodRequest.MethodParam param = invokeMethodRequest.getParams().get(i);
final String paramType = param.getParamType();
final String paramValueJson = param.getParamValueJson();
final JSONObject jsonObject = JSON.parseObject(paramValueJson);
final Class<?> paramTypeClass = TypeSupport.getType(paramType,classloader);
if (ClassUtils.isPrimitiveOrWrapper(paramTypeClass)){
// paramValues[i] = jsonObject.get("value");
paramValues[i] = Long.parseLong((String) jsonObject.get("value"));
}else if (paramTypeClass == String.class || paramTypeClass == BigDecimal.class){
paramValues[i] = jsonObject.get("value");
}else if (paramTypeClass == Date.class){
paramValues[i] = jsonObject.getDate("value");
}else {
if (paramTypeClass == List.class){
// paramValues[i] = .toJavaObject(paramTypeClass);
List list = new ArrayList<>();
paramValues[i] = list;
final JSONArray value = jsonObject.getJSONArray("value");
for (int j = 0; j < value.size(); j++) {
list.add(value.get(j));
}
}else {
paramValues[i] = jsonObject.getJSONObject("value").toJavaObject(paramTypeClass);
}
}
}
// 发起调用
long startTime = System.currentTimeMillis();
final Object o = ReflectUtils.newInstance(invokeClass);
final Object invokeResult = ReflectionUtils.invokeMethod(method, o, paramValues);
long spendTime = System.currentTimeMillis() - startTime;
log.info("[{}]方法调用耗时[{}ms]",method.getName(),spendTime);
final Class<?> returnType = method.getReturnType();
InvokeMethodRequest.MethodParam result = null;
if (returnType == Void.class){
result = new InvokeMethodRequest.MethodParam(returnType.getName());
}else {
result = new InvokeMethodRequest.MethodParam(returnType.getName(),JSON.toJSONString(invokeResult));
}
final InvokeMethodResponse invokeMethodResponse = new InvokeMethodResponse(spendTime,result);
return invokeMethodResponse;
}
InvokeMethodRequest
@Data
public class InvokeMethodRequest {
private String classloaderName;
@NotBlank
private String className;
@NotBlank
private String methodName;
private List<MethodParam> params = new ArrayList<>();
@Data
public static final class MethodParam{
/**
* 参数名称, 可以为空
*/
private String paramName;
/**
* 参数类型
*/
private String paramType;
/**
* 参数值 json 串
* {"value": 参数数据}
*/
private String paramValueJson;
public MethodParam() {
}
public MethodParam(String paramType) {
this.paramType = paramType;
}
public MethodParam(String paramType, String paramValueJson) {
this.paramType = paramType;
this.paramValueJson = paramValueJson;
}
public MethodParam(String paramName, String paramType, String paramValueJson) {
this.paramName = paramName;
this.paramType = paramType;
this.paramValueJson = paramValueJson;
}
}
}
1、泛型以数组形式使用其它参数另外传递
用 jackson 处理,以 Map<String, Integer> 为例
2、多层嵌套
Map<String, List<String>>
3、普通类型另做判断
例如
4、直接使用的标准答案