System.getProperty ("java.class.path") не показывает "WEB-INF / lib" и включающие jar - PullRequest
1 голос
/ 25 ноября 2010
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

Итак, мой вопрос: как заставить компилятор ссылаться на файлы jar из каталога WEB-INF / lib?

Ответы [ 4 ]

3 голосов
/ 25 ноября 2010

Вы не можете зависеть от java.class.path, установленного для чего-либо конкретного.

Java устанавливает эту переменную, когда запускает всю JVM, содержащую ваш контейнер сервлета.Так как он создает много разных загрузчиков классов для многих других целей, он не меняет его.Это не может.Для всего процесса существует только одно значение java.class.path, но в каждом веб-приложении может быть много разных веб-приложений и даже много разных загрузчиков классов.

Вам потребуется собственный явный механизм конфигурации для связипуть к классу для такого рода материалов компиляции и использование getRealPath для создания путей.

2 голосов
/ 25 ноября 2010

Итак, мой вопрос: как заставить компилятор ссылаться на файлы jar из каталога WEB-INF / lib?

При условии, что WAR веб-приложения расширен, вы должны иметь возможность программно создать строку пути к классу, которая соответствует тому, что дает вам веб-контейнер. Это просто вопрос дублирования эффективного пути поиска классов, который использует веб-контейнер.

Однако я подозреваю, что передача аргумента "classpath" в компилятор явно или через свойства System является неправильным подходом. Я нашел следующее в этой статье IBM .

Для компиляции исходного кода Java требуются следующие компоненты:

  • classpath, из которого компилятор может разрешить библиотечные классы. classpath компилятора обычно состоит из упорядоченного списка файлов системные каталоги и архивные файлы (Файлы JAR или ZIP), содержащие предварительно скомпилированные файлы .class. путь к классу реализуется JavaFileManager, который управляет несколькими исходный код и класс JavaFileObject экземпляры и ClassLoader переданы в конструктор JavaFileManager. ...

Таким образом, может показаться, что правильный подход - просто взять соответствующий объект загрузчика классов и передать его конструктору JavaFileManager.

0 голосов
/ 25 ноября 2010

То, как вы устанавливаете системное свойство 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

Предупреждение : оба подхода ТОЛЬКО работают, если веб-приложение развернуто (неФайл WAR).Если он не расширен, вам не повезло.

0 голосов
/ 25 ноября 2010

Предполагается, что вы используете ANT для создания файла WAR. Вам нужно сделать что-то похожее на приведенное ниже, чтобы включить файлы jar под WEB-INF / lib в WAR Измените структуру каталогов так, чтобы она соответствовала структуре каталогов вашего приложения.

<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>
...