在 Java EE / Spring 容器中多次使用 jul-to-slf4j 有什么影响?

What is impact of using jul-to-slf4j several times in Java EE / Spring container?

将 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 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 (author of Log4j, SLF4J and Logback) doesn't recommend installing SLF4JBridgeHandler 相乘。但是他没有解释为什么...

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

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

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

主题参考:

我提出改进文档的请求: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.

所以在 multi-application 容器环境中 jul-to-slf4j 应该是每个 JVM 的单个实例并从系统加载 类 否则你很难解释问题。

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

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

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

下一行是 JULI、Tomcat 的日志记录实现。仔细查看讨论自定义 LogManager:

的部分

The key component there is a custom LogManager implementation, that is aware of different web applications running on Tomcat (and their different class loaders). It supports private per-application logging configurations.

现在我们来看看jul-to-slf4j的源代码。这个简单但非常强大的class,开箱即用没有。要启用桥接,您必须将 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) 你记得 enahnced Tomcat 的 LogManager 允许所有应用程序具有 per-application 日志记录配置正确的?还记得 jul-to-slf4j 可以在 logging.properties 文件中启用吗?


要在enable/disablejul-to-slf4j桥接运行范围内对Tomcat单人申请你必须:

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

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