Могу ли я создать собственный путь к классам для каждого приложения в Tomcat?

Для некоторых приложений я использую ZK, другие Hibernate, другие Apache Commons и т. Д.

Я не хочу развертывать файл войны размером 75 МБ, просто потому, что он использует много библиотек.

Я не хочу добавлять библиотеки в мою папку tomcat lib или путь к классам к его конфигурации, поскольку у меня может быть старое приложение, использующее библиотеку x.1, и другое приложение, использующее библиотеку x.2

По этой причине было бы здорово иметь что-то в web.xml или context.xml, где я говорю что-то вроде:

<classpath>/usr/local/tomcat/custom-libs/zk-5.0.4</classpath>

Примечание: вышеприведенный псевдокод

4 ответа

Решение

В Tomcat 7 нет упоминаний о невозможности использовать VirtualWebappLoader в работе. Я попробовал это, и это работает как сон. Просто добавьте следующее в META-INF/context.xml:

<?xml version="1.0" encoding="UTF-8"?>

<Context antiJARLocking="true" path="/websandbox">
    <Loader className="org.apache.catalina.loader.VirtualWebappLoader"
          virtualClasspath="/usr/.../*.jar;/usr/.../*.jar"/>
</Context>

В Netbeans, под упаковкой, я просто убираю галочку со всех пакетов, уменьшая размер.war, проверяю, что зависимости находятся в правильных папках на сервере, и загружаю их. Yey! Не более 100 МБ WAR-файла.

Дополнение @Spider answer.

Контекст Tomcat содержит элемент Loader. Согласно дескриптору развертывания документов (что в <Context> тег) может быть размещен в:

  • $CATALINA_BASE/conf/server.xml - bad - требуется перезапуск сервера для перечитывания конфигурации
  • $CATALINA_BASE/conf/context.xml - плохо - используется всеми приложениями
  • $CATALINA_BASE/work/$APP.war:/META-INF/context.xml - плохо - требуется переупаковка для изменения конфигурации
  • $CATALINA_BASE/work/[enginename]/[hostname]/$APP/META-INF/context.xml - приятно, но смотри последний вариант!!
  • $CATALINA_BASE/webapps/$APP/META-INF/context.xml - приятно, но смотри последний вариант!!
  • $CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml - лучше всего - полностью вне приложения и автоматически сканируется на наличие изменений!!!

Здесь мой конфиг, который демонстрирует, как использовать разрабатываемые версии файлов проекта из $CATALINA_BASE иерархия (обратите внимание, что я помещаю этот файл в src/test/resources Dir и Intruct Maven для предварительной обработки ${basedir} заполнители через pom.xml<filtering>true</filtering> поэтому после сборки в новой среде я копирую его в $CATALINA_BASE/conf/Catalina/localhost/$APP.xml):

<Context docBase="${basedir}/src/main/webapp"
         reloadable="true">
    <!-- http://tomcat.apache.org/tomcat-7.0-doc/config/context.html -->
    <Resources className="org.apache.naming.resources.VirtualDirContext"
               extraResourcePaths="/WEB-INF/classes=${basedir}/target/classes,/WEB-INF/lib=${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>
    <Loader className="org.apache.catalina.loader.VirtualWebappLoader"
            virtualClasspath="${basedir}/target/classes;${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>
    <JarScanner scanAllDirectories="true"/>

    <!-- Use development version of JS/CSS files. -->
    <Parameter name="min" value="dev"/>
    <Environment name="app.devel.ldap" value="USER" type="java.lang.String" override="true"/>
    <Environment name="app.devel.permitAll" value="true" type="java.lang.String" override="true"/>
</Context>

ОБНОВЛЕНИЕ Tomcat 8 изменить синтаксис для <Resources> а также <Loader> элементы, соответствующие части теперь выглядят так:

<Resources>
    <PostResources className="org.apache.catalina.webresources.DirResourceSet"
                   webAppMount="/WEB-INF/classes" base="${basedir}/target/classes" />
    <PostResources className="org.apache.catalina.webresources.DirResourceSet"
                   webAppMount="/WEB-INF/lib" base="${basedir}/target/${project.build.finalName}/WEB-INF/lib" />
</Resources>

Еще одна хакерская альтернатива.

Вы можете написать пользовательский загрузчик классов из 5-6 строк, который происходит от urlclassloader и просто добавляет ваши файлы пути к классам, используя метод addUrl().

Затем установите его как загрузчик класса контекста потока в коде вашего приложения.

Thread.setContextClassLoader(new CustomClassloader(path, parentClassLoader)

где обычно загружается родительский класс

Thread.getContextClassloader()

Для этого можно использовать файл META-INF/context.xml. Вы определили свой собственный WebappLoader, который загружает классы для вашего конкретного веб-приложения. Это ссылка, которую я использовал: http://tomcat.apache.org/tomcat-5.5-doc/config/loader.html (Изменить: для Tomcat 6: http://tomcat.apache.org/tomcat-6.0-doc/config/loader.html, для Tomcat 7: http://tomcat.apache.org/tomcat-7.0-doc/config/loader.html)

Также этот парень здесь, кажется, публикует решение вашей конкретной проблемы (пример включен): http://java.dzone.com/articles/extending-tomcat-webapploader

Другие вопросы по тегам