String CompilePath = "abc.java";
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
String classpath = System.getProperty("java.class.path");
System.setProperty("java.class.path", classpath + ";" + LocalMachine.home + "WebContent/WEB-INF/lib");
int result = compiler.run(null, null, null, CompilePath);
上面运行时作为JUnit测试运行正常,因为编译jars
文件需要abc.java
。但是当在服务器中运行相同的代码时,它无法找到所需的jar
文件。 System.getProperty("java.class.path")
的输出是
E:\apache-tomcat-7.0.4\bin\bootstrap.jar;E:\apache-tomcat-7.0.4\bin\tomcat-juli.jar;C:\Program Files\Java\jdk1.6.0_21\lib\tools.jar
所以,我的问题是如何让编译器引用WEB-INF / lib目录中的jar文件?
答案 0 :(得分:3)
您不能依赖java.class.path将其设置为特定的任何内容。
Java在启动包含servlet容器的整个JVM时建立此变量。因为它为许多不同的目的创建了许多不同的类加载器,所以它不会改变它。这不可以。整个过程只有一个java.class.path值,但是每个webapp中可以有许多不同的webapps,实际上有很多不同的类加载器。
您将需要自己的显式配置机制来传达此类编译内容的类路径,并使用getRealPath构建路径名。
答案 1 :(得分:2)
所以,我的问题是如何让编译器引用WEB-INF / lib目录中的jar文件?
假设扩展了webapp的WAR,您应该能够以编程方式创建一个类似于Web容器为您提供的类路径字符串。它“简单地”是重复Web容器使用的有效类搜索路径的问题。
但是,我怀疑将“classpath”参数显式地或通过系统属性传递给编译器是错误的方法。我在this IBM article中找到了以下内容。
编译Java源代码需要以下组件:
- 一个类路径,编译器从该路径开始 可以解析库类。该 编译器类路径通常是 由有序的文件列表组成 系统目录和存档文件 (JAR或ZIP文件)包含 以前编译的.class文件。该 classpath由a实现 管理多个的JavaFileManager 源和类JavaFileObject 实例和ClassLoader传递 到JavaFileManager构造函数。 ...
所以看起来正确的方法是获取相关的类加载器对象并将其传递给JavaFileManager构造函数。
答案 2 :(得分:0)
他们设置java.class.path系统属性的方式是要求麻烦 - 最好不要这样做。 更优雅的方法是使用-classpath
选项传递自定义类路径。有关详细信息,请参阅How do I use JDK6 ToolProvider and JavaCompiler with the context classloader?。
这个问题也很有用:Using javax.tools.ToolProvider from a custom classloader?
关于构建实际的类路径,您可以将上下文类加载器强制转换为URLClassLoader
,并从这些URL中获取文件(如this answer中所述)。
或者您可以使用ServletContext。getRealPath(String)
和手动构建整个类路径:
ServletConfig cfg = ...; //obtained in Servlet.init(ServletConfig) method
ServletContex ctx = cfg.getServletContext();
String realWebInfPath = ctx.getRealPath("WEB-INF/lib");
//TODO use the realWebInfPath to create a File object and iterate over all JAR files
警告:如果展开Web应用程序(不是WAR文件),两种方法都 ONLY 。如果它没有扩展,那你就不走运了。
答案 3 :(得分:-2)
假设您正在使用ANT来构建WAR文件。您需要执行类似下面的操作,在WAR中包含WEB-INF / lib下的jar。修改目录结构,因为它适合您的app目录结构。
<war warfile="yourApp.war" webxml="WEB-INF/web.xml">
<fileset dir="yourWarDir">
<include name="**/*.jsp"/>
<include name="**/include/**"/>
</fileset>
<include name="WEB-INF/lib/*"/>
<include name="WEB-INF/classes/**"/>
</war>