Принудительно настроить собственный ClassLoader для файлов WAR? - PullRequest
4 голосов
/ 20 сентября 2011

Существует ли стандартный способ (т. Е. Определенный некоторыми спецификациями Java / J2EE / и т. Д.) Предоставить пользовательский загрузчик классов в контейнер сервлетов Java, который следует использовать для загрузки файла WAR?

НаВ новом проекте мы расширяем большой коммерческий программный пакет Java (Foo) с помощью веб-сервисов, что требует некоторой гибкости развертывания (как отдельных сервисов и т. д.).В частности, мы хотим избежать необходимости включать в каждый WAR-файл все Jar-файлы зависимости от программного обеспечения Foo, поскольку они многочисленны, велики и будут меняться с выпусками исправлений / исправлений по мере разработки.Точно так же крайне нежелательно копировать все зависимости в каталог lib каждого контейнера Servlet.

В идеале я хотел бы сообщить серверу приложений Java, что эти файлы WAR должны быть загружены с использованием пользовательскогоЗагрузчик классов, который я предоставлю, который автоматически включает в себя Jar для зависимости от программного обеспечения Foo.Примерно так (в Java-псевдокоде):

public class MyWarFileClassLoader extends ClassLoader {
  protected URLClassLoader urlcl;
  public MyWarFileClassLoader(File warFile) {
    File installDir = System.getEnv("FOO_HOME");
    List<File> fooEntries = new File(installDir, "jars").listFiles("*.jar");
    fooEntries.add(new File(installDir, "resources"));
    fooEntries.add(warFile);
    this.urlcl = new URLClassLoader(fooEntries);
  }
  public Class<?> findClass(String name) {
    return this.urlcl.findClass(name);
  }
}

Если не существует стандартного способа сделать это, существует ли простой способ достижения одной и той же цели для нескольких файлов WAR,независимо от целевого контейнера сервлетов?

[Edit]

Другими словами: существует ли общая схема, позволяющая файлам WAR управлять своими собственными зависимостями во время выполнениявместо того, чтобы полагаться на конфигурацию контейнера сервлетов?Я мог бы, конечно, включить в манифест файла WAR атрибут Class-Path, но тогда записи все еще «жестко закодированы» во время сборки, а не обнаружены автоматически во время выполнения.

1 Ответ

5 голосов
/ 20 сентября 2011

Не существует стандартного способа принудительного использования определенного пользовательского загрузчика классов в приложении Java EE для загрузки классов из предопределенного источника. Однако существует возможность связывать библиотеки в приложении Java EE, чтобы несколько модулей (включая веб-модули, находящиеся в WAR) могли загружать и получать доступ к классам в связанных библиотеках.

Спецификация Java EE позволяет развертыванию приложения Enterprise (файл .ear) объединять библиотеки в каталог развертывания библиотеки; по умолчанию это каталог lib в файле .ear. Эти библиотеки могут затем использоваться несколькими веб-модулями (расположенными в разных файлах .war) в корне файла .ear. Соответствующей частью спецификации Java EE 6 является Раздел EE 8.2.1, где указано следующее:

Файл .ear может содержать каталог, содержащий библиотеки, упакованные в файлы JAR. Элемент library-directory дескриптора развертывания файла .ear содержит имя этого каталога. Если элемент library-directory не указан или файл .ear не содержит дескриптор развертывания, используется каталог с именем lib. Пустой элемент library-directory может использоваться для указания отсутствия каталога библиотеки.

Все файлы в этом каталоге (кроме подкаталогов) с расширением .jar должны быть доступны для всех компонентов, упакованных в файл EAR, включая клиенты приложений. Эти библиотеки могут ссылаться на другие библиотеки, либо связанные с приложением, либо установленные отдельно, с использованием любого из методов, описанных здесь.

Важно отметить, что все серверы приложений, совместимые с Java EE (WebLogic / WebSphere / JBoss и др.), Будут поддерживать развертывание файлов EAR с помощью связанных библиотек. Однако существуют контейнеры сервлетов (такие как Tomcat и Jetty), которые не соответствуют всей спецификации Java EE; такие контейнеры не будут поддерживать развертывание файлов EAR.

В случае, когда к библиотекам требуется доступ к нескольким веб-модулям в контейнере сервлета (либо из-за выбора контейнера, либо из-за предпочтения файлов WAR), вам следует полагаться на поддержку контейнера сервлета для общих библиотек для развертывания файлов WAR без библиотек. Спецификация Java EE не требует каких-либо требований в этой области относительно использования установленных библиотек. Некоторые контейнеры поддерживают совместно используемые библиотеки лучше, чем другие, поддерживая версионные совместно используемые библиотеки (где развернутые приложения могут использовать только одну версию из нескольких), в то время как другие (например, Tomcat) - нет.

...