127 lines
4.6 KiB
Markdown
127 lines
4.6 KiB
Markdown
---
|
||
icon: edit
|
||
date: 2023-02-17
|
||
category:
|
||
- Java
|
||
headerDepth: 5
|
||
---
|
||
|
||
|
||
# java 动态执行代码,可以从数据库·拉代码执行的方式例子
|
||
```DynamicJavaCompilerUtil.java```
|
||
```java
|
||
import javax.tools.JavaCompiler;
|
||
import javax.tools.ToolProvider;
|
||
import java.io.File;
|
||
import java.io.IOException;
|
||
import java.io.RandomAccessFile;
|
||
import java.lang.reflect.InvocationTargetException;
|
||
import java.lang.reflect.Method;
|
||
import java.net.URL;
|
||
import java.net.URLClassLoader;
|
||
import java.util.Arrays;
|
||
import java.util.stream.Collectors;
|
||
|
||
public class DynamicJavaCompilerUtil {
|
||
|
||
static String tmpPath = "./tmp";
|
||
|
||
|
||
public static void Test() throws IOException {
|
||
String code = new String("public class T4{ " +
|
||
"static void print(String a){ " +
|
||
"System.out.println(\"Hello world! \"+ a);" +
|
||
"}" +
|
||
"static void print(){ " +
|
||
"System.out.println(\"Hello world! \");" +
|
||
"}" +
|
||
"static void print(Integer a,String b){ " +
|
||
"System.out.println(\"Hello world! \"+a+b);" +
|
||
"}" +
|
||
"}");
|
||
CompilerToRun(code, "T4", "print", 1, " 2");
|
||
}
|
||
|
||
/*
|
||
* @param Code 代码字符串
|
||
* @param ClassName 类名
|
||
* @param MethodName 需要执行的方法名
|
||
* @param MethodParam 需要执行的方法的参数
|
||
*/
|
||
public static void CompilerToRun(String Code, String ClassName, String MethodName, Object... MethodParam) throws IOException {
|
||
isDirExists(new File(tmpPath));
|
||
File file = new File(tmpPath + "/" + ClassName + ".java");
|
||
RandomAccessFile accessFile = null;
|
||
try {
|
||
accessFile = new RandomAccessFile(file, "rw");
|
||
accessFile.write(Code.getBytes());
|
||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); //调用动态编译的工具
|
||
int result = compiler.run(null, null, null, tmpPath + "/" + ClassName + ".java"); //进行动态编译,并返回结果
|
||
if (result != 0) {
|
||
throw new RuntimeException("编译失败");
|
||
}
|
||
//通过反射方法动态执行
|
||
//1、首先构建文件的目录url地址,
|
||
URL[] urls = new URL[]{new URL("file:" + tmpPath + "/")};
|
||
//2、使用URLClassLoader对象的loadClass方法加载对应类
|
||
URLClassLoader loder = new URLClassLoader(urls);
|
||
//3、获取所加载类的方法
|
||
Class clazz = loder.loadClass(ClassName);
|
||
|
||
Class[] MethodParamClass = Arrays.asList(MethodParam).stream().map(Object::getClass).collect(Collectors.toList()).toArray(new Class[]{});
|
||
// 4、传入方法所需的参数通过invoke运行方法
|
||
Method method = clazz.getDeclaredMethod(MethodName, MethodParamClass);
|
||
method.setAccessible(true);
|
||
method.invoke(null, MethodParam); //当类型为String[]时,需要(Object)new String[] {}初始化
|
||
} catch (IOException e) {
|
||
throw new RuntimeException(e);
|
||
} catch (ClassNotFoundException e) {
|
||
throw new RuntimeException(e);
|
||
} catch (InvocationTargetException e) {
|
||
throw new RuntimeException(e);
|
||
} catch (NoSuchMethodException e) {
|
||
throw new RuntimeException(e);
|
||
} catch (IllegalAccessException e) {
|
||
throw new RuntimeException(e);
|
||
} finally {
|
||
accessFile.close();
|
||
deleteFile(new File(tmpPath));
|
||
}
|
||
|
||
}
|
||
|
||
private static void isDirExists(File file) {
|
||
if (!file.exists()) {
|
||
file.mkdir();
|
||
}
|
||
}
|
||
|
||
private static Boolean deleteFile(File file) {
|
||
//判断文件不为null或文件目录存在
|
||
if (file == null || !file.exists()) {
|
||
System.out.println("文件删除失败,请检查文件是否存在以及文件路径是否正确");
|
||
return false;
|
||
}
|
||
//获取目录下子文件
|
||
File[] files = file.listFiles();
|
||
//遍历该目录下的文件对象
|
||
for (File f : files) {
|
||
//判断子目录是否存在子目录,如果是文件则删除
|
||
if (f.isDirectory()) {
|
||
//递归删除目录下的文件
|
||
deleteFile(f);
|
||
} else {
|
||
//文件删除
|
||
f.delete();
|
||
//打印文件名
|
||
System.out.println("文件名:" + f.getName());
|
||
}
|
||
}
|
||
//文件夹删除
|
||
file.delete();
|
||
System.out.println("目录名:" + file.getName());
|
||
return true;
|
||
}
|
||
}
|
||
|
||
``` |