Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 382|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-6-25 12:16:33 | 显示全部楼层 |阅读模式

    一、问题

      动态编译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;
            }
        }
    }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-1 19:44 , Processed in 0.062881 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表