Управление путём классов в сервлете

В моем приложении сервлета есть несколько библиотек .jars, некоторые из которых содержат встроенные файлы log4j.xml или log4j.properties. Я хочу, чтобы log4j сначала нашел мой log4j.xml! Я попытался найти некоторую спецификацию приоритетов различных элементов classpath в сервлете (например, WEB-INF/классы всегда предшествуют WEB-INF/lib?) Или каким-то образом настроить или настроить сервлет-загрузчик классов, чтобы данный каталог ресурсов появляется на ранней стадии пути к классам. Пока что я нарисовал пробел. Любые предложения по обеспечению того, что файл сервлета .war загружает правильный файл log4j.xml через загрузчик классов?

Ответ 1

Насколько я понимаю, выбор ресурсов из пути к классам не является детерминированным (с точки зрения разработчика приложения). Даже если один и тот же файл будет загружен последовательно, поведение может измениться:  1. Когда вы обновляете версию своего текущего контейнера.  2. Если вы переключаете контейнеры.

Простейшим решением будет удаление встроенных файлов конфигурации log4j из баннеров библиотеки. Почти никогда не рекомендуется вставлять конфигурацию log4j, поскольку она приводит к проблеме, которую вы видите здесь...

Являетесь ли вы сторонними банками или банками?

Ответ 2

Tomcat 8.5

Ditto Tomcat 8.0.

См. документацию: Класс Loader HOW-TO.

Tomcat 8.0

Ответ прост, взятый с страницы документации Tomcat, Класс Loader HOW-TO. В частности, обратите внимание на использование каталога /WEB-INF/.

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

  • Начальные классы вашей JVM
  • /WEB-INF/classes вашего веб-приложения
  • /WEB-INF/lib/*.jar вашего веб-приложения
  • Классы загрузчика системного класса (описанные выше)
  • Общие классы загрузчика классов (описанные выше)

Если загрузчик класса веб-приложения настроен с <Loader delegate="true"/>, тогда порядок будет выглядеть следующим образом:

  • Начальные классы вашей JVM
  • Классы загрузчика системного класса (описанные выше)
  • Общие классы загрузчика классов (описанные выше)
  • /WEB-INF/classes вашего веб-приложения
  • /WEB-INF/lib/*.jar вашего веб-приложения

Tomcat 6

Выдержка из страницы Tomcat 6, Класс Loader HOW-TO.

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

  • Начальные классы вашей JVM
  • Классы загрузчика системного класса (описанные выше)
  • /WEB-INF/classes вашего веб-приложения
  • /WEB-INF/lib/*.jar вашего веб-приложения
  • $CATALINA_HOME/lib
  • $CATALINA_HOME/lib/*.jar

Ответ 3

Мы Spring Log4jConfigListener в нашем файле web.xml.

В качестве параметра контекста можно указать расположение конфигурационного файла log4j, т.е. вы можете установить его как /WEB -INF/log4j.xml

Будет ли это вариантом для вас? Если вы не используете Spring, я знаю, что вы можете установить местоположение Log4j программно, что также может работать.

Ответ 4

По моему опыту, WEB-INF/классы обычно имеют приоритет над jars в WEB-INF/lib, однако это также зависит от используемого вами контейнера сервлета (я никогда не мог понять поведение JRun, например). Это очень помогло бы, если бы вы могли сказать мне, какой контейнер вы используете.

Также вы уверены, что оскорбительная конфигурация log4j находится в банке в WEB-INF/lib? Как правило, когда я сталкивался с проблемами классов в контексте контейнера сервлета, это из-за библиотек, которые находятся в вне веб-приложения.

Спецификации сервлета рекомендуют, чтобы загрузчики классов веб-приложений загружали свои собственные классы перед передачей загрузчику классов контейнеров (SRV.9.7.2), но поскольку это противоречит спецификации Java, не все производители делают это по умолчанию (на самом деле Tomcat это единственный контейнер, который я использовал, который делает это по умолчанию). С учетом сказанного всегда можно настроить поведение загрузки класса веб-приложения контейнера. Если вы скажете мне, какой контейнер вы используете, я могу помочь вам (в частности, я сделал это успешно ранее в WebLogic, WebSphere, Glassfish и JRun)).

Ответ 5

Если вы не можете контролировать путь к классам, поскольку Tomcat устанавливает его для вас, вы, по крайней мере, можете установить системное свойство для log4j.configuration? Я считаю, что местоположение, на которое указывает это свойство, может быть установлено за пределами пути к классам.

Если нет, другой подход, хотя и уродливый, должен был явно запустить один из конфигураторов самостоятельно в вашем коде приложения.

Ответ 6

В вашем CLASSPATH необходимо иметь log4j.properties. Лучшее место в разделе WEB-INF/classes.

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