前端传参到后端反射类的方法调用? ?
我想从前端传一个完整的类的方法信息到后台, 然后让后端可以直接反射调用
目前是这样设计的, 传的参数结构大概是这样子
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> 为例
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