【问题标题】:What is impact of using jul-to-slf4j several times in Java EE / Spring container?在 Java EE / Spring 容器中多次使用 jul-to-slf4j 有什么影响?
【发布时间】:2016-04-01 06:07:45
【问题描述】:

将 JUL 桥接到 SLF4J 的常用指令添加到 pom.xml

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
    <version>${slf4j.version}</version>
</dependency>

添加到logback.xml:

<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/>

添加到 Spring bean:

<bean class="org.slf4j.bridge.SLF4JBridgeHandler" init-method="install"/>

请注意,我不包括:

<bean class="org.slf4j.bridge.SLF4JBridgeHandler"
      init-method="removeHandlersForRootLogger"/>

因为remove Tomcat's/JBoss's etc logging registrations。容器注册到 JUL 的一个原因 - 将控制台输出重定向到文件,但我不确定这是否属实。

Ceki(Log4j、SLF4J 和 Logback 的作者)doesn't recommend installingSLF4JBridgeHandler 相乘。但他没有解释为什么……

如果两个 webapp 同时在一个 Tomcat 中注册 SLF4JBridgeHandler.install() 会发生什么?他们有冲突吗?一个人会窃取其他人的所有日志消息吗?

com.sun.jersey.* 的 JAXB-RS 实现使用 JUL 日志记录,我希望每个应用程序重定向日志语句而不是系统 catalina.log

另一个奇怪的建议是将jul-to-slf4j.jar 放入容器的lib/ 目录中,并且不要包含在应用程序中。为什么?

主题参考

【问题讨论】:

    标签: tomcat jaxb slf4j logback java.util.logging


    【解决方案1】:

    我会说你的答案不正确(至少是最后一部分)。

    (我的回答实际上不是关于多次调用SLF4JBridgeHandler.install() 的影响,而是涵盖了您可能想要实现的场景——在Tomcat 的多个应用程序中使用jul-to-slf4j。)

    首先,您必须熟悉Tomcat's classloaders 以及它们的使用方式。主要思想是每个应用程序都有自己的类加载器,因此可以包含它自己的jul-to-slf4j.jar

    接下来是JULI,Tomcat 的日志实现。仔细看看讨论自定义LogManager的部分:

    关键组件有一个自定义的LogManager实现,即 了解在 Tomcat 上运行的不同 Web 应用程序(及其 不同的类加载器)。它支持私有的每个应用程序日志记录 配置。

    现在我们来看看jul-to-slf4j的源码。这个简单但功能非常强大的类,开箱即用,什么都不做。要启用网桥,您必须将SLF4JBridgeHandler 附加到根记录器。 Ceki 为我们提供了两种选择:

    1. 通过调用静态方法org.slf4j.bridge.SLF4JBridgeHandler.install()
    2. 通过在logging.properties 文件中指定网桥句柄。

    ad 1)方法流程如下代码:

    java.util.logging.LogManager.getLogManager().getLogger("").addHandler(new SLF4JBridgeHandler());
    

    但是,嘿,我们在 Tomcat 的宇宙中,我们不想使用那个丑陋的 java.util.logging.LogManager 经理!我们希望与 Tomcat 一起提供增强版。所以忘记这个方法,不要在 Tomcat 中调用它。

    ad 2)您还记得增强型 Tomcat 的 LogManager 允许所有应用程序具有每个应用程序的日志记录配置,对吗?还记得jul-to-slf4j 可以在logging.properties 文件中启用吗?


    要在 Tomcat 上运行的单个应用程序范围内启用/禁用 jul-to-slf4j 桥接器,您必须:

    1. jul-to-slf4j.jar 放入/app/WEB-INF/lib
    2. /app/WEB-INF/classes 中创建logging.properties 文件,内容如下:handlers=org.slf4j.bridge.SLF4JBridgeHandler

    几天来我一直在为类似的问题苦苦挣扎,这个答案涵盖了我研究的一部分。希望它可以帮助您和其他人建立由 SLF4J 负责的正确环境。

    【讨论】:

      【解决方案2】:

      我提出改进文档的请求:http://jira.qos.ch/browse/SLF4J-351

      回复是:

      There is one j.u.l.LogManager instance per JVM.
      Thus, any manipulation of it impacts the whole JVM.
      

      因此,在多应用容器环境中,jul-to-slf4j 应该是每个 JVM 的单个实例并从系统类加载,否则您将很难解释问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-13
        • 2014-05-04
        • 2021-05-26
        • 1970-01-01
        • 2014-12-31
        • 1970-01-01
        相关资源
        最近更新 更多