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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM