Решение для адаптации/разрешения конфликтов JAVA log framework

Java

предисловие

Вы когда-нибудь столкнулись с ситуацией, когда журнал настроен, но не может быть напечатан?

Вы когда-нибудь столкнулись с ситуацией, когда настроен вкус, но ошибка Log4j будет предложена при запуске? Как следующее:

log4j:WARN No appenders could be found for logger (org.example.App).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

Сталкивались ли вы с такой ошибкой в ​​SLF4J?

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/jiang/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/jiang/.m2/repository/org/slf4j/slf4j-log4j12/1.7.30/slf4j-log4j12-1.7.30.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

Вы когда-нибудь сталкивались с ситуацией, когда журнал DUBBO не распечатывается должным образом?

Вы когда-нибудь сталкивались с ситуацией, когда журнал Mybatis SQL не может быть распечатан?

Вы когда-нибудь сталкивались с ситуацией, когда журнал JPA/Hibernate SQL не распечатывается?

Вы когда-нибудь сталкивались с ситуацией, когда в сложном проекте нельзя распечатать множество внутренних логов фреймворка?

Вы когда-нибудь сталкивались с проектом Tomcat с несколькими копиями файла журнала, catalina.out и других файлов?

Вы столкнулись с проектом SpringBoot, файлы журнала, распечатайте несколько копий проблемы?

Вы когда-нибудь сталкивались с различными проблемами конфигурации журнала...


Конфликт фреймворка ведения журнала

Вышеупомянутые проблемы в основном вызваны сосуществованием нескольких фреймворков журналов или ошибками конфигурации. Так почему же происходит сосуществование или конфликт?

Обычно следующие причины:

  1. Проект вручную ссылается на пакеты различных фреймворков журналирования, таких как log4j/log4j2/logback/jboss-logging/jcl и т. д.
  2. Переходные зависимости инструмента управления пакетами приводят, например, к dubbo, но dubbo зависит от zkclient, но zkclient зависит от log4j. В настоящее время, если в вашем проекте существуют и используются другие среды ведения журналов, заставьте несколько наборов сосуществовать
  3. Сосуществование нескольких версий одной и той же среды ведения журнала

Различные фреймворки ведения журналов в JAVA

Прежде чем официально представить конфликты и их разрешение, нам нужно кратко рассказать о различных средах ведения журналов в Java:

В Java есть два типа фреймворков ведения журнала, а именно абстракция/фасад журнала и реализация журнала.

Бревенчатая абстракция/фасад

Журнал Аннотация / Фасад, они не несут ответственности за конкретную печать журнала, такие как вывод в файл, настроить формат содержимого журнала. Они просто абстрактный набор журналов, определяют единый набор стандартов печати журнала, таких как объект регистратора, объект уровня.

slf4j(Простой фасад ведения журнала для Java) иjcl(Журналирование Apache Commons) Эти две структуры журналов являются наиболее распространенными абстракциями журналов в JAVA. есть еще одинjboss-logging, в основном используется для программного обеспечения серии jboss, такого как спящий режим и тому подобное. рисунокjclОн не обновлялся много лет (последнее время обновления было 14 лет), наиболее рекомендуемым в настоящее время является использование slf4j.

реализация журнала

Основные фреймворки для реализации журналов в Java следующие:

  1. log4j - Apache (старая основа лесозаготовки, но она не обновлялась на протяжении многих лет, новая версия - log4j2)
  2. Log4j2 - Apache (новая версия log4j, текущая асинхронная производительность IO, простая конфигурация)
  3. logback - QOS (slf4j - продукт этой компании)
  4. jul (java.util.logging) — встроенный jdk

В программе вы можете использовать структуру журнала напрямую или использовать схему коллокации абстракции журнала + реализации журнала. Однако обычно он реализуется с помощью абстракции журнала + журнала, что является более гибким и простым в адаптации.

