System.getProperty(“java.class.path”)不显示“WEB-INF / lib”和包含jar

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

由于编译abc.java文件所需的所有jars文件,因此在作为JUnit测试执行时上面运行正常。 但是当在服务器中运行相同的代码时,它无法找到所需的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文件?

他们设置java.class.path系统属性的方式是要求麻烦 – 最好不要这样做。 更优雅的方法是使用-classpath选项传入自定义类路径。 请参阅如何将JDK6 ToolProvider和JavaCompiler与上下文类加载器一起使用? 详情。

此问题也是有用的参考: 从自定义类加载器使用javax.tools.ToolProvider?


至于构建实际的类路径,您可以将上下文类加载器强制转换为URLClassLoader并从这些URL中获取文件(如本答案中所述 )。

或者你可以使用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文件)。 如果它没有扩展,那你就不走运了。

您不能依赖java.class.path来特别设置任何东西。

Java在启动包含servlet容器的整个JVM时建立此变量。 因为它为许多不同的目的创建了许多不同的类加载器,所以它不会改变它。 这不可以。 整个过程只有一个java.class.path值,但是每个webapp中可能有许多不同的webapps,实际上有很多不同的类加载器。

您将需要自己的显式配置机制来传达此类编译内容的类路径,并使用getRealPath构造路径名。

所以,我的问题是如何让编译器引用WEB-INF / lib目录中的jar文件?

假设扩展了webapp的WAR,您应该能够以编程方式创建一个类似于Web容器为您提供的类路径字符串。 它“简单地”是重复Web容器使用的有效类搜索路径的问题。

但是,我怀疑将“classpath”参数显式地或通过系统属性传递给编译器是错误的方法。 我在这篇IBM文章中找到了以下内容 。

编译Java源代码需要以下组件:

  • 一个类路径,编译器可以从中解析库类。 编译器类路径通常由包含以前编译的.class文件的文件系统目录和存档文件(JAR或ZIP文件)的有序列表组成。 类路径由JavaFileManager实现,该JavaFileManager管理多个源和类JavaFileObject实例以及传递给JavaFileManager构造函数的ClassLoader。 …

因此,似乎正确的方法是只获取相关的类加载器对象并将其传递给JavaFileManager构造函数。

假设您使用ANT来构建WAR文件。 您需要执行类似下面的操作,在WAR中包含WEB-INF / lib下的jar。 修改目录结构,因为它适合您的app目录结构。