2010-11-25 28 views
1
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); 

上面运行正常时,因为用于编译所需的所有jars作为JUnit测试执行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.jarSystem.getProperty(“java.class.path”)不显示“WEB-INF/LIB”和包括罐子

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

+0

你是如何在应用程序中打包(生成WAR)的? – CoolBeans 2010-11-25 01:43:07

回答

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完成)。可以使用ServletContextgetRealPath(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 

警告:这两种方法ONLY工作,如果Web应用程序扩展(不是WAR文件)。如果它没有扩大,你运气不好。

-2

假设您使用ANT构建WAR文件。您需要执行下面的操作,以便在WAR中的WEB-INF/lib下包含jar。修改适合您的应用程序目录结构的目录结构。

<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> 
+0

我有一种感觉,他没有要求关于如何在Web应用程序中包含JAR文件的说明。 – 2010-11-25 08:49:39

+0

我不使用蚂蚁来构建。 Eclipse可以完成Web项目中的所有工作。 – brayne 2010-11-25 11:56:54

+0

@Neeme Praks - 他的问题在于打包应用程序。他依靠服务器类路径来查找包含在WEB-INF/lib文件夹中的jar文件。这是什么告诉你的? – CoolBeans 2010-11-25 16:22:25

3

你不能依赖java.class.path来将其设置为特定的任何东西。

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

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

2

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

如果Web应用程序的WAR已扩展,您应该能够以编程方式创建与Web容器为您提供的对应类路径字符串。这仅仅是复制Web容器使用的有效类搜索路径的问题。

但是,我怀疑为编译器显式或通过系统属性传递“classpath”参数是错误的方法。我在this IBM article找到了以下内容。

编译Java源需要以下组件:

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

所以它似乎是正确的做法是只获取相关的类加载器对象,并把它传递给JavaFileManager构造函数。