Java Web部署到tomcat后,使用动态编译无法找到相关类的解决方案

Java Web部署到tomcat后,使用动态编译无法找到相关类的解决方案

一、问题

动态编译java文件时(这个java文件虽引用了第三方jar包),如果这个过程发生在java命令行程序中,则正常编译。如果发生在JavaWeb中,然后此Java部署到Tomcat之后,执行动态编译时,就会提示找不到相关类或者Jar。

二、解决方案

将所依赖到的Jar文件,复制到%JAVA_Home%\jre\lib\ext目录下。 例如:C:\Program
Files\Java\jdk1.8.0_161\jre\lib\ext 再重启Tomcat。

三、解决方法二:

编译时,添加classPath参数,即可,DEMO代码很乱,参考如下:

package servlets;

import com.github.henryhuang.dynamiccompiler.ClassGenerator;
import domain.MyJavaSourceFromString;
import org.apache.commons.io.FileUtils;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        try {

            String buildOutput = MyServlet.class.getProtectionDomain().getCodeSource().getLocation().getPath();
            File f = new File("D:\\Project\\JavaProject\\dynamicompileInWeb\\out\\artifacts\\web_war_exploded", "WEB-INF\\TestCode.java");
            String code = FileUtils.readFileToString(f, "UTF-8");
            resp.getWriter().write(code);

            // instantiate the Java compiler
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            JavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);

            // load the uploaded files into the compiler
            List<JavaFileObject> files = new ArrayList<JavaFileObject>();
            //files.add(new ByteArrayJavaFileObject(fullName, patchFile.getBytes()));

            files.add(new MyJavaSourceFromString("TestCode", code));
            // set the classpath
            List<String> options = new ArrayList<String>();

            options.add("-classpath");
            StringBuilder sb = new StringBuilder();
            URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
            for (URL url : urlClassLoader.getURLs()) {
                sb.append(url.getFile()).append(File.pathSeparator);
            }
            options.add(sb.toString());
            options.add("-d");
            options.add(buildOutput);
            // execute the compiler
            boolean isok = compiler.getTask(null, fileManager, null, options, null, files).call();
            System.out.println(isok);
            File root = new File(buildOutput);
            if (!root.exists()) root.mkdirs();
            URL[] urls = new URL[]{root.toURI().toURL()};
            URLClassLoader classLoader = URLClassLoader.newInstance(urls);
            Class<?> clazz2 = Class.forName("TestCode", true, classLoader);

            // instantiate the class (FAILS HERE)
            //Object instance = fileManager.getClassLoader(null).loadClass("TestCode").newInstance();

            // close the file manager
            fileManager.close();

            //
            //if (clazz != null) {
            //    resp.getWriter().write("\r\n" + clazz + ":compile success.");
            //} else {
            //    resp.getWriter().write("\r\n" + clazz + ":compile failed.");
            //}

        } catch (Exception ex) {
            resp.getWriter().write(ex.getMessage());
        }

    }
}

简单封装

package com.test.utils.compile;

import org.apache.commons.io.FileUtils;
import com.test.utils.context.AppContext;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;


public class ClassBuilder {

    public static Class<?> buildClass(String fullClassName, String codeFilePath) throws IOException, ClassNotFoundException {

        return buildClass(fullClassName, codeFilePath, "UTF-8", AppContext.baseDirectory());
    }

    public static Class<?> buildClass(String fullClassName, String codeFilePath, String charsetName, String buildOutput) throws IOException, ClassNotFoundException {
        try {
            String code = FileUtils.readFileToString(FileUtils.getFile(codeFilePath), charsetName);
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            JavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
            List<JavaFileObject> files = new ArrayList<>();
            files.add(new JavaSourceFromCodeString(fullClassName, code));
            List<String> options = new ArrayList<>();
            options.add("-classpath");
            StringBuilder sb = new StringBuilder();
            URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
            for (URL url : urlClassLoader.getURLs()) {
                sb.append(url.getFile()).append(File.pathSeparator);
            }
            options.add(sb.toString());
            options.add("-d");
            options.add(buildOutput);
            // execute the compiler
            boolean isok = compiler.getTask(null, fileManager, null, options, null, files).call();
            if (isok) {
                File root = new File(buildOutput);
                if (!root.exists()) root.mkdirs();
                URL[] urls = new URL[]{root.toURI().toURL()};
                ClassLoader classLoader = ClassBuilder.class.getClassLoader();
                Class<?> clazz = Class.forName(fullClassName, true, classLoader);
                return clazz;
            }
            return null;
        } catch (Exception ex) {
            throw ex;
        }
    }
}

Java Web部署到tomcat后,使用动态编译无法找到相关类的解决方案
https://www.dearcloud.cn/2018/05/02/20200310-cnblogs-old-posts/20180502-JavaWeb部署到tomcat后,使用动态编译无法找到相关类的解决方案/
作者
宋兴柱
发布于
2018年5月2日
许可协议