Это как-то связано с с , но у меня это не сработало.
Вопрос сформулирован в одном предложении
Как добавить библиотеки для весенней загрузки, используя loader.path
или что-то подобное при запуске веб-приложения, упакованного в файл WAR?
Что я хочу / Что я пробовал
Я хочу использовать свойство loader.path
Spring Boot. Проблема в том, что весенняя загрузка не распознает его. Я думал, что это может быть потому, что я экспортировал проект в виде WAR
файла.
Это мой код, предназначенный для загрузки другого приложения и библиотеки:
public static void load(String jarPath,String className,String methodName) throws MalformedURLException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
/*my old solution
URL[] urls={new File(jarPath).toURI().toURL()};
ClassLoader loader=AccessController.doPrivileged((PrivilegedAction<URLClassLoader>)()->new ParentPreferringURLClassLoader(urls,WebBot.class.getClassLoader()));
*/
ClassLoader loader=Thread.currentThread().getContextClassLoader();
Class<?> clazz = loader.loadClass(className);
Method method = clazz.getMethod(methodName);
Object ret = method.invoke(null);
if(ret instanceof MyCommunicationClass) {
MyCommunicationClass com=ret;
}else {
throw new IllegalArgumentException("the communication object supplier returned a "+ret.getClass().getCanonicalName()+": "+ret);
}
}
Соответствующие части pom.xml
в моем веб-приложении:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<packaging>war</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>Group ID of the shared library</groupId>
<artifactId>Artefact ID of the shared library</artifactId>
<version>Version of the shared library</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Примените части моего pom.xml
в другом приложении:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
</project>
<dependencies>
<dependency>
<groupId>Group ID of the shared library</groupId>
<artifactId>Artefact ID of the shared library</artifactId>
<version>Version of the shared library</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin><!-- assembly (JAR) -->
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>io.github.jdiscordbots.nightdream.core.NightDream</mainClass>
</manifest>
</archive>
<finalName>NightDream</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
После упаковки обоих приложений с помощью mvn clean package
я запускаю веб-приложение, которое должно запускать другое приложение, используя java -Dloader.path="file:../otherApplication/target/other.jar" -Dloader.debug=true -jar target\MyWebApplication.war
Проблема в том, что Thread.currentThread().getContextClassLoader().loadClass(className)
выдает ClassNotFoundException
при попытке загрузить класс связи.
Я могу убедиться, что свойства устанавливаются с помощью System.getProperty()
, но я не получаю никаких дополнительных данных отладчика для загрузчика и не могу загрузить класс.
Кажется, что я что-то пропустил при установке loader.path
(и loader.debug
) свойство.
Кто-нибудь знает, как добавить библиотеки для весенней загрузки, используя loader.path
или что-то подобное при запуске веб-приложения, упакованного как файл WAR?
Сфера / мой старый так lution (я не думаю, что это действительно нужно для ответа на этот вопрос)
Я использую Spring Boot для создания веб-интерфейса для другого приложения (он экспортируется в виде файла WAR
по мере необходимости использовать JSP). Веб-интерфейс имеет доступ только к библиотеке, которую может изменить другое приложение.
Другое приложение должно быть предоставлено в JAR, который я могу выбрать.
Другое приложение также необходимо работать без веб-интерфейса.
Ранее я загружал другое приложение из своего веб-приложения, используя пользовательское ClassLoader
, которое расширяет URLClassLoader
, но использует родительский ClassLoader
, если класс существует в обоих классах. loaders:
public class ParentPreferringURLClassLoader extends URLClassLoader {
public ParentPreferringURLClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try{
return getParent().loadClass(name);
}catch(ClassNotFoundException e) {
return super.loadClass(name);
}
}
}
Мне нужно было использовать это ClassLoader
, потому что я не мог приводить объекты из библиотеки из приложения
Мне не нравится это решение, потому что оно приносит следующее Основные проблемы:
- Используется версия библиотеки, предоставленная из моего веб-интерфейса. Я хочу иметь возможность изменять версию библиотеки, которую использует другое приложение, без изменения версии в библиотеке. Веб-интерфейс должен также использовать версию библиотеки (если нет конфликтов, но эти конфликты не важны для вопроса)
- Я использую Java API компилятора в моем другом приложении, и мне нужен доступ код другого приложения в нем. Кажется, что возникают проблемы при загрузке скомпилированного класса, поскольку он не включает другое приложение.
- В идеале я хочу использовать регистратор SLF4J, предоставленный другим приложением.