В настоящее время наиболее популярным решением является slf4j+logback/log4j2, но если это продукт серии jboss, в конце концов, он может использовать больше jboss-loging, сын мой. В таких фреймворках, как JPA/Hibernate, встроенным является jboss-loging.

Пример конфликта фреймворка ведения журналов SpringBoot + Dubbo

Например, наиболее распространенныйПередача зависимости коллизии сосуществования, вызванной:

Например, у меня есть «чистый» проект с весенней загрузкой, настолько чистый, что есть только одинspring-boot-starterЗависимость, на данный момент я хочу интегрировать dubbo и использовать zookeeper в качестве центра регистрации.На данный момент моя конфигурация зависимостей выглядит следующим образом:

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.7.9</version>
  </dependency>
  <dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-registry-zookeeper</artifactId>
    <version>2.7.9</version>
  </dependency>
</dependencies>

Теперь запустите этот проект с весенней загрузкой, и вы обнаружите кучу красных ошибок:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/jiang/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/jiang/.m2/repository/org/slf4j/slf4j-log4j12/1.7.30/slf4j-log4j12-1.7.30.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
----------------------------------人肉分割线----------------------------------------
log4j:WARN No appenders could be found for logger (org.apache.dubbo.common.logger.LoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

Из сообщения об ошибке содержание ошибки разделено на две части:

  1. ошибка slf4j, предполагающая, что журнал обязательно найдет больше slf4j
  2. ошибка log4j, предполагающая отсутствие конфигурации приложения log4j

Эта ошибка возникает из-за того, что транзитивная зависимость dubbo содержит log4j, а конфигурация spring-boot по умолчанию — slf4j+logback. После использования пакетов, связанных с dubbo, проект теперь существует одновременно.logback/jcl(apache commons-logging)/log4j/jul-to-slf4j/slf4j-log4j/log4j-to-slf4j

Взгляните на график зависимости:springboot-sample.png

На этот раз испортилось.slf4j-log4jЭто реализация log4j в slf4j, и функция заключается в использовании вывода log4j при вызове API slf4j; иlog4j-to-slf4jЭффект заключается вlog4jРеализация была замененаslf4j, так что это не бесконечный цикл

И существует logback, logback реализует абстракцию slf4j по умолчанию, иslf4j-log4jОн также реализует абстракцию slf4j,logback, в проекте сосуществуют два множестваslf4jреализация, затем использованиеslf4jКакая реализация будет использоваться при печати интерфейса?

Ответ «Первый», который является первым, кто будет загружен классом реализации SLF4J, но это зависит от загрузки загрузки CloseLoader CloseLoader Log Configuration, чтобы убедиться, что не летать

Если вы хотите использовать журнал в обычном режиме и позволить всем платформам в этом проекте печатать журнал в обычном режиме, вы должны унифицировать структуру журнала. Однако унификация здесь заключается не в форсировании модификации, а в использовании метода «адаптация/транзит».

Хотя сейчас в проекте есть конфигурация slf4j-log4j, эта конфигурация адаптирована под log4j2, а у нас зависимость только log4j1, по факту этот перенос недействителен. Но logback эффективен, и это конфигурация по умолчанию для проекта spring-boot.На этот раз logback выбран в качестве единой структуры ведения журнала проекта.

Теперь в проекте есть пакет log4j(1), и при запуске сообщается об ошибке log4j, указывающей на то, что какой-то код вызывает API log4j. Но мы не хотим использовать log4j, поэтому сначала нужно решить проблему с log4j.

Поскольку есть ссылки на код log4j, удалить log4j напрямую не представляется возможным. slf4j предоставляетlog4j-over-slf4jПакет, который копирует класс интерфейса log4j1 (Logger и т. д.) и изменяет класс реализации на slf4j.

Так что исключайте (переходную) зависимость log4j, при ссылкеlog4j-over-slf4jДля решения этой проблемы Log4J. Теперь, чтобы изменить зависимости в POM (см. Зависимая карта может использовать команду maven, или идея поставляется с диаграммой зависимостей Maven или плагином, который является помощником Maven)

<dependency>
  <groupId>org.apache.dubbo</groupId>
  <artifactId>dubbo-registry-zookeeper</artifactId>
  <version>2.7.9</version>
  <scope>compile</scope>
  <!--排除log4j-->
  <exclusions>
    <exclusion>
      <artifactId>log4j</artifactId>
      <groupId>log4j</groupId>
    </exclusion>
  </exclusions>
</dependency>
<!--增加log4j-slf4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
    <version>1.7.30</version>
</dependency>

После решения проблемы log4j осталась проблема двух реализаций slf4j, с которой разобраться проще. Поскольку мы планируем использовать logback, просто исключите/удалитеslf4j-log4jЭта реализация зависит от

<dependency>
  <groupId>org.apache.dubbo</groupId>
  <artifactId>dubbo-registry-zookeeper</artifactId>
  <version>2.7.9</version>
  <scope>compile</scope>
  <exclusions>
    <exclusion>
      <artifactId>log4j</artifactId>
      <groupId>log4j</groupId>
    </exclusion>
    <exclusion>
      <artifactId>slf4j-log4j12</artifactId>
      <groupId>org.slf4j</groupId>
    </exclusion>
  </exclusions>
</dependency>

После завершения модификации при повторном запуске нет ошибки, и проблема легко решается

Полная адаптация журнала

Выше представлен только метод преобразования, но с таким количеством фреймворков журналов их можно преобразовать друг в друга. Но конечной целью являетсяУнифицированная структура журналирования, так что окончательная реализация только одного набора журналов** 这么多的日志适配/转换方式,全记住肯定是有点难。为此我画了一张Возможно, это самая полная диаграмма адаптации логфрейма во всей сети (исходное изображение больше по размеру, нажмите, чтобы увеличить его), если вы снова столкнетесь с конфликтами, когда вам нужно преобразовать одну структуру ведения журналов в другую, вам нужно будет только пройти по пути, указанному на рисунке, и импортировать соответствующие пакеты зависимостей. **image.pngНапример, если вы хотите адаптировать/преобразовать slf4j в log4j2. Следуйте по пути на схеме, нужно только сослатьсяlog4j-slf4j-implВот и все.

Если вы хотите адаптировать/преобразовать jcl в slf4j, просто удалитеjclпакет, затем ссылкаjcl-over-slf4jВот и все.

Часть стрелок на картинке выделены текстом, что требует дополнительных пакетов для конвертации, а часть не выделена текстом, что является реализацией встроенной адаптации. На самом деле, встроенная реализация будет более проблематичной, потому что, если вы столкнетесь с сосуществованием, вам в основном нужно указать реализацию журнала, настроив переменные среды/настроив дополнительные свойства.

В настоящее время slf4j является основной структурой схемы адаптации, которая является центральным звеном этого графа. Пока адаптация/трансформация выполняется вокруг slf4j, нет конфликтов, с которыми нельзя было бы справиться.

Суммировать

Решить проблему сосуществования/конфликта фреймворка журнала на самом деле очень просто, просто следуйте нескольким принципам:

  1. Унифицированное использование набора реализации журнала
  2. Удалить дополнительный нежелательный журнал, зависящий от журнала
  3. Если есть ссылки, которые должны сосуществовать, затем удалить исходный пакет и используйте пакет типа «OVER» (пакет The Type копирует копию исходного интерфейса и переосмысления)
  4. Если его нельзя перезаписать, используйте указанный метод, предоставляемый абстракцией журнала, напримерjboss-logging, пройти можноorg.jboss.logging.providerПеременные среды указывают конкретную реализацию платформы ведения журналов.

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

После разрешения сосуществования/конфликта в проекте остается только одна структура ведения журнала. Больше не будет всяких отвратительных проблем типа "невозможно набрать лог", "конфигурация лога не вступает в силу", и вы сможете уйти с работы раньше!

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