前端传参到后端反射类的方法调用? ?

我想从前端传一个完整的类的方法信息到后台, 然后让后端可以直接反射调用

目前是这样设计的, 传的参数结构大概是这样子

classloaderName : 类加载器名称

className: 类名称

methodName : 方法名

params: 参数列表 List

参数结构为:

type: 参数类型 String

name: 参数名称 String

value : 参数值 jsonString , 当是普通类型时为 {"value": 参数值} , 复杂类型时为 {"value": 参数JSON}

但现在遇到的问题是

  1. 泛型怎么传到后端
  2. 后端对于普通类型的转换问题

目前我的核心代码如下

/**

* 调用上传类的方法

* @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> 为例

    public static void main(String[] args) throws JsonProcessingException, ClassNotFoundException {

Class mainClass = Class.forName("java.util.Map");

// 泛型部分,组装成数组

Class g1 = Class.forName("java.lang.String");

Class g2 = Class.forName("java.lang.Integer");

JavaType javaType = TypeFactory.defaultInstance().constructParametricType(mainClass, g1, g2);

ObjectMapper objectMapper = new ObjectMapper();

String json = "{\"xxx\":123,\"yyy\":345}";

Object value = objectMapper.readValue(json, javaType);

System.out.println(value);

}

2、多层嵌套 Map<String, List<String>>

    public static void main(String[] args) throws JsonProcessingException, ClassNotFoundException {

Class mainClass = Class.forName("java.util.Map");

Class g1 = Class.forName("java.lang.String");

Class listClass = Class.forName("java.util.List");

Class listClassG1 = Class.forName("java.lang.String");

JavaType type = TypeFactory.defaultInstance().constructParametricType(listClass, listClassG1);

JavaType javaType = TypeFactory.defaultInstance().constructParametricType(mainClass, g1, type.getRawClass());

ObjectMapper objectMapper = new ObjectMapper();

String json = "{\"xxx\":[\"123\"],\"yyy\":[\"456\"]}";

Object value = objectMapper.readValue(json, javaType);

System.out.println(value);

}

3、普通类型另做判断
例如

if (type == "java.lang.String") {

// code

}

4、直接使用的标准答案

public class Test {

public static void main(String[] args) throws JsonProcessingException {

ObjectMapper objectMapper = new ObjectMapper();

String classInfo = "{\n" +

" \"className\":\"java.util.Map\",\n" +

" \"genericClass\":[\n" +

" {\n" +

" \"className\":\"java.lang.String\"\n" +

" },\n" +

" {\n" +

" \"className\":\"java.util.List\",\n" +

" \"genericClass\":[\n" +

" {\n" +

" \"className\":\"java.lang.String\"\n" +

" }\n" +

" ]\n" +

" }\n" +

" ]\n" +

"}";

NestClass nestClass = objectMapper.readValue(classInfo, NestClass.class);

JavaType javaType = nestClass.toClass();

System.out.println(javaType);

String json = "{\"456\":[\"789\"]}";

Object value = objectMapper.readValue(json, javaType);

System.out.println(value);

}

static class NestClass {

private String className;

private List<NestClass> genericClass;

public JavaType toClass() {

Class<?> mainClass;

try {

mainClass = Class.forName(className);

} catch (ClassNotFoundException e) {

throw new RuntimeException(e);

}

if (genericClass != null && genericClass.size() != 0) {

List<JavaType> collect = genericClass.stream().map(NestClass::toClass).collect(Collectors.toList());

return TypeFactory.defaultInstance().constructParametricType(mainClass, collect.toArray(new JavaType[]{}));

}

return TypeFactory.defaultInstance().constructType(mainClass);

}

public void setClassName(String className) {

this.className = className;

}

public void setGenericClass(List<NestClass> genericClass) {

this.genericClass = genericClass;

}

}

}

以上是 前端传参到后端反射类的方法调用? ? 的全部内容, 来源链接: utcz.com/p/944660.html

回到顶部