You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dotnet-learn-vs/WebMVC/WebMVCApi/md/java 动态执行代码,可以从数据库·拉代码执行的方式...

4.6 KiB

icon date category headerDepth
edit 2023-02-17
Java
5

java 动态执行代码,可以从数据库·拉代码执行的方式例子

DynamicJavaCompilerUtil.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;
    }
}