Доступ к ресурсам из другого файла JAR
У меня есть простая структура: файл JAR данных, который содержит пакет данных, и файл JAR службы, который запускает службу с использованием данных. Чтобы данные были легко заменить, у меня есть отдельные, и classpath service.jar содержит каталог, в котором находится data.jar.
В service.jar я использую getResource для загрузки файлов данных. Это работает, если файлы данных находятся непосредственно в папке, но завершается ошибкой, когда они находятся внутри data.jar;
Это не удается:
all
+ globalclasspath
| + data.jar
| + mine.properties
+ daemons
+ service.jar
jsvc -cp globalclasspath:daemons/service.jar (...)
MyClass.class.getClassLoader( ).getResource( "mine.properties" ); // <-- null
Но это работает:
all
+ globalclasspath
| + mine.properties
+ daemons
+ service.jar
jsvc -cp globalclasspath:daemons/service.jar (...)
MyClass.class.getClassLoader( ).getResource( "mine.properties" ); // <-- not null
Я не хочу менять путь к классу (если я не могу изменить его на что-то общее, что не зависит от имени файла JAR данных), но я в порядке с изменением строки getResource (я пытался / данные /mine.properties и /data.jar/mine.properties безрезультатно). Могу ли я внести изменения, чтобы ресурсы могли быть загружены из фляги?
3 ответа
Решение 1
Используйте подстановочный знак classpath.
jsvc -cp globalclasspath/*:daemons/service.jar (...)
См. " Как использовать подстановочный знак в пути к классам для добавления нескольких банок? "
Решение 2
Чтобы прочитать данные в JAR-файлах, не находящихся на пути к классам, используйте URLClassLoader
, Общий алгоритм таков:
- Найдите список JAR в
globalclasspath
каталог. - Создать
URLClassLoader
из этого списка JAR. - Найдите нужный вам ресурс из
URLClassLoader
пример.
Чтобы найти JAR на пути к классам, я использовал ResourceList
из статьи Stackru " Получить список ресурсов из каталога classpath ".
public class MyClass {
/**
* Creates a {@code URLClassLoader} from JAR files found in the
* globalclasspath directory, assuming that globalclasspath is in
* {@code System.getProperty("java.class.path")}.
*/
private static URLClassLoader createURLClassLoader() {
Collection<String> resources = ResourceList.getResources(Pattern.compile(".*\\.jar"));
Collection<URL> urls = new ArrayList<URL>();
for (String resource : resources) {
File file = new File(resource);
// Ensure that the JAR exists
// and is in the globalclasspath directory.
if (file.isFile() && "globalclasspath".equals(file.getParentFile().getName())) {
try {
urls.add(file.toURI().toURL());
} catch (MalformedURLException e) {
// This should never happen.
e.printStackTrace();
}
}
}
return new URLClassLoader(urls.toArray(new URL[urls.size()]));
}
public static void main(String[] args) {
URLClassLoader classLoader = createURLClassLoader();
System.out.println(classLoader.getResource("mine.properties"));
}
}
Я выполнил следующую команду:
java -cp globalclasspath:daemons/service.jar MyClass
Выход терминала:
jar:file:/workspace/all/globalclasspath/data.jar!/mine.properties
Ты пытался getResourceAsStream
как предложено здесь:
You can now use the
maven-resources-plugin
to share resources between your jars!
In the pom.xml file of the source module/jar, add the following plugin:
<artifactId>DATA_MODULE_NAME</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
</plugins>
</build>
This will tell maven to copy the contents of the resource folder along with the jar.
In the module you want to access those resources, add this to the dependencies in the pom:
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>DATA_MODULE_NAME</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
When you build your final jar, the resources from the source module will be copied in and available using
getResources